转自https://blog.csdn.net/shanghaiqianlun/article/details/52537485
1. 基本概念
1.1 基本公式
从图中我们可以得到如下关系:
r = (X – X0)/cos(α) = (Y0-Y)/sin(α)
Xn = r*cos(θ + α) + X0
=r*cos(θ)*cos(α) – r*sin(θ)*sin(α) + X0
=((X – X0)/cos(α)) * cos(θ)*cos(α) – ((Y0-Y)/sin(α)) * sin(θ)*sin(α) + X0
= (X – X0) * cos(θ) + (Y – Y0) * sin(θ)+ X0
Yn = -r*sin(θ + α) + Y0
=-r*sin(θ) * cos(α) – r*cos(θ)*sin(α) + Y0
= -(X-X0)sin(θ) + (Y-Y0)*cos(θ) + Y0
整理得到公式1:
Xn = (X – X0) * cos(θ) + (Y – Y0) * sin(θ) + X0
Yn = -(X-X0)*sin(θ) + (Y-Y0)*cos(θ) + Y0
反过来可得公式2:
X = (Xn – X0) * cos(θ) - (Yn – Y0) * sin(θ) + X0
Y = (Xn-X0) * sin(θ) + (Yn-Y0) * cos(θ) + Y0
由此得到旋转前后像素的坐标关系。可通过公式1来计算任意一个旋转前的像素在旋转后的图像中的坐标位置;利用公式2计算任意一个旋转后的像素在旋转前的图像中的坐标位置。
其中:θ,逆时针方向旋转角度
(X0,Y0)旋转中心
(X,Y)为像素在旋转前的坐标
(Xn,Yn)为旋转后该像素的坐标
按照基本公式来旋转,计算量巨大。
1.2 基于刚体旋转而得到的快速算法
为了提高旋转的运算速度,基于旋转图像是刚体运动的特点,可简化运算量。
我们考察图3,试图用A’, QL’,QR’来表示Q’。显然两个红三角形是全等的。
因此有公式4:
Xn = XR’ + (XL’ – XA’)
Yn = YR’ + (YL’ – YA’)
公式4说明,利用某一行和某一列的旋转坐标就可以计算所有像素的旋转后坐标,一般我们选AB图像的第一行,AC为图像的第一列。
例如,如果一个图像的大小是1080p(水平1920,垂直1080),图像的左上角为坐标原点,逆时针旋转θ角。
我们可以用公式四和公式一计算原始图像坐标(X,Y)的像素旋转后的新坐标(Xn,Yn)。
1) 按照公式一计算出:
a) 原始图像第一行X, (0…1919), Y=0,对应的旋转后坐标XR’(即:Xn): H(X,0)= { H(0,0)…H(1919,0) };YR’(即:Yn): V(X,0)= { V(0,0)…V(1919,0) }。
b) 原始图像第一列X= 0,Y:(0…1079)对应的旋转后坐标XL’(即:Xn) : H(0,Y) = { H(0,0)…H(0,1079) };YL’(即:Yn): V(0,Y) = { V(0,0)…V(0,1079) }。
c) XA’ = H(0,0),YA’ = V(0,0)。
2) 按照公式4,原始图像的任意一点(X,Y),旋转后的坐标为:
a) Xn = H(X,0) + ( H(0,Y) – H(0,0))
b) Yn = V(X,0) + ( V(0,Y) – V(0,0))
我们可以用公式四和公式二计算旋转后图像任意一个像素(Xn,Yn)在原始图像中的坐标(X,Y)。
3) 按照公式二计算出:
a) 旋转后图像第一行Xn, (0…1919), Yn=0,对应的在原始图像中的坐标XR’(即:X): H(Xn,0) = { H(0,0)…H(1919,0) };YR’(即:Y): V(Xn,0)= { V(0,0)…V(1919,0) }。
b) 旋转后图像第一列Xn= 0,Yn:(0…1079)对应在原始图像中的坐标XL’(即:X) : H(0,Yn) = { H(0,0)…H(0,1079) };YL’(即:Y): V(0,Yn)= { V(0,0)…V(0,1079) }。
c) XA’ = H(0,0),YA’ = V(0,0)。
4) 按照公式4,旋转后图像任意一点(Xn,Yn),在原始图像中的坐标为:
a) X = H(Xn,0) + ( H(0,Yn) – H(0,0))
b) Y = V(Xn,0) + ( V(0,Yn) –V(0,0) )
显然,我们只需计算第一行和第一列的对应关系就可以。通过简单的计算来获得任意像素的对应关系。从而提高的运算效率。
1.3 三步法
如果旋转中心为坐标原点,及X0=Y0=0,则公式二简化为:
Xn = X * cos(θ) - Y *sin(θ)
Yn= X * sin(θ) + Y*cos(θ)
写成矩阵形式,即公式五:
注意一个三角函数公式: tan(θ)= (1 - cos(θ))/sin(θ) = sin(θ)/(1+cos(θ))。将这个代入上式即可验证这个关系。
由公式五,我们可以把一次旋转看作通过三次错切变换来完成。也即三步法。
fig4: rotating 90deg, 30deg
1.4 一些特殊角度的旋转
2. 关于算法的实现问题
图4
2.1 近邻法与双线性插值法
将一个图像顺时针旋转一个角度,如图4所示。红色为显示屏幕点阵。黑色为原始图像经过顺时针旋转一个角度的图像。其对应关系由公式1和2给出。
显然公式1和2的计算结果是分数坐标,这在图4中也可以看出,如旋转后的像素(红1),在原始图像中不是一个整数坐标,而是一个分数坐标,那么(红1)像素值如何得到呢?
近邻法:取距离最近的原始图像中的像素值,及黑1像素值。
双线性法:由相邻的4个像素(黑0,1,5,6)插值而来。计算方法如图5:
图5
第一步在x方向上插值,得f(x,0)和f(x,1):
f(x,0) = (1-x)*f(0,0) + x*f(1,0)
f(x,1) = (1-x)*f(0,1) + x*f(1,1)
第二步在y方向上插值,得到结果f(x,y):
f(x,y) = (1-y)*f(x,0) + y*f(x,1)