当前位置:   article > 正文

OpenCV4 详解仿射变换和透视变换和C++实现_opencv parallel perspective

opencv parallel perspective

作者:RayChiu_Labloy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处


目录

 2D图像变换包括:

仿射变换和透视变换区别:

 仿射变换:

 使用场景:

原理: 

平移、旋转、缩放和翻转等对应的仿射变换矩阵:

平移:

 旋转:

 翻转:

 缩放:

 刚体变换:

 相似变换:

 总结:

相关函数:

C++ 实现: 

 透视(投影)变换:

 使用场景:

 原理:

 相关函数:

C++实现:

python实现仿射变换和透视变换:


 2D图像变换包括:

  1. 基于2×3矩阵的仿射变换
  2. 基于3×3矩阵透视变换

仿射变换和透视变换区别:

        仿射变换后平行四边形的各边仍操持平行,透视变换结果允许是梯形等四边形,所以仿射变换是透视变换的子集 

 仿射变换:

 使用场景:

  1. 平移
  2. 旋转
  3. 缩放
  4. 错切(类似矩形变平行四边形)
  5. 翻转 

原理: 

其实就是二维坐标的变换:从一种二维坐标(x,y)到另一种二维坐标(u,v)线性变换 

如果写成矩阵的形式,就是: 

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

我们作如下定义:

        矩阵 T (2×3)  就称为仿射变换的 变换矩阵 R 为线性变换矩阵 为平移矩阵,简单来说, 仿射变换就是线性变换+平移 。变换后直线依然是直线平行线依然是平行线,直线间的相对位置关系不变,因此 非共 线的 三个对应点 便可确定唯一的一个仿射变换 ,线性变换 4 个自由度 + 平移 2 个自由度  →  仿射变换自由度 6(6个自由度可理解为线性变换的4个参数和平移2个参数)  

平移、旋转、缩放和翻转等对应的仿射变换矩阵:

其实平移、旋转、缩放和翻转等变换就是对应了不同的仿射变换矩阵,下面分别来看下。

平移:

 平移就是xy方向上的直接移动,可以上下 ty /左右 tx 移动,自由度为2,变换矩阵可以表示为:

 旋转:

旋转是坐标轴方向饶原点旋转一定的角度θ,自由度为1,不包含平移,如顺时针旋转可以表示为:

 翻转:

翻转是 x y 某个方向或全部方向上取反,自由度为 2 ,比如这里以垂直翻转为例:

 缩放:

        缩放是x y 方向的尺度(倍数)变换,在有些资料上非等比例的缩放也称为拉伸 / 挤压,等比例缩放自由度为1 ,非等比例缩放自由度为 2 ,矩阵可以表示为:

 刚体变换:

就是平移、旋转和翻转的组合,图像变换前后两点间的距离仍然保持不变,自由度为3(夹角、tx、ty)。变换矩阵可以表示为:

 相似变换:

 就是刚体变换的基础上加了缩放,所以并不会保持欧氏距离不变,但直线间的夹角依然不变。自由度为4(缩放比例、旋转角度、x和y向平移量)若缩放比例为scale,旋转角度为θ,旋转中心是$ (center_x,center_y) $,则仿射变换可以表示为:

 其中:

 总结:

相关函数:

cvWrapAffine(src,dst,mat) 

