1. 目的
把一副图片顺时针旋转任意角度θ。
2. 分析
假设有如下(w*h)大小的图片,用黑色坐标系标注,原图在该坐标系下的各点也用黑色标识。
在数字图像处理中,一副图片默认的原点是左上角的端点,例如原图中的O点。如果用该点为对称点进行旋转,则在旋转角度过大的情形下,会使旋转后的图片大部分甚至全部都落在当前区域之外,由此造成区域的重新计算,以及映射坐标的重新计算。例如,如果将原图以O作为对称点进行顺时针旋转90度,则整个图片已经全部处于当前区域之外,当然,可以通过三角计算得出各顶点的坐标,但是为了得到最终的结果,还是要进行坐标平移,平移之后还要进行新顶点坐标的计算,不过并不能说明不可行,只是步骤不够简洁。为了避免过于复杂的区域和映射坐标的计算,将图片的对称中心移至O’(h/2,w/2)处,以该点作为对称中心进行图片旋转,无论以多大角度进行操作,四个顶点坐标仍然大致处于一个“可控”范围内。
图1. 坐标系变换
假设有点P(a,b)在旧坐标系下,把其坐标变换到新坐标系下的P(x,y),在此假设下,x表示该点所在的高度,y表示该点所在的宽度,变换公式为(1)。
(1)
假设在新坐标系下有点P(x,y),如图2所示。
图2. 直角坐标系下的某点P(x,y)
则该点在极坐标下的坐标为公式(2)。
(2)
如果把该点沿顺时针旋转θ度,则可以得到P’(x’,y’)为公式(3)。
(3)
改写为矩阵乘法的形式,得到公式(4)。
(4)
那么在新坐标系下,原图的左上P1(-h/2,-w/2),右上P2(-h/2,w/2),左下P3(h/2,-w/2),右下P4(h/2,w/2)沿顺时针旋转θ角度后的新点分别假设为P1’(x1,y2),P2’(x2,y2),P3’(x3,y3)和P4’(x4,y4)。
由上面的坐标变换公式(4)可以得到四个新点的坐标分别为公式(5)-(8)。
(5)
(6)
(7)
(8)
把到现在为止的步骤都叠加在一张图片中,得到图3。
图3. 旋转前图为黑色,旋转后为黄色
根据图中旋转后的图形区域,可以得到旋转后图形的外接矩形的宽w’和高h’为公式(9)。
(9)
最后推导原直角坐标系下的点P(a,b)和平移旋转后的最终位置点P’(x’,y’)之间坐标值的数量关系,根据(1)和(4),可以得到以下关系为公式(10)。
(10)
(10)简化可以得到公式(11)。
(11)
公式(11)是一个从原图映射到旋转后的最终结果图的数量关系。
直接使用公式(11)就可以进行图像旋转的操作,不过同时也可以看出这里有一个问题,因为图像的坐标都是整型,而上面的公式中有浮点操作,当然即使没有浮点操作也会有这个问题,所以无法保证用原图的坐标在运算后覆盖所有新图中的坐标,所以在这种映射关系下,会造成结果图像内容中出现很多背景色的槽点。
为了解决公式(11)造成的槽点问题,需要把映射关系换一下,也就是将新图中的坐标映射到旋转前的旧图中,但是这样也会有问题,原因也是浮点操作取整的结果,也就是映射后的点可能对应旧图中的几个点,采用权重的办法取最合适的点解决这个问题。公式(12)就是从新图中的坐标映射到旧图的推导关系。
(12)
3. 实验效果图
图4是旋转操作前的原图。
图4. 旋转前的图片
图5是使用公式(11)进行旋转操作后的图,放大后可以看到图片区域中有许多背景颜色的槽点。
图5. 使用公式(11)顺时针旋转65度的图
图6是使用公式(12)进行旋转操作后的图片,可以看到整体效果比图5好了很多。
图6. 使用公式(12)顺时针旋转65度的图
4. 总结
总体来说,图像的操作其实都是数学和计算机的结合,物理偶尔会出现一下,公式的推导还是需要一点细心的,多使用矩阵乘法的形式来表示方程组可以使得公式看起来更加直观。
使用公式(11)进行操作的代码可以参考GitHub;
使用公式(12)进行操作的代码可以参考GitHub。