opencv透视变换

opencv透视变换
实现透视变换
目标:
在这篇教程中你将学到:
1、如何进行透视变化
2、如何生存透视变换矩阵
理论:
什么是透视变换:
1、 透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。
2、换算公式

u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中
变换矩阵可以拆成4部分,表示线性变换,比如scaling,shearing和ratotion。用于平移,产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。

重写之前的变换公式可以得到:

所以,已知变换对应的几个点就可以求取变换公式。反之,特定的变换公式也能新的变换后的图片。简单的看一个正方形到四边形的变换:
变换的4组对应点可以表示成:

根据变换公式得到:

定义几个辅助变量:

都为0时变换平面与原来是平行的,可以得到:

不为0时,得到:

求解出的变换矩阵就可以将一个正方形变换到四边形。反之,四边形变换到正方形也是一样的。于是,我们通过两次变换:四边形变换到正方形+正方形变换到四边形就可以将任意一个四边形变换到另一个四边形。

代码:
# include  "opencv2/highgui.hpp"
# include  "opencv2/imgproc.hpp"
# include  <iostream >
# include  <stdio.h >
using  namespace  cv;
using  namespace  std;
/**  @function  main  */
int  main(  int  argc,  char * *  argv  )
{
             cv : :Mat src = cv : :imread(  "test.jpg", 0);
                  if ( !src.data)
                                  return  0;
                vector <Point > not_a_rect_shape;
                not_a_rect_shape.push_back(Point( 122, 0));
                not_a_rect_shape.push_back(Point( 814, 0));
                not_a_rect_shape.push_back(Point( 22, 540));
                not_a_rect_shape.push_back(Point( 910, 540));
                  // For debugging purposes, draw green lines connecting those points
                  // and save it on disk
                 const Point * point = &not_a_rect_shape[ 0];
                 int n = ( int )not_a_rect_shape.size();
                Mat draw = src.clone();
                polylines(draw, &point, &n, 1true, Scalar( 0, 255, 0), 3, CV_AA);
                imwrite(  "draw.jpg", draw);
                  //  topLeft, topRight, bottomRight, bottomLeft
                cv : :Point2f src_vertices[ 4];
                src_vertices[ 0] = not_a_rect_shape[ 0];
                src_vertices[ 1] = not_a_rect_shape[ 1];
                src_vertices[ 2] = not_a_rect_shape[ 2];
                src_vertices[ 3] = not_a_rect_shape[ 3];

                Point2f dst_vertices[ 4];
                dst_vertices[ 0] = Point( 0, 0);
                dst_vertices[ 1] = Point( 960, 0);
                dst_vertices[ 2] = Point( 0, 540);
                dst_vertices[ 3] = Point( 960, 540);
                Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);
                cv : :Mat rotated;
                warpPerspective(src, rotated, warpMatrix, rotated.size(), INTER_LINEAR, BORDER_CONSTANT);
                  // Display the image
                cv : :namedWindow(  "Original Image");
                cv : :imshow(  "Original Image",src);
                cv : :namedWindow(  "warp perspective");
                cv : :imshow(  "warp perspective",rotated);
                imwrite(  "result.jpg",src);
                cv : :waitKey();
                  return  0;
}
代码解释:
1、获取图片,如果输入路径为空的话程序直接退出
  cv : :Mat src = cv : :imread(  "test.jpg", 0);
                  if ( !src.data)
                                  return  0;
2、定义边界点,输入到std::vector数据结构中。注意这里的顺序如上图。
  vector <Point > not_a_rect_shape;
                not_a_rect_shape.push_back(Point( 122, 0));
                not_a_rect_shape.push_back(Point( 814, 0));
                not_a_rect_shape.push_back(Point( 22, 540));
                not_a_rect_shape.push_back(Point( 910, 540));
并将这几个点标注出来
         const Point * point = &not_a_rect_shape[ 0];
                 int n = ( int )not_a_rect_shape.size();
                Mat draw = src.clone();
                polylines(draw, &point, &n, 1true, Scalar( 0, 255, 0), 3, CV_AA);
                imwrite(  "draw.jpg", draw);
3、生成透视变换矩阵
   cv : :Point2f src_vertices[ 4];
                src_vertices[ 0] = not_a_rect_shape[ 0];
                src_vertices[ 1] = not_a_rect_shape[ 1];
                src_vertices[ 2] = not_a_rect_shape[ 2];
                src_vertices[ 3] = not_a_rect_shape[ 3];

                Point2f dst_vertices[ 4];
                dst_vertices[ 0] = Point( 0, 0);
                dst_vertices[ 1] = Point( 960, 0);
                dst_vertices[ 2] = Point( 0, 540);
                dst_vertices[ 3] = Point( 960, 540);
                Mat warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);
4、执行转换
    cv : :Mat rotated;
                warpPerspective(src, rotated, warpMatrix, rotated.size(), INTER_LINEAR, BORDER_CONSTANT);
5、显示并保存结果
        // Display the image
                cv : :namedWindow(  "Original Image");
                cv : :imshow(  "Original Image",src);
                cv : :namedWindow(  "warp perspective");
                cv : :imshow(  "warp perspective",rotated);
                imwrite(  "result.jpg",src);
结果:
原始图片
标注四个边界点
透视变换后的图片
需要注意的是,这里变化后的图像丢失了一些边界细节,这在具体实现的时候是需要注意的。



2017年4月30日09:03:03 感谢 网友 CHEN Tian-hua 指出一处错误,已经将 最后的a12修改成a23

 

目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com
优秀的个人博客,低调大师

微信关注我们

原文链接:https://yq.aliyun.com/articles/649618

转载内容版权归作者及来源网站所有!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

相关文章

发表评论

资源下载

更多资源
优质分享Android(本站安卓app)

优质分享Android(本站安卓app)

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Apache Tomcat7、8、9(Java Web服务器)

Apache Tomcat7、8、9(Java Web服务器)

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Eclipse(集成开发环境)

Eclipse(集成开发环境)

Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。

Java Development Kit(Java开发工具)

Java Development Kit(Java开发工具)

JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。