openCV中getRotationMatrix2D和wrapAffine源码理解

更新时间:2023-06-04 12:34:13 阅读: 评论:0

openCV中getRotationMatrix2D和wrapAffine源码理解
建议阅读该博客的朋友最好对插值、matlab编程、数字图像有⼀些了解,另外所有代码和测试图⽚都可以到 去下载。在⼀次数字图像处理课中,我接触到了图⽚旋转的⼀些原理,当时没完全想明⽩,课后通过⼀段时间的学习,终于完成了图⽚旋转的matlab程序。开始觉得应该挺简单的,但终究是纸上谈兵,在实现的过程中遇到很多问题。
1 旋转矩形
urge
⾸先建议阅读 ,这篇博客可以让你很好地理解图像中的每⼀个点是如何进⾏旋转操作的。其中涉及到了图像原点与笛卡尔坐标原点之间的相互转换以及点旋转的⼀些公式推导。我们⼀般认为图像应该绕着中⼼点旋转,但是图像的原点在左上⾓,在计算的时候⾸先需要将左上⾓的原点移到图像中⼼,并且Y轴需要翻转。设⼀点 ,图像宽为 ,⾼为 ,原点变换后的点为 ,变换如下式。 图像旋转⾓度为 ,设原点变换后通过旋转矩阵旋转 后的点为 ,公式如下。 旋转后的图像的宽为 ,⾼为 ,那么从笛卡尔坐标原点变换回左上⾓的公式如下。 综上可得,原图像的⼀点 经过如下公式可以变换到旋转后的 。 同理,旋转后的⼀点 经过如下公式可以变换回原图像的 。 在开始下⼀部分之前,先要得到旋转后图像的⼤⼩,设原图像⾼为m,宽为n。代码如下,虽然看起来有点复杂,建议朋友们⾃⼰画张图看⼀下,那样会⼀⽬了然。
% image size after rotation
[m, n, o] = size(img);
下一个永远
new_m = ceil(abs(m*cosd(degree)) + abs(n*sind(degree)));
new_n = ceil(abs(n*cosd(degree)) + abs(m*sind(degree)));
2 前向映射
建议阅读 ,⾥⾯采⽤的是前向映射的⽅法。什么是前向映射呢?就是通过原图像的坐标计算旋转之后的坐标,并将相应的灰度值传给旋转后的图像。这样遇到最⼤的问题就是出现了⼀些有规律的噪声,如下图。
通过代码来分析⼀下产⽣这种现象的原因,前向映射的代码如下。m1,m2和m3这三个矩阵可以对应到公式(4)中的三个矩阵,可以看出转换后的坐标是⼩数,并且进⾏了取整操作,这样部分像素并没有对应的灰度值。中央近义词
% forward mapping matrices
m1 = [1 0 0; 0 -1 0; -0.5*n 0.5*m 1];
m2 = [cosd(degree) -sind(degree) 0; sind(degree) cosd(degree) 0; 0 0 1];
m3 = [1 0 0; 0 -1 0; 0.5*new_n 0.5*new_m 1];
for i = 1:n
for j = 1:m
new_coordinate = [i j 1]*m1*m2*m3;
col = round(new_coordinate(1));
row = round(new_coordinate(2));
% no-rotation image's coordinates to rotated image's coordinates
new_img_forward(row, col, 1) = img(j, i, 1);
new_img_forward(row, col, 2) = img(j, i, 2);
new_img_forward(row, col, 3) = img(j, i, 3);
心灵的深处end
end
3 反向映射
为了解决上述问题,可以采⽤反向映射的⽅法,即从旋转后的图像出发,找到对应的原图像的点,然后将原图像中的灰度值传递过来即可,这样旋转后的图像的每个像素肯定可以对应到原图像中的⼀个点,采取不同策略可以让像素对应地更加准确,建议⾸先阅读 以及 来更好的理解反向映射。下图可以很好地理解反向映射的过程。
下⾯代码实现了最近邻插值和双线性插值,其中rm1,rm2和rm3表⽰式(5)中的三个转换矩阵。
% rever mapping matrices
带花的古诗rm1 = [1 0 0; 0 -1 0; -0.5*new_n 0.5*new_m 1];
rm2 = [cosd(degree) sind(degree) 0; -sind(degree) cosd(degree) 0; 0 0 1];
rm3 = [1 0 0; 0 -1 0; 0.5*n 0.5*m 1];
for i = 1:new_n
for j = 1:new_m
% rotated image's coordinates to no-rotation image's coordinates
old_coordinate = [i j 1]*rm1*rm2*rm3;
col = round(old_coordinate(1));
row = round(old_coordinate(2));
% prevent border overflow
if row < 1 || col < 1 || row > m || col > n
new_img_nnp(j, i) = 0;
new_img_lp(j, i) = 0;
el
% nearest neighbor interpolation
new_img_nnp(j, i, 1) = img(row, col, 1);
new_img_nnp(j, i, 2) = img(row, col, 2);
new_img_nnp(j, i, 3) = img(row, col, 3);
% bilinear interpolation
left = floor(col);
right = ceil(col);
top = floor(row);
bottom = ceil(row);
a = col - left;
b = row - top;
new_img_lp(j, i, 1) = (1-a)*(1-b)*img(top, left, 1) + a*(1-b)*img(top, right, 1) + ...
(1-a)*b*img(bottom, left, 1) + a*b*img(bottom, right, 1);
new_img_lp(j, i, 2) = (1-a)*(1-b)*img(top, left, 2) + a*(1-b)*img(top, right, 2) + ...
(1-a)*b*img(bottom, left, 2) + a*b*img(bottom, right, 2);
new_img_lp(j, i, 3) = (1-a)*(1-b)*img(top, left, 3) + a*(1-b)*img(top, right, 3) + ...
猪仔
(1-a)*b*img(bottom, left, 2) + a*b*img(bottom, right, 3);
end
end
end
经过反向映射得到如下结果,下⾯展⽰的是反向映射+双线性插值的结果,很好的解决了前向映射出现有规律噪声的问题。
姚老师4 总结
上下联怎么贴
⽂章介绍了关于图像旋转的⼀些原理和相关的实现,从旋转矩阵开始,到前向映射,再到反向映射,反向映射中采⽤了最近邻插值和双线性插值,较好的实现了图⽚的旋转功能。建议朋友们多阅读⽂中引⽤的⼀些博客和论⽂,这样对图像旋转的很多细节会有更好的把握。

本文发布于:2023-06-04 12:34:13,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/985355.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:旋转   图像   映射
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图