在查找cv2.getRotationMatrix2D的这个函数时,看到很多博客给都是如下的式子,自己推导了一下发现好像是错了,现在给出推导过程,如果有错欢迎评论指出
以下图为例,首先图像坐标以左上为原点,图像中的点\(v(x,y)\)逆时针转到\(v^{'}(x^{'},y^{'})\),可以得到
\(x^{'}=Rcos(\alpha -\theta )=Rcos\alpha cos\theta +Rsin\alpha sin\theta =xcos\theta +ysin\theta\)
\(y^{'}=Rsin(\alpha -\theta )=Rsin\alpha cos\theta -Rcos\alpha sin\theta =ycos\theta -xsin\theta\)
即 \(\begin{bmatrix} x^{'}\\ y^{'} \end{bmatrix}=\begin{bmatrix} cos\theta &sin\theta \\ -sin\theta &cos\theta \end{bmatrix}\begin{bmatrix} x\\ y \end{bmatrix}\)
这是图片以左上角原点的结果,实际应用中我们可以指定旋转中心,通常是图片的中心,这种情况下的做法是:
- 首先将旋转中心平移到原点
- 按上述描述的绕原点进行旋转
- 再将旋转中心平移回原来的位置
在计算机图形学中,为了统一将平移、旋转、缩放等用矩阵表示,需要引入齐次坐标。(假设使用\(2\times 2\)的矩阵,是没有办法描述平移操作的,只有引入\(3\times 3\)矩阵形式,才能统一描述二维中的平移、旋转、缩放操作。同理必须使用\(4\times 4\)的矩阵才能统一描述三维的变换)
假设旋转中心为\((tx,ty)\),将旋转中心平移到原点后,任意一点\((x,y)\)变成\((x^{'},y^{'})\)
\(x^{'}=x-tx\)
\(y^{'}=y-ty\)
由于引入了齐次坐标,在描述二维坐标的时候,使用\((x,y,w)\)的方式(一般\(w=1\)),于是上述变换可以写成如下矩阵变换的形式
\(\begin{bmatrix} x^{'}\\ y^{'}\\ 1 \end{bmatrix}=\begin{bmatrix} 1 &0 &-tx \\ 0&1 & -ty\\ 0& 0 &1 \end{bmatrix}\begin{bmatrix} x\\ y\\ 1 \end{bmatrix}\)
将旋转中心平移回原位置同理,于是整个变换过程可以表示成如下所示的矩阵
\(\begin{bmatrix} x^{'}\\ y^{'}\\ 1 \end{bmatrix}=M\begin{bmatrix} x\\ y\\ 1 \end{bmatrix}\)
\(M=\begin{bmatrix} 1 &0 &tx \\ 0 &1 &ty \\ 0&0 &1 \end{bmatrix}\begin{bmatrix} cos\theta &sin\theta &0 \\ -sin\theta &cos\theta &0 \\ 0&0 &1 \end{bmatrix}\begin{bmatrix} 1 &0 &-tx \\ 0& 1 &-ty \\ 0&0 & 1 \end{bmatrix}=\begin{bmatrix} cos\theta &sin\theta &(1-cos\theta)*tx-sin\theta*ty \\ -sin\theta&cos\theta & sin\theta*tx+(1-cos\theta)*ty\\ 0&0 &1 \end{bmatrix}\)
注意这里是左乘,因此算得时候要从右往左乘
到这里整个推导就完了,可以与第一个矩阵进行比较,其中
\(\alpha =cos\theta ,\beta =sin\theta,center_{x}=tx,center_{y}=ty\)
验证如下,其中cv2.getRotationMatrix2D第一个参数为旋转中心坐标,这里取(1,1),第二个为旋转角度取45,第三个为缩放比例,可以将这两个参数带入上面两个表达式算下并与结果对比,会发现文章最开始的那个式子是错的
import cv2
mat_rotation = cv2.getRotationMatrix2D((1, 1), 45, 1)
print(mat_rotation)
[[ 0.70710678 0.70710678 -0.41421356]
[-0.70710678 0.70710678 1. ]]
还可以参考PIL的rotate实现,会发现和上面的式子一样https://github.com/python-pillow/Pillow/blob/8dc5f692dbd9a418d8c441f0e2aa09a3f5c03508/src/PIL/Image.py#L1974
参考
Opencv:图像旋转,cv2.getRotationMatrix2D 和 cv2.warpAffine 函数_宁静致远*的博客-CSDN博客_opencv4旋转图像函数