图像旋转:getRotationMatrix2D详解

您所在的位置:网站首页 ai图形旋转中心点可以变化吗 图像旋转:getRotationMatrix2D详解

图像旋转:getRotationMatrix2D详解

2023-08-31 05:48| 来源: 网络整理| 查看: 265

使用opencv对图像进行旋转的代码随手一搜即得,但是有些旋转后图像会不完整,有些只给出代码并未解释其实现原理。本文会详细介绍如何使用opencv实现图像旋转得到完整图像,以及其中的实现原理。

最终实现效果:

1. getRotationMatrix2D详解

opencv的getRotationMatrix2D函数可以获取旋转变换矩阵。输入中心点坐标(centerX,centerY),旋转角度\theta,缩放比例,给出M变换矩阵

\begin{bmatrix} cos\theta & -sin\theta & (1-cos\theta)*centerX+sin\theta*centerY \\ sin\theta & cos\theta & (1-cos\theta)*centerY-sin\theta*centerX \\ 0 & 0 & 1 \end{bmatrix} \

那这个矩阵到底如何计算得到的呢?

我们先对一个点基于原点进行旋转,如下图,将V1点逆时针旋转\theta角度到V2点,缩放比例我们先假定为1.

V1点和原点连线与水平线夹角a,V2点和原点连线与水平线夹角b=a+\theta。计算旋转变换矩阵

记V1 =(x1, y1),V2 = (x2, y2)

那么

x1 = cosa

y1 = sina

x2 = cos(a + \theta) = cos\theta*cosa - sina*sin\theta

y2 = sin(a + b) = sina*cos\theta + cosa*sin\theta

将x1,y1带入

x2=x1cos\theta-y1sin\theta

y2=y1cos\theta + x1sin\theta = x1sin\theta + y1cos\theta

输出矩阵形式

\begin{bmatrix} x2 \\ y2 \end{bmatrix} = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{bmatrix} * \begin{bmatrix} x1 \\ y1 \end{bmatrix}

但是通常我们会基于中心点进行旋转,如果是需要绕任意点(tx,ty)旋转,我们可以

1.先把旋转点平移到原点

2.然后进行以上旋转操作

3.按1的逆操作平移回去

就可以得到绕任意点旋转点变换矩阵:

以上就是旋转矩阵M的由来。

2. warpAffine操作

2.1 获取M矩阵

得到变换矩阵M,对图像每个点进行M变换就可以得到旋转后的图像,这一步可以通过opencv的warpAffine得到。但是通过以上操作,旋转后大图像会丢失信息,如下图所示:

2.2 扩大画布

画布大小不变的情况下,会有一部分图像超出,显示不全,所以我们需要将画布扩大为:

新的高由图片中两段蓝色线组合

new\_H = int(w * fabs(sin(radians(angle))) + h * fabs(cos(radians(angle))))

新的宽由图片中两段红色线组合

new\_W = int(h * fabs(sin(radians(angle))) + w * fabs(cos(radians(angle))))

新的画布扩大是基于原图左上角点扩大,显示的还是蓝色区域,同样丢失了信息。

2.3 平移图像

我们还需要将红色区域进行平移操作显示到蓝色区域

所以,在变换矩阵M上,我们可以调整平移参数:

M[0, 2]+= (new\_W - w) / 2

M[1, 2] += (new\_H - h) / 2

通过以上操作就可以显示出文章最初到效果了。

最后附上使用opencv进行图像旋转并且不丢失信息到完整代码:

def opencv_rotate(img, angle): h, w = img.shape[:2] center = (w / 2, h / 2) scale = 1.0 # 2.1获取M矩阵 """ M矩阵 [ cosA -sinA (1-cosA)*centerX+sinA*centerY sinA cosA -sinA*centerX+(1-cosA)*centerY ] """ M = cv2.getRotationMatrix2D(center, angle, scale) # 2.2 新的宽高,radians(angle) 把角度转为弧度 sin(弧度) new_H = int(w * fabs(sin(radians(angle))) + h * fabs(cos(radians(angle)))) new_W = int(h * fabs(sin(radians(angle))) + w * fabs(cos(radians(angle)))) # 2.3 平移 M[0, 2] += (new_W - w) / 2 M[1, 2] += (new_H - h) / 2 rotate = cv2.warpAffine(img, M, (new_W, new_H), borderValue=(0, 0, 0)) return rotate


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3