前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图像旋转:getRotationMatrix2D详解--无损失旋转图片

图像旋转:getRotationMatrix2D详解--无损失旋转图片

原创
作者头像
languageX
发布2021-03-06 20:20:04
23.2K3
发布2021-03-06 20:20:04
举报
文章被收录于专栏:计算机视觉CV

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

最终实现效果:

test.png
test.png
test_rotated.jpg
test_rotated.jpg

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.

image.png
image.png

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进行图像旋转并且不丢失信息到完整代码:

代码语言:txt
复制
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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档