C++ 实现: 

  1. //仿射变换—平移,旋转,缩放,翻转,错切
  2. #include "stdafx.h"
  3. #include<opencv2/opencv.hpp>
  4. #include<iostream>
  5. #include<math.h>
  6. using namespace cv;
  7. using namespace std;
  8. int main(int argc, char* argv) {
  9. Mat src, dst;
  10. src = imread("C:/Users/59235/Desktop/image/girl5.jpg");
  11. if (!src.data) {
  12. printf("could not load image...\n");
  13. return -1;
  14. }
  15. namedWindow("original image", CV_WINDOW_AUTOSIZE);
  16. imshow("original image", src);
  17. Mat dst_warp, dst_warpRotateScale, dst_warpTransformation, dst_warpFlip;
  18. Point2f srcPoints[3];//原图中的三点 ,一个包含三维点(x,y)的数组,其中x、y是浮点型数
  19. Point2f dstPoints[3];//目标图中的三点
  20. //第一种仿射变换的调用方式:三点法
  21. //三个点对的值,上面也说了,只要知道你想要变换后图的三个点的坐标,就可以实现仿射变换
  22. srcPoints[0] = Point2f(0, 0);
  23. srcPoints[1] = Point2f(0, src.rows);
  24. srcPoints[2] = Point2f(src.cols, 0);
  25. //映射后的三个坐标值
  26. dstPoints[0] = Point2f(0, src.rows*0.3);
  27. dstPoints[1] = Point2f(src.cols*0.25, src.rows*0.75);
  28. dstPoints[2] = Point2f(src.cols*0.75, src.rows*0.25);
  29. Mat M1 = getAffineTransform(srcPoints, dstPoints);//由三个点对计算变换矩阵
  30. warpAffine(src, dst_warp, M1, src.size());//仿射变换
  31. //第二种仿射变换的调用方式:直接指定角度和比例
  32. //旋转加缩放
  33. Point2f center(src.cols / 2, src.rows / 2);//旋转中心
  34. double angle = 45;//逆时针旋转45
  35. double scale = 0.5;//缩放比例
  36. Mat M2 = getRotationMatrix2D(center, angle, scale);//计算旋转加缩放的变换矩阵
  37. warpAffine(src, dst_warpRotateScale, M2, Size(src.cols, src.rows), INTER_LINEAR);//仿射变换
  38. //仿射变换—平移
  39. Point2f srcPoints1[3];
  40. Point2f dstPoints1[3];
  41. srcPoints1[0] = Point2i(0, 0);
  42. srcPoints1[1] = Point2i(0, src.rows);
  43. srcPoints1[2] = Point2i(src.cols, 0);
  44. dstPoints1[0] = Point2i(src.cols / 3, 0);
  45. dstPoints1[1] = Point2i(src.cols / 3, src.rows);
  46. dstPoints1[2] = Point2i(src.cols + src.cols / 3, 0);
  47. Mat M3 = getAffineTransform(srcPoints1, dstPoints1);
  48. warpAffine(src, dst_warpTransformation, M3, Size(src.cols + src.cols / 3, src.rows));
  49. //仿射变换—翻转、镜像
  50. Point2f srcPoints2[3];
  51. Point2f dstPoints2[3];
  52. srcPoints2[0] = Point2i(0, 0);
  53. srcPoints2[1] = Point2i(0, src.rows);
  54. srcPoints2[2] = Point2i(src.cols, 0);
  55. dstPoints2[0] = Point2i(src.cols, 0);
  56. dstPoints2[1] = Point2i(src.cols, src.rows);
  57. dstPoints2[2] = Point2i(0, 0);
  58. Mat M4 = getAffineTransform(srcPoints2, dstPoints2);
  59. warpAffine(src, dst_warpFlip, M4, Size(src.cols, src.rows));
  60. //flip(src, dst_warpFlip, 1);// flipCode:= 0 图像向下翻转
  61. //> 0 图像向右翻转
  62. //< 0 图像同时向下向右翻转
  63. imshow("affine transformation1(三点法)", dst_warp);
  64. imshow("affine transfoemation2(指定比例和角度)", dst_warpRotateScale);
  65. imshow("affine transfoemation3(仿射变换平移)", dst_warpTransformation);
  66. imshow("affine transformation4(仿射变换镜像)", dst_warpFlip);
  67. waitKey(0);
  68. return 0;
  69. }

 透视(投影)变换:

 使用场景:

        将2D矩阵图像变换成3D的空间显示效果,全景拼接 。

 原理:

         前面仿射变换后依然是平行四边形,并不能做到任意的变换。

        透视变换(Perspective Transformation)是将二维的图片投影到一个三维视平面上,然后再转换到二维坐标下,所以也称为投影映射(Projective Mapping)。简单来说就是 二维(x,y) →三维(X,Y,Z)→二维(x’,y’) 的一个过程。

 齐次矩阵的形式:

 其中a1、b1、a2、b2表示线性变换,a3、b3产生透视变换,c1、c2、c3是平移变换。

 接下来再通过除以Z轴转换成二维坐标:

        透视变换相比仿射变换更加灵活,变换后会产生一个新的四边形,但不一定是平行四边形,所以需要非共线的四个点才能唯一确定,原图中的直线变换后依然是直线。因为四边形包括了所有的平行四边形,所以透视变换包括了所有的仿射变换。

 相关函数:

 cvWrapPerspective(src,dst,mat)

C++实现:

  1. #include <iostream>
  2. #include <opencv.hpp>
  3. using namespace std;
  4. using namespace cv;
  5. Mat PerspectiveTrans(Mat src, Point2f* scrPoints, Point2f* dstPoints)
  6. {
  7. Mat dst;
  8. Mat Trans = getPerspectiveTransform(scrPoints, dstPoints);
  9. warpPerspective(src, dst, Trans, Size(src.cols, src.rows), CV_INTER_CUBIC);
  10. return dst;
  11. }
  12. void main()
  13. {
  14. Mat I = imread("1.jpg"); //700*438
  15. Point2f AffinePoints0[4] = { Point2f(100, 50), Point2f(100, 390), Point2f(600, 50), Point2f(600, 390) };
  16. Point2f AffinePoints1[4] = { Point2f(200, 100), Point2f(200, 330), Point2f(500, 50), Point2f(600, 390) };
  17. Mat dst_perspective = PerspectiveTrans(I, AffinePoints0, AffinePoints1);
  18. for (int i = 0; i < 4; i++)
  19. {
  20. circle(I, AffinePoints0[i], 2, Scalar(0, 0, 255), 2);
  21. circle(dst_perspective, AffinePoints1[i], 2, Scalar(0, 0, 255), 2);
  22. }
  23. imshow("origin", I);
  24. imshow("perspective", dst_perspective);
  25. waitKey();
  26. }

 效果:

python实现仿射变换和透视变换:

请看我的另外一篇文章:opencv-python 实现仿射变换和透视变换_RayChiu757374816的博客-CSDN博客

【如果对您有帮助,交个朋友给个一键三连吧,您的肯定是我博客高质量维护的动力!!!】 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/100349?site
推荐阅读
相关标签
  

闽ICP备14008679号