OpenCV实现仿射变换

什么是仿射变换?

?

  1. 一个随意的仿射变换都能表示为 乘以一个矩阵 (线性变换) 接着再 加上一个向量 (平移).
  2. 综上所述, 我们可以用仿射变换来表示:
    1. 旋转 (线性变换)
    2. 平移 (向量加)
    3. 缩放操作 (线性变换)

    你如今能够知道, 其实, 仿射变换代表的是两幅图之间的 关系 .

    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include <iostream>
    #include <stdio.h>
    
    using namespace cv;
    using namespace std;
    
    /// 全局变量
    char* source_window = "Source image";
    char* warp_window = "Warp";
    char* warp_rotate_window = "Warp + Rotate";
    
    /** @function main */
     int main( int argc, char** argv )
     {
       Point2f srcTri[3];
       Point2f dstTri[3];
    
       Mat rot_mat( 2, 3, CV_32FC1 );
       Mat warp_mat( 2, 3, CV_32FC1 );
       Mat src, warp_dst, warp_rotate_dst;
    
       /// 载入源图像
       src = imread( argv[1], 1 );
    
       /// 设置目标图像的大小和类型与源图像一致
       warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
    
       /// 设置源图像和目标图像上的三组点以计算仿射变换
       srcTri[0] = Point2f( 0,0 );
       srcTri[1] = Point2f( src.cols - 1, 0 );
       srcTri[2] = Point2f( 0, src.rows - 1 );
    
       dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 );
       dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 );
       dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 );
    
       /// 求得仿射变换
       warp_mat = getAffineTransform( srcTri, dstTri );
    
       /// 对源图像应用上面求得的仿射变换
       warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
    
       /** 对图像扭曲后再旋转 */
    
       /// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵
       Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );
       double angle = -50.0;
       double scale = 0.6;
    
       /// 通过上面的旋转细节信息求得旋转矩阵
       rot_mat = getRotationMatrix2D( center, angle, scale );
    
       /// 旋转已扭曲图像
       warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );
    
       /// 显示结果
       namedWindow( source_window, CV_WINDOW_AUTOSIZE );
       imshow( source_window, src );
    
       namedWindow( warp_window, CV_WINDOW_AUTOSIZE );
       imshow( warp_window, warp_dst );
    
       namedWindow( warp_rotate_window, CV_WINDOW_AUTOSIZE );
       imshow( warp_rotate_window, warp_rotate_dst );
    
       /// 等待用户按随意按键退出程序
       waitKey(0);
    
       return 0;
      }
    

    说明?

    1. 定义一些须要用到的变量, 比方须要用来储存中间和目标图像的Mat和两个须要用来定义仿射变换的二维点数组.

      Point2f srcTri[3];
      Point2f dstTri[3];
      
      Mat rot_mat( 2, 3, CV_32FC1 );
      Mat warp_mat( 2, 3, CV_32FC1 );
      Mat src, warp_dst, warp_rotate_dst;
      
    2. 载入源图像:
      src = imread( argv[1], 1 );
      
    3. 以与源图像相同的类型和大小来对目标图像初始化:
      warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
      
    4. 仿射变换: 正如上文所说, 我们须要源图像和目标图像上分别一一映射的三个点来定义仿射变换:
      srcTri[0] = Point2f( 0,0 );
      srcTri[1] = Point2f( src.cols - 1, 0 );
      srcTri[2] = Point2f( 0, src.rows - 1 );
      
      dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 );
      dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 );
      dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 );
      

      你可能想把这些点绘出来以获得对变换的更直观感受. 他们的位置大概就是在上面图例中的点的位置 (原理部分). 你会注意到由三点定义的三角形的大小和方向改变了.

    5. 通过这两组点, 我们可以使用OpenCV函数 getAffineTransform 来求出仿射变换:
      warp_mat = getAffineTransform( srcTri, dstTri );
      

      我们获得了用以描写叙述仿射变换的 2X3 矩阵 (在这里是 warp_mat)

    6. 将刚刚求得的仿射变换应用到源图像
      warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
      

      函数有下面參数:

      • src: 输入源图像
      • warp_dst: 输出图像
      • warp_mat: 仿射变换矩阵
      • warp_dst.size(): 输出图像的尺寸

      这样我们就获得了变换后的图像! 我们将会把它显示出来. 在此之前, 我们还想要旋转它...

    7. 旋转: 想要旋转一幅图像, 你须要两个參数:
      1. 旋转图像所要环绕的中心
      2. 旋转的角度. 在OpenCV中正角度是逆时针的
      3. 可选择: 缩放因子

      我们通过以下的代码来定义这些參数:

      Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );
      double angle = -50.0;
      double scale = 0.6;
      
    8. 我们利用OpenCV函数 getRotationMatrix2D 来获得旋转矩阵,
      这个函数返回一个 2X3  矩阵 (这里是 rot_mat)

      rot_mat = getRotationMatrix2D( center, angle, scale );
      
    9. 如今把旋转应用到仿射变换的输出.
      warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );
      
    10. 最后我们把仿射变换和旋转的结果绘制在窗口中,源图像也绘制出来以作參照:
      namedWindow( source_window, CV_WINDOW_AUTOSIZE );
      imshow( source_window, src );
      
      namedWindow( warp_window, CV_WINDOW_AUTOSIZE );
      imshow( warp_window, warp_dst );
      
      namedWindow( warp_rotate_window, CV_WINDOW_AUTOSIZE );
      imshow( warp_rotate_window, warp_rotate_dst );
      
    11. 等待用户退出程序
      waitKey(0);
