当前位置:   article > 正文

OpenCV C++图像处理之仿射变换与透视变换_opencv c++ 图像仿射变换

opencv c++ 图像仿射变换

1 仿射变化

仿射变换是一种线性变换,它将一个二维或三维空间中的对象(如点、图像、图形等)映射到另一个空间中,保持了一些基本的几何性质,如直线的平行性和点的共线性。仿射变换通常由矩阵乘法和向量加法组成,其一般形式如下:

\begin{bmatrix} {x_{i}}'\\ {y_{i}}' \end{bmatrix}= \begin{bmatrix} M_{11} & M_{12} &M_{13} \\ M_{21} & M_{22} & M_{23} \end{bmatrix}\cdot \begin{bmatrix} x_{i}\\ y_{i} \\ 1 \end{bmatrix}

其中,\begin{bmatrix} M_{11} & M_{12} &M_{13} \\ M_{21} & M_{22} & M_{23} \end{bmatrix}是映射矩阵。

 warpAffine()

  1. void cv::warpAffine(
  2. InputArray src,
  3. OutputArray dst,
  4. InputArray M,
  5. Size dsize,
  6. int flags = INTER_LINEAR,
  7. int borderMode = BORDER_CONSTANT,
  8. const Scalar & borderValue = Scalar()
  9. )

函数warpAffine对图像应用仿射变换,使用指定的矩阵变换源图像:

dst(x,y)=src(M_{11}x+M_{12}y+M_{13},M_{21}x+M_{22}y+M_{23})

参数

src:输入图像
dst:输出图像,大小为dsize,类型与src相同
M:2×3变换矩阵
dsize:输出图像的大小
flags:插值方法
bordermode:像素外推法
bordervalue:边界不变时使用的值,默认为0

InterpolationFlags

INTER_NEAREST:最近邻插值
INTER_LINEAR :双线性插值
INTER_CUBIC :双三次插值

......

BorderTypes

BORDER_CONSTANT:常数边界,图像边界的像素被填充成一个常数值
BORDER_REPLICATE:复制边界,图像的边界像素会被复制,也就是用最近边界上的像素值来填充边界
BORDER_REFLECT:反射边界,图像的边界像素被镜像反射,也就是边界上的像素值会像镜子一样反射到图像外部
BORDER_WRAP:环绕边界,图像的边界像素被视为环绕的,也就是当你越过图像边界时,会从另一侧的边界开始计算像素值

......

 计算二维旋转的仿射矩阵M

 getRotationMatrix2D()

  1. Mat cv::getRotationMatrix2D(
  2. Point2f center,
  3. double angle,
  4. double scale
  5. )

center:源图像中旋转的中心
angle:以度为单位的旋转角度,正值表示逆时针旋转
sacle:尺度因子

计算三对对应点的仿射变换M

 getAffineTransform()

  1. Mat cv::getAffineTransform(
  2. const Point2f src[],
  3. const Point2f dst[]
  4. )

src:源图像中三角形顶点的坐标
dst:目标图像中对应三角形顶点的坐标

 测试代码

  1. # include <iostream>
  2. # include <opencv2/opencv.hpp>
  3. using namespace std;
  4. using namespace cv;
  5. int main()
  6. {
  7. Mat img = imread("lena.jpg");
  8. // 定义用于旋转的变量
  9. Mat rotation0, img_warp0, img_warp1;
  10. // 设置旋转角度为45度
  11. double angle = 45;
  12. // 创建目标图像的尺寸
  13. Size dst_size(img.rows, img.cols); // cv::Size_<int>
  14. // 定义旋转中心点
  15. Point2f center(img.rows / 2.0, img.cols / 2.0); // cv::Point_<float>
  16. // 获取旋转矩阵,其中参数分别为旋转中心、旋转角度、缩放因子
  17. rotation0 = getRotationMatrix2D(center, angle, 1);
  18. // 对图像进行仿射变换,采用线性插值,边界填充方式为常数填充和反射填充
  19. warpAffine(img, img_warp0, rotation0, dst_size, INTER_LINEAR, BORDER_CONSTANT);
  20. warpAffine(img, img_warp1, rotation0, dst_size, INTER_LINEAR, BORDER_REFLECT);
  21. // 根据定义的三个点进行仿射变换
  22. Point2f src_points[3];
  23. Point2f dst_points[3];
  24. // 定义原始图像中的三个点
  25. src_points[0] = Point2f(0, 0);
  26. src_points[1] = Point2f(0, (float)(img.rows - 1));
  27. src_points[2] = Point2f((float)(img.cols - 1), (float)(img.rows - 1));
  28. // 定义目标图像中的三个点
  29. dst_points[0] = Point2f((float)(0, 0));
  30. dst_points[1] = Point2f((float)(img.cols - 1) * 0.1, (float)(img.rows - 1) * 0.5);
  31. dst_points[2] = Point2f((float)(img.cols - 1) * 0.8, (float)(img.rows - 1) * 0.8);
  32. // 创建仿射变换矩阵
  33. Mat rotation1, img_warp2;
  34. rotation1 = getAffineTransform(src_points, dst_points);
  35. // 对图像进行仿射变换
  36. warpAffine(img, img_warp2, rotation1, dst_size);
  37. // 显示原始图像和三个处理后的图像
  38. imshow("img", img);
  39. imshow("img_warp0", img_warp0);
  40. imshow("img_warp1", img_warp1);
  41. imshow("img_warp2", img_warp2);
  42. waitKey(0);
  43. }

运行结果

                                 原图                                                               旋转45度(黑色填充)               

                 旋转45度(反射填充)                                                      三点仿射变换

 2 透视变换

透视变换是一种线性变换,用于将图像从一种视角或透视变换到另一种视角。这通常用于校正图像中的透视畸变,例如将斜切的文档图像变换成正常的矩形形状,或者将一个平面上的物体投影到另一个平面上。一般公式如下:

\begin{bmatrix} {t_{i}x_{i}}'\\ t_{i}{y_{i}}' \\ t_{i} \end{bmatrix}= \begin{bmatrix} M_{11} & M_{12} &M_{13} \\ M_{21} & M_{22} & M_{23} \\ M_{31} & M_{32} & M_{33}\end {bmatrix}\cdot \begin{bmatrix} x_{i}\\ y_{i} \\ 1 \end{bmatrix}

其中,\begin{bmatrix} M_{11} & M_{12} &M_{13} \\ M_{21} & M_{22} & M_{23} \\ M_{31} & M_{32} & M_{33}\end {bmatrix}是映射矩阵。

warpPerspective()

函数warpPerspective对图像应用透视转换,使用指定的矩阵变换源图像:

dst(x,y)=src(\frac{M_{11}x+M_{12}y+M_{13}}{M_{31}x+M_{32}y+M_{33}},\frac{M_{21}x+M_{22}y+M_{23}}{M_{31}x+M_{32}y+M_{33}})

参数

src:输入图像
dst:输出图像,大小为dsize,类型与src相同
M:3×3变换矩阵
dsize:输出图像的大小
flags:插值方法
bordermode:像素外推法(BORDER_CONSTANT或border_replication)。
bordervalue:边界不变时使用的值,默认为0

从四对对应点计算一个透视变换M

 getPerspectiveTransform()

  1. Mat cv::getPerspectiveTransform(
  2. const Point2f src[],
  3. const Point2f dst[],
  4. int solveMethod = DECOMP_LU
  5. )

src:源图像中四个点的坐标
dst:目标图像中对应四个点的坐标
solveMethod:不用填       

测试代码

  1. # include <iostream>
  2. # include <opencv2/opencv.hpp>
  3. using namespace std;
  4. using namespace cv;
  5. int main()
  6. {
  7. Mat img = imread("test");
  8. Mat rotation0, img_warp0, img_warp1;
  9. Point2f src_points[4];
  10. Point2f dst_points[4];
  11. // 获取棋盘格的四个角点
  12. src_points[0] = Point2f(205, 107);
  13. src_points[1] = Point2f(472, 43);
  14. src_points[2] = Point2f(238, 440);
  15. src_points[3] = Point2f(607, 350);
  16. // 将这四点映射到
  17. dst_points[0] = Point2f(0, 0);
  18. dst_points[1] = Point2f(700, 0);
  19. dst_points[2] = Point2f(0, 800);
  20. dst_points[3] = Point2f(700, 800);
  21. Size dst_size(700, 800);
  22. Mat rotation, img_warp;
  23. // 得到映射矩阵
  24. rotation = getPerspectiveTransform(src_points, dst_points);
  25. warpPerspective(img, img_warp, rotation, dst_size);
  26. imshow("img", img);
  27. imshow("img_warp", img_warp);
  28. waitKey(0);

运行结果

                                                                          

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

闽ICP备14008679号