OpenCV实现仿射变换

什么是仿射变换?

  1. 一个任意的仿射变换都能表示为 乘以一个矩阵 (线性变换) 接着再 加上一个向量 (平移).

  2. 综上所述, 我们能够用仿射变换来表示:

    1. 旋转 (线性变换)
    2. 平移 (向量加)
    3. 缩放操作 (线性变换)

    你现在可以知道, 事实上, 仿射变换代表的是两幅图之间的 关系 .

  1. 1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/imgproc/imgproc.hpp" 3 #include <iostream> 4 #include <stdio.h> 5 6 using namespace cv; 7 using namespace std; 8 9 /// 全局变量 10 char* source_window = "Source image"; 11 char* warp_window = "Warp"; 12 char* warp_rotate_window = "Warp + Rotate"; 13 14 /** @function main */ 15 int main( int argc, char** argv ) 16 { 17 Point2f srcTri[3]; 18 Point2f dstTri[3]; 19 20 Mat rot_mat( 2, 3, CV_32FC1 ); 21 Mat warp_mat( 2, 3, CV_32FC1 ); 22 Mat src, warp_dst, warp_rotate_dst; 23 24 /// 加载源图像 25 src = imread( argv[1], 1 ); 26 27 /// 设置目标图像的大小和类型与源图像一致 28 warp_dst = Mat::zeros( src.rows, src.cols, src.type() ); 29 30 /// 设置源图像和目标图像上的三组点以计算仿射变换 31 srcTri[0] = Point2f( 0,0 ); 32 srcTri[1] = Point2f( src.cols - 1, 0 ); 33 srcTri[2] = Point2f( 0, src.rows - 1 ); 34 35 dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 ); 36 dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 ); 37 dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 ); 38 39 /// 求得仿射变换 40 warp_mat = getAffineTransform( srcTri, dstTri ); 41 42 /// 对源图像应用上面求得的仿射变换 43 warpAffine( src, warp_dst, warp_mat, warp_dst.size() ); 44 45 /** 对图像扭曲后再旋转 */ 46 47 /// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵 48 Point center = Point( warp_dst.cols/2, warp_dst.rows/2 ); 49 double angle = -50.0; 50 double scale = 0.6; 51 52 /// 通过上面的旋转细节信息求得旋转矩阵 53 rot_mat = getRotationMatrix2D( center, angle, scale ); 54 55 /// 旋转已扭曲图像 56 warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() ); 57 58 /// 显示结果 59 namedWindow( source_window, CV_WINDOW_AUTOSIZE ); 60 imshow( source_window, src ); 61 62 namedWindow( warp_window, CV_WINDOW_AUTOSIZE ); 63 imshow( warp_window, warp_dst ); 64 65 namedWindow( warp_rotate_window, CV_WINDOW_AUTOSIZE ); 66 imshow( warp_rotate_window, warp_rotate_dst ); 67 68 /// 等待用户按任意按键退出程序 69 waitKey(0); 70 71 return 0; 72 }

    说明

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

      1Point2f srcTri[3]; 2Point2f dstTri[3]; 3 4Mat rot_mat( 2, 3, CV_32FC1 ); 5Mat warp_mat( 2, 3, CV_32FC1 ); 6Mat src, warp_dst, warp_rotate_dst;
    2. 加载源图像:

      src = imread( argv[1], 1 );
      
    3. 以与源图像同样的类型和大小来对目标图像初始化:

      warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
      
    4. 仿射变换: 正如上文所说, 我们需要源图像和目标图像上分别一一映射的三个点来定义仿射变换:

      1srcTri[0] = Point2f( 0,0 ); 2srcTri[1] = Point2f( src.cols - 1, 0 ); 3srcTri[2] = Point2f( 0, src.rows - 1 ); 4 5dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 ); 6dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 ); 7dstTri[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. 可选择: 缩放因子

      我们通过下面的代码来定义这些参数:

      1Point center = Point( warp_dst.cols/2, warp_dst.rows/2 ); 2double angle = -50.0; 3double 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);

本文同步分享在 博客“shiter”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

OpenCV实现仿射变换

什么是仿射变换?¶(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.opencv.org.cn%2Fopencvdoc%2F2.3.2%2Fhtml%2Fdoc%2Ftutorials%2Fimgproc%2Fimgtrans%2Fwarp_affine%2Fwarp_af

10、图像的几何变换——平移、镜像、缩放、旋转、仿射变换

1.几何变换的基本概念  图像几何变换又称为图像空间变换,它将一副图像中的坐标位置映射到另一幅图像中的新坐标位置。我们学习几何变换就是确定这种空间映射关系,以及映射过程中的变化参数。图像的几何变换改变了像素的空间位置,建立一种原图像像素与变换后图像像素之间的映射关系,通过这种映射关系能够实现下面两种计算:1.原图像任意像素