【OpenCV 4开发详解】图像仿射变换
本文首发于“小白学视觉”微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究!
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。 |
接下来将要介绍图像的旋转,但是在OpenCV 4中并没有专门用于图像旋转的函数,而是通过图像的仿射变换实现图像的旋转。实现图像的旋转首先需要确定旋转角度和旋转中心,之后确定旋转矩阵,最终通过仿射变换实现图像旋转。针对这个流程,OpenCV 4提供了getRotationMatrix2D()函数用于计算旋转矩阵和warpAffine()函数用于实现图像的仿射变换。首先介绍计算旋转矩阵getRotationMatrix2D()函数,该函数的函数原型在代码清单3-31中给出。
代码清单3-31 getRotationMatrix2D()函数原型
1. Mat cv::getRotationMatrix2D (Point2f center,
2. double angle,
3. double scale
4. )
- center:图像旋转的中心位置。
- angle:图像旋转的角度,单位为度,正值为逆时针旋转。
- scale:两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1。
该函数输入旋转角度和旋转中心,返回图像旋转矩阵,该返回值得数据类型为Mat类,是一个2×3的矩阵。如果我们已知图像旋转矩阵,可以自己生成旋转矩阵而不调用该函数。该函数生成的旋转矩阵与旋转角度和旋转中心的关系如式(3.11)所示。
Rotation=[αβ(1−α)∗center.x−β∗center.y−βαβ∗center.x+(1−α)∗center.y](3.11){\rm{Rotation}} = \begin{bmatrix} \alpha & \beta & {(1 - \alpha ) * {\rm{center}}{\rm{.x}} - \beta * {\rm{center}}{\rm{.y}}}\\ - \beta &\alpha & {\beta * {\rm{center}}{\rm{.x}} + (1 - \alpha ) * {\rm{center}}{\rm{.y}}}\\ \end{bmatrix} \tag{3.11}Rotation=[α−ββα(1−α)∗center.x−β∗center.yβ∗center.x+(1−α)∗center.y](3.11)
其中:
α=scale∗cos(angle)β=scale∗sin(angle)(3.12)\begin{array}{l} \alpha = {\rm{scale}} * \cos ({\rm{angle}})\\ \beta = {\rm{scale}} * \sin ({\rm{angle}}) \end{array} \tag{3.12}α=scale∗cos(angle)β=scale∗sin(angle)(3.12)
确定旋转矩阵后,通过warpAffine()函数进行仿射变换,就可以实现图像的旋转,在代码清单3-32中给出了warpAffine()函数的函数原型。
代码清单3-32 warpAffine()函数原型
1. void cv::warpAffine(InputArray src,
2. OutputArray dst,
3. InputArray M,
4. Size dsize,
5. int flags = INTER_LINEAR,
6. int borderMode = BORDER_CONSTANT,
7. const Scalar& borderValue = Scalar()
8. )
- src:输入图像。
- dst:仿射变换后输出图像,与src数据类型相同,但是尺寸与dsize相同。
- M:2×3的变换矩阵。
- dsize:输出图像的尺寸。
- flags:插值方法标志,可选参数及含义在表3-3和表3-4中给出。
- borderMode:像素边界外推方法的标志。
- borderValue:填充边界使用的数值,默认情况下为0。
该函数拥有多个参数,但是多数都与前面介绍的图像尺寸变换具有相同的含义。函数中第三个参数为前面求取的图像旋转矩阵,第四个参数是输出图像的尺寸。函数第五个参数是仿射变换插值方法的标志,这里相比于图像尺寸变换多增加了两个类型,可以与其他插值方法一起使用,这两种类型在表3-4中给出。函数第六个参数为像素边界外推方法的标志,其可以的标志和对应的方法在表3-5中给出。第七个参数是外推标志选择BORDER_CONSTANT时的定值,默认情况下为0。
表3-4 图像仿射变换中的补充插值方法
标志参数 | 简记 | 作用 |
---|---|---|
WARP_FILL_OUTLIERS | 8 | 填充所有输出图像的像素,如果部分像素落在输入图像的边界外,那么他们的值设定为fillval |
WARP_INVERSE_MAP | 16 | 表示M为输出图像到输入图像的反变换。 |
表3-5 边界填充方法和对应标志
标志参数 | 简记 | 作用 |
---|---|---|
BORDER_CONSTANT | 0 | 用特定值填充,如iiiiii |
BORDER_REPLICATE | 1 | 两端复制填充,如aaaaaa |
BORDER_REFLECT | 2 | 倒叙填充,如fedcba |
BORDER_WRAP | 3 | 正序填充,如cdefgh |
BORDER_REFLECT_101 | 4 | 不包含边界值倒叙填充,如gfedcb |
BORDER_TRANSPARENT | 5 | 随机填充,uvwxyz |
BORDER_REFLECT101 | 4 | 与BORDER_REFLECT_101相同 |
BORDER_DEFAULT | 4 | 与BORDER_REFLECT_101相同 |
BORDER_ISOLATED | 16 | 不关心感兴趣区域之外的部分 |
在了解函数每个参数的含义之后,为了更好的理解函数作用,需要介绍一下仿射变换的概念。仿射变换就是图像的旋转、平移和缩放操作的统称,可以表示为线性变换和平移变换的叠加。仿射变换的数学表示是先乘以一个线形变换矩阵再加上一个平移向量,其中线性变换矩阵为2×2的矩阵,平移向量为2×1的向量,至此你可能理解了为什么函数需要输入一个2×3的变换矩阵。假设我们存在一个线性变换矩阵AAA 和平移矩阵BBB ,两者与输入的MMM矩阵之间的关系如式(3.13)中所示。
M=[AB]=[a00a01b0a10a11b1](3.13){M}=\begin{bmatrix} A&B\end{bmatrix}=\begin{bmatrix} {{a_{00}}}&{{a_{01}}}&{{b_{0}}}\\ {{a_{10}}}&{{a_{11}}}&{{b_{1}}} \end{bmatrix} \tag{3.13}M=[AB]=[a00a10a01a11b0b1](3.13)
根据旋转矩阵AAA 和平移矩阵BBB以及图像像素值[xy]T\begin{bmatrix} x&y \end{bmatrix}^{T}[xy]T,仿射变换的数学原理可以用式(3.14)来表示。
T=A∗[xy]+B(3.14){\bf{T}} = {\bf{A}} *\begin{bmatrix} x\\y \end{bmatrix} + {\bf{B}} \tag{3.14}T=A∗[xy]+B(3.14)
仿射变换又称为三点变换,如果知道变换前后两张图像中三个像素点坐标的对应关系,就可以求得仿射变换中的变换矩阵 ,OpenCV 4提供了利用三个对应像素点来确定 矩阵的函数getAffineTransform(),该函数的函数原型在代码清单3-33中给出。
代码清单3-33 getAffineTransform()函数原型
1. Mat cv::getAffineTransform(const Point2f src[],
2. const Point2f dst[]
3. )
- src[]:原图像中的三个像素坐标。
- dst[]:目标图像中的三个像素坐标。
该函数两个输入量都是存放浮点坐标的数组,在生成数组的时候像素点的输入顺序无关,但是需要保证像素点的对应关系,函数的返回值是一个2×3的变换矩阵。
有了前面变换矩阵的求取,就可以利用warpAffine()函数实现矩阵的仿射变换,我们在代码清单3-34的例程中实现了图像的旋转以及图像三点映射的仿射变换,最终结果在图3-23中给出。
代码清单3-34 myWarpAffine.cpp图像旋转与仿射变换
1. #include <opencv2\opencv.hpp>
2. #include <iostream>
3. #include <vector>
4.
5. using namespace std;
6. using namespace cv;
7.
8. int main()
9. {10. Mat img = imread("lena.png");
11. if (img.empty())
12. {13. cout << "请确认图像文件名称是否正确" << endl;
14. return -1;
15. }
16.
17. Mat rotation0, rotation1, img_warp0, img_warp1;
18. double angle = 30; //设置图像旋转的角度
19. Size dst_size(img.rows, img.cols); //设置输出图像的尺寸
20. Point2f center(img.rows / 2.0, img.cols / 2.0); //设置图像的旋转中心
21. rotation0 = getRotationMatrix2D(center, angle, 1); //计算放射变换矩阵
22. warpAffine(img, img_warp0, rotation0, dst_size); //进行仿射变换
23. imshow("img_warp0", img_warp0);
24. //根据定义的三个点进行仿射变换
25. Point2f src_points[3];
26. Point2f dst_points[3];
27. src_points[0] = Point2f(0, 0); //原始图像中的三个点
28. src_points[1] = Point2f(0, (float)(img.cols - 1));
29. src_points[2] = Point2f((float)(img.rows - 1), (float)(img.cols - 1));
30. //放射变换后图像中的三个点
31. dst_points[0] = Point2f((float)(img.rows)*0.11, (float)(img.cols)*0.20);
32. dst_points[1] = Point2f((float)(img.rows)*0.15, (float)(img.cols)*0.70);
33. dst_points[2] = Point2f((float)(img.rows)*0.81, (float)(img.cols)*0.85);
34. rotation1 = getAffineTransform(src_points, dst_points); //根据对应点求取仿射变换矩阵
35. warpAffine(img, img_warp1, rotation1, dst_size); //进行仿射变换
36. imshow("img_warp1", img_warp1);
37. waitKey(0);
38. return 0;
39. }
图3-23 mywarpAffine.cpp程序运行结果
OpenCV 4开发详解 |
往期推荐 |
---|
【OpenCV 4开发详解】Windows系统中安装OpenCV 4 |
【OpenCV 4开发详解】Ubuntu系统中安装OpenCV 4 |
【OpenCV 4开发详解】opencv_contrib扩展模块的安装 |
【OpenCV 4开发详解】Image Watch插件的使用 |
【OpenCV 4开发详解】安装过程中问题解决方案 |
【OpenCV 4开发详解】了解OpenCV的模块架构 |
【OpenCV 4开发详解】Mat类介绍 |
【OpenCV 4开发详解】Mat类构造与赋值 |
【OpenCV 4开发详解】4种读取Mat类元素的的方法 |
【OpenCV 4开发详解】图像的读取与显示 |
【OpenCV 4开发详解】视频加载与摄像头调用 |
【OpenCV 4开发详解】图像与视频的保存 |
【OpenCV 4开发详解】保存和读取XML和YMAL文件 |
【OpenCV 4开发详解】颜色模型与转换 |
【OpenCV 4开发详解】多通道分离与合并 |
【OpenCV 4开发详解】图像像素统计 |
【OpenCV 4开发详解】两图像间的像素操作 |
【OpenCV 4开发详解】图像二值化 |
【OpenCV 4开发详解】图像LUT查找表 |
【OpenCV 4开发详解】图像连接 |
经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持! |
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。 |
【OpenCV 4开发详解】图像仿射变换相关推荐
- 【OpenCV 4开发详解】图像膨胀
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像腐蚀
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像距离变换
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像连通域分析
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像噪声的种类与生成
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像卷积
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像直方图绘制
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像金字塔
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
- 【OpenCV 4开发详解】图像上绘制几何图形
本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...
最新文章
- LTE PUCCH F2 TX/RX汇总
- IE自动在后台运行,不知道是什么病毒?
- java比较运算_Java比较运算符
- Yahoo! UI Library入门
- 从零开始内建你的安全测试流程
- linux p 参数,tar的-p参数解决方案
- java url链接超时_Java HttpURLConnection超时和IO异常处理
- 自动驾驶 5-3 前馈速度控制 Feedforward Speed Control
- 动软连接oraclet生成代码
- 何佳佳:民生银行基于开源的运维实践
- ios下 KeyChain 的研究
- 电脑打死都连不上手机热点问题
- solr中英文分词模糊查询
- iOS 系统分享UIActivityViewController,自定义分享预览UI
- html中的colspan是什么意思
- Vue 3 中 v-if 和 v-show 指令实现的原理(源码分析)
- 马蜂窝毕博:分析完这9点工作原理,我们最终选择了 Apache SeaTunnel!
- 【人工智能实验室】第三次培训之手写数字识别代码理解
- Axure 自定义元件库
- 前端必备精美CSS样式,不来瞅瞅吗?
热门文章
- Google Duplex语气自然流利,外媒却质疑其演示通话录音是伪造的
- 人类间谍快“混”不下去了,CIA 打算用 AI 替代他们
- MySQL数据库时间类型datetime、bigint、timestamp的查询效率比较
- 稳~阿里程序员常用的 15 款开发者工具
- 一文读懂微服务架构的重构策略
- 贝叶斯机器学习:经典模型与代码实现!
- 一行代码都不写!Github 博客小白版入门教程
- 心中的象牙塔:怎样才能拿到理想的教职offer?
- 清华连续三年稳坐亚洲第一!西交利物浦成今年黑马 | 2021泰晤士亚洲大学排名...
- 斯坦福新书《决策算法》,694页PDF免费下载