图像的旋转操作底层原理
就是做图像像素点的位置变换,旋转后的位置的像素点赋值为原先像素点的值
旋转的原图像以图像左上角的顶点为原点,左上角的两条边分别为x轴和y轴建立图像坐标系。当然就算图像坐标系不是这样建立的,可以将原问题转换为这样建立图像坐标系的此问题再完成图像的图像坐标系到原问题的图像坐标系的变换
普通数学的运算
任意一点与旋转中心的连线,长度和与x轴的角度,伴随着旋转发生变化,进而计算出旋转后的位置。
1 | import cv2 |
旋转矩阵
设坐标轴ZBZ的x轴绕原点旋转θ_x,y轴绕原点旋转θ_y后变为坐标轴ZBZ’,则在坐标轴ZBZ下的点A(x,y)在坐标轴ZBZ’下的坐标表示为(x’,y’),有关系
np.matmul(np.array([[cosθ_x,sinθ_x],[-sinθ_y,cosθ_y]]),np.array([[x],[y]]))=np.array([[x’],[y’]])
np.array([[cosθ_x,sinθ_x],[-sinθ_y,cosθ_y]])就是旋转矩阵,一般情况下,坐标轴旋转的时候θ_x=θ_y
旋转矩阵的推导过程可通过三角函数和画图得出,此处不再赘述
由旋转矩阵的产生方法,我们对旋转问题进行新的构造,即旋转后的图像的图像坐标轴旋转到我们主视角的坐标轴,在旋转后的图像的图像坐标系中各个像素点的位置是正常视角的,即图像左上角的点位置坐标为(0,0),现在求这些点在新的旋转的图像坐标系(尽管来说这个“新的旋转的”才是我们的主视角)上的位置坐标,直接用旋转矩阵乘上去即可,旋转变换。
注意代码里的旋转矩阵套的θ为-da,再经过奇变偶不变,正负看象限,变换得来。
1 | import numpy as np |
两种方法的对比
旋转矩阵比元素级别的多次计算快0.2s,故整体也差不多快这么多,尤其旋转矩阵方法中A是普通数学运算方法的A和B的拼接,基本上速度差不多。
旋转矩阵方法我初始化A的时候首先采用的代码是A=np.array([[[i-cx,j-cy] for j in range(w)] for i in range(h)]),好像这样做消耗更多的性能,花费的时间至少说是最终的那行代码的三倍,体感特别差,还有A还需要转置和reshape,拖累了整体的性能,害我差点以为矩阵乘方法没有元素级别的数学运算的方法快,在众人间闹出笑话,之后测了一下,就发现问题的源头在这个初始化,因为矩阵乘比元素操作快,其他位置的运算差不多,(一开始以为把大小为2的维度从第3维挪到第1维会加快速度呢,结果没有,差不多的时间,说明索引方法差不多,没有索引维度方面的优化),那改了A的初始化,速度快了很多,比普通数学运算快了。
之前我跟着参考链接的博客学线性变换的时候,考虑过如何做图像旋转,想不明白,昨天又看它介绍旋转矩阵,不行,这次我好歹也得把这玩意搞出来,就做出来普通数学运算的方法,今天和室友的交流,以及又看了一遍博客,才想明白旋转矩阵的方法。
参考链接:旋转矩阵
创建于2023.4.6/18.35,修改于2023.4.6/18.35