时间: 2024-10-09 10:40:55

OpenCV实现仿射变换的相关文章

【OpenCV新手教程之十八】OpenCV仿射变换 &amp;amp; SURF特征点描写叙述合辑

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/33320997 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 知乎:http://www.zhihu.com/people/mao-xing-yun 邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本号: 2.4.9 本篇文章中.我们一起探讨了OpenCV

【OpenCV入门教程之十八】OpenCV仿射变换 &amp; SURF特征点描述合辑

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/33320997 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 知乎:http://www.zhihu.com/people/mao-xing-yun 邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本: 2.4.9 本篇文章中,我们一起探讨了OpenCV中

对图像的仿射变换

仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间 线性变换包含了平移,缩放,旋转,镜像,斜切,正交投影,线性变换在几何上可能造成拉伸但是不会直线不会出现弯折. 在OpenCV里仿射变换通过一个2x3的矩阵来表示,前面两列表示旋转.缩放.斜切.镜像等,后面两列表示x,y方向平移 下面我们来通过仿射变换来实现图像的平移.缩放.旋转 平移:(向X轴方向平移100像素) 只平移的话,前面两列单位矩阵,后面一列数据(100,0) 缩放:(x轴缩放0.3

EasyPR--开发详解

我正在做一个开源的中文车牌识别系统,Git地址为:https://github.com/liuruoze/EasyPR. 我给它取的名字为EasyPR,也就是Easy to do Plate Recognition的意思.我开发这套系统的主要原因是因为我希望能够锻炼我在这方面的能力,包括C++技术.计算机图形学.机器学习等.我把这个项目开源的主要目的是:1.它基于开源的代码诞生,理应回归开源:2.我希望有人能够一起协助强化这套系统,包括代码.训练数据等,能够让这套系统的准确性更高,鲁棒性更强等等

EasyPR--开发详解(5)颜色定位与偏斜扭转

转自https://www.cnblogs.com/subconscious/p/4351007.html 让我们先看一下示例图片,这幅图片中的车牌通过颜色的定位法进行定位并从偏斜的视角中扭正为正视角(请看右图的左上角). 图1 新版本的定位效果 下面内容会对这两个特性的实现过程展开具体的介绍.首先介绍颜色定位的原理,然后是偏斜扭正的实现细节. 由于本文较长,为方便读者,以下是本文的目录: 一.颜色定位 1.1起源 1.2方法 1.3不足与改善 二.偏斜扭正 2.1分析 2.2ROI截取 2.3

OpenCV仿射变换+投射变换+单应性矩阵

本来想用单应性求解小规模运动的物体的位移,但是后来发现即使是很微小的位移也会带来超级大的误差甚至错误求解,看起来这个方法各种行不通,还是要匹配知道深度了以后才能从三维仿射变换来入手了,纠结~ estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切变. getAffineTransform():计算3个二维点对之间的仿射变换矩阵H(2行x3列),自由度为6. warpAffine():对输入图像进行仿射

OpenCV探索之路(八):重映射与仿射变换

重映射 重映射就是把一幅图像中某个位置的像素放置到另一个图片中指定位置的过程. 用一个数学公式来表示就是: 其中的 f 就是映射方式,也就说,像素点在另一个图像中的位置是由 f 来计算的. 在OpenCV中,用的是remap函数实现重映射. 基本重映射 #include <iostream> #include <opencv2\opencv.hpp> #include <opencv2\imgproc\imgproc.hpp> #include <opencv2\

Opencv图像识别从零到精通(30)---重映射,仿射变换

一.序言 面对图像处理的时候,我们会旋转缩放图像,例如前面所提高的resize 插值改变,也是几何变换: 几何运算需要空间变换和灰度级差值两个步骤的算法,像素通过变换映射到新的坐标位置,新的位置可能是在几个像素之间,即不一定为整数坐标.这时就需要灰度级差值将映射的新坐标匹配到输出像素之间.最简单的插值方法是最近邻插值,就是令输出像素的灰度值等于映射最近的位置像素,该方法可能会产生锯齿.这种方法也叫零阶插值,相应比较复杂的还有一阶和高阶插值. 除了插值算法感觉只要了解就可以了,图像处理中比较需要理

OpenCV仿射变换 &amp; SURF特征点描述合辑

OpenCV仿射变换 & SURF特征点描述合辑 转载地址:http://blog.csdn.net/poem_qianmo/article/details/33320997?utm_source=tuicool&utm_medium=referral