OpenCV仿射变动实现图像扭曲与旋转

打印 上一主题 下一主题

主题 1016|帖子 1016|积分 3048

目次

1. 仿射变动
2. 仿射变动的求解
3. 代码实现
3.1 图像扭曲
3.2 图像旋转
参考内容


1. 仿射变动

仿射变动是一种可以表达为乘以一个矩阵(线性变动)再加上一个向量(平移)的变动。在几何中,就是将一个向量空间举行一次线性变化并接上一个平移。
因此我们可以用仿射变化表达如下内容:

  • 旋转Rotations(线性变动,linear transformation);
  • 平移Translations(矢量加,vector addition);
  • 缩放操纵Scale operations(线性变动)。
由此可见,在图像处理当中,仿射变动本质上反映了两个图像之间的关系。
我们通常使用2×3矩阵来表现仿射变动。
对于“乘以一个矩阵”的线性变动,我们引入矩阵A:

对于加法部门(平移),我们引入矩阵B:

设待转换的二维列向量为X,转换后的向量为T,则:


思量齐次坐标和齐次矩阵更易于举行仿射几何变动,令:

二维向量X视作一个点,其齐次坐标表现为这样的列向量:

这样,我们可以借助齐次坐标,把平移变量也通过一个矩阵表现,则有:

可见矩阵M就是我们所需要的仿射变动矩阵。
2. 仿射变动的求解

参考内容通过几何方式(三角形三个极点的映射)形貌仿射变动的求解过程,我们也可以用代数知识表达,对于不共线的三点,令:


方程

其方程组情势为:

有唯一解,从而可以求出仿射矩阵M。
在OpenCV中,我们可以通过cv::getAffineTransform函数求解仿射矩阵或cv::getRotationMatrix2D,求解二维旋转矩阵。
Mat cv::getAffineTransform
(
InputArray
src,
InputArray
dst 
)

Python:
cv.getAffineTransform(
src, dst
) ->
retval

   
getRotationMatrix2D()

  
     
Mat cv::getRotationMatrix2D

(

Point2f

center,

double 

angle,

double 

scale 

)

inline


Python:

cv.getRotationMatrix2D(

center, angle, scale

) ->

retval


3. 代码实现

3.1 图像扭曲

  1. #include "opencv2/imgcodecs.hpp"
  2. #include "opencv2/highgui.hpp"
  3. #include "opencv2/imgproc.hpp"
  4. #include <iostream>
  5. using namespace cv;
  6. int main()
  7. {
  8.     // 读取图像
  9.     Mat src = imread("park.jpg");
  10.     if (src.empty())
  11.     {
  12.         std::cout << "Could not open or find the image!\n" << std::endl;
  13.         return -1;
  14.     }
  15.     // 选定三角形三个顶点
  16.     Point2f srcTri[3];
  17.     srcTri[0] = Point2f(0.f, 0.f);
  18.     srcTri[1] = Point2f(src.cols - 1.f, 0.f);
  19.     srcTri[2] = Point2f(0.f, src.rows - 1.f);
  20.     // 假定转换后的三个顶点坐标
  21.     Point2f dstTri[3];
  22.     dstTri[0] = Point2f(0.f, src.rows * 0.33f);
  23.     dstTri[1] = Point2f(src.cols * 0.55f, src.rows * 0.25f);
  24.     dstTri[2] = Point2f(src.cols * 0.35f, src.rows * 0.7f);
  25.     // 求解仿射矩阵
  26.     Mat warp_mat = getAffineTransform(srcTri, dstTri);
  27.     // 求解扭曲后的图像
  28.     Mat warp_dst;
  29.     warpAffine(src, warp_dst, warp_mat, src.size());
  30.     imshow("Warped Image", warp_dst);
  31.     waitKey(0);
  32.     return 0;
  33. }
复制代码
  1. # 图像扭曲
  2. import cv2
  3. import numpy as np
  4. # 读取图像
  5. img = cv2.imread('park.jpg')
  6. # 图像扭曲
  7. (rows, cols) = img.shape[:2]
  8. srcTri = np.array( [[0, 0], [img.shape[1] - 1, 0], [0, img.shape[0] - 1]] ).astype(np.float32)
  9. dstTri = np.array( [[0, img.shape[0]*0.33], [img.shape[1]*0.55, img.shape[0]*0.25], [img.shape[1]*0.35, img.shape[0]*0.7]] ).astype(np.float32)
  10. M = cv2.getAffineTransform(srcTri, dstTri)
  11. warped_img = cv2.warpAffine(img, M, (cols, rows))
  12. # 显示旋转后的图像
  13. cv2.imshow('Warped Image', warped_img)
  14. # 等待用户输入并关闭窗口
  15. cv2.waitKey(0)
  16. cv2.destroyAllWindows()
复制代码


3.2 图像旋转

  1. #include "opencv2/imgcodecs.hpp"
  2. #include "opencv2/highgui.hpp"
  3. #include "opencv2/imgproc.hpp"
  4. #include <iostream>
  5. using namespace cv;
  6. int main()
  7. {
  8.     // 读取图像
  9.     Mat src = imread("park.jpg");
  10.     if (src.empty())
  11.     {
  12.         std::cout << "Could not open or find the image!\n" << std::endl;
  13.         return -1;
  14.     }
  15.     // 设置旋转中心、旋转角度和缩放比例
  16.     Point center = Point(src.cols / 2, src.rows / 2);
  17.     double angle = 35;
  18.     double scale = 0.5;
  19.     // 获取旋转矩阵
  20.     Mat rot_mat = getRotationMatrix2D(center, angle, scale);
  21.     // 旋转后的图像
  22.     Mat rotated_dst;
  23.     warpAffine(src, rotated_dst, rot_mat, src.size());   
  24.     // 显示图像
  25.     imshow("Rotated Image", rotated_dst);
  26.     waitKey(0);
  27.     return 0;
  28. }
复制代码
  1. # 图像旋转
  2. import cv2
  3. # 读取图像
  4. img = cv2.imread('park.jpg')
  5. # 旋转图像
  6. (rows, cols) = img.shape[:2]
  7. M = cv2.getRotationMatrix2D((cols/2, rows/2), 35, 0.5)
  8. rotated_img = cv2.warpAffine(img, M, (cols, rows))
  9. # 显示旋转后的图像
  10. cv2.imshow('Rotated Image', rotated_img)
  11. # 等待用户输入并关闭窗口
  12. cv2.waitKey(0)
  13. cv2.destroyAllWindows()
复制代码

参考内容

OpenCV: Affine Transformations
注:OpenCV这个文档的示例代码中,C++代码和Python代码并不匹配,Python代码中的dstTri第一个点的y坐标,shape[1]应为shape[0](见本文示例代码)。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊雷无声

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表