[速查速记] 几何变换 - 平移变换、缩放变换、镜像变换、旋转变换

平移变换

1. 基本原理

平移变换,指在像素的坐标上,实现如下形式:
\begin{bmatrix} x \\ y \\ 1\end{bmatrix}= T\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix} = \begin{bmatrix} 1 & 0 & \Delta x \\ 0 & 1 & \Delta y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix}

其中 T 为平移变换的操作矩阵,针对原图像中的每一个像素坐标,进行矩阵计算,得出新图像中存放的坐标。
经过平移变换的图像的部分像素会离开原始的图像区域,此时如果不增加画布的大小,图像会被截断。

2. 使用场景

图像的平移

3. 代码

cv.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]):仿射变换,使用指定的矩阵 M 转换源图像,dsize 为目标图像的尺寸。borderValue 则控制未指定像素区域的颜色

import cv2 as cv
import numpy as np
 
img1 = cv.imread('dip.jpeg')
tx = 100
ty = 20
 
affine_arr = np.float32([[1,0,tx],[0,1,ty]])

# 仿射变换
# 画布适配平移 cv.warpAffine(img1,affine_arr,(img1.shape[0] + tx ,img1.shape[1] + ty))
res = cv.warpAffine(img1,affine_arr,(img1.shape[0],img1.shape[1])) 
 
plt.figure()
plt.subplot(1,2,1)
plt.imshow(img1, cmap='gray')
plt.subplot(1,2,2)
plt.imshow(res, cmap='gray')
plt.show()

结果如下:


缩放变换

缩放变换,只需要更改变换矩阵的形式即可
\begin{bmatrix} x \\ y \\ 1\end{bmatrix}= T\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix} = \begin{bmatrix} S_x & 0 & 0 \\ 0 & S_y & 0 \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix}

Sx = 2
Sy = 2
affine_arr = np.float32([[Sx,0,0],[0,Sy,0]])

缩小时,原图像的部分有规律位置的点显示到新的图像上。扩大时,会对未赋值像素的位置进行内插操作(默认使用中心点充实领域)。

镜像变换

镜像变换分为水平镜像和垂直镜像。
水平镜像:
\begin{bmatrix} x \\ y \\ 1\end{bmatrix}= T\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix} = \begin{bmatrix} -1 & 0 & Width \\ 0 & 1 & 0 \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix}

affine_arr = np.float32([[-1,0,img1.shape[0]],[0,1,0]])

垂直镜像:
\begin{bmatrix} x \\ y \\ 1\end{bmatrix}= T\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 \\ 0 & -1 & Height \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix}

affine_arr = np.float32([[1,0,0],[0,-1,img1.shape[1]]])

旋转变换

\begin{bmatrix} x \\ y \\ 1\end{bmatrix}= T\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix} = \begin{bmatrix} cos\theta & sin\theta & 0 \\ -sin\theta & cos\theta & 0 \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_0 \\ y_0 \\ 1\end{bmatrix}

def dumpRotateImage(img,degree):
 
    height, width = img.shape[:2]
    # 计算旋转后的可容纳的画布大小
    heightNew = int(width * fabs(sin(radians(degree))) + height * fabs(cos(radians(degree))))
    widthNew = int(height * fabs(sin(radians(degree))) + width * fabs(cos(radians(degree))))

    # 计算旋转中心
    matRotation = cv2.getRotationMatrix2D((width//2, height//2), degree, 1)

    # 加入平移操作,居中
    matRotation[0,2] += (widthNew - width)//2
    matRotation[1,2] += (heightNew - height)//2
 
    # 执行仿射变换
    imgRotation = cv2.warpAffine(img, matRotation,(widthNew,heightNew),borderValue=(255,255,255))
 
    return imgRotation
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容