OpenCV Python 学习笔记(三) 仿射变换

本文介绍了仿射变换的概念及其矩阵表示方法,并通过实例演示了如何利用Python进行图像的平移、旋转及任意变换。

什么是仿射变换?

仿射变换就是图像的线性变换加上平移,用一幅图表示,就是 

                      

 

由 image1 到 image2 的转换经过了三个操作

  1. 旋转 (线性变换)
  2. 缩放操作(线性变换)
  3. 平移 (向量加)

如果没有了第3个平移的操作,那它就是线性变换。前两个笔记已经整理了图像的旋转、缩放和平移的各个方法,接下来会介绍仿射变换的矩阵表示和使用方法。


放射变化的矩阵形式

图像的变换要对图像的每一个像素点进行操作,假设其中的一个像素点的坐标是(x,y),我们用矩阵形式表示:    

我们通常使用 2 \times 3 矩阵来表示仿射变换。


                                            

                                         矩阵 AB 就是变换矩阵

经过仿射变换后的点的矩阵坐标是T,我们已经知道放射变换就是线性变换加上平移,用矩阵表示的话就是     T = A \cdot \begin{bmatrix}x \\ y\end{bmatrix} + B


也可以写成       T = M \cdot  [x, y, 1]^{T}


计算可得        T =  \begin{bmatrix}    a_{00}x + a_{01}y + b_{00} \\    a_{10}x + a_{11}y + b_{10}    \end{bmatrix}



使用代码

来看一下之前说过的图像平移的代码

import cv2  
import numpy as np  
      
img = cv2.imread('Rachel.jpg', 0)  
rows, cols = img.shape  
       
M = np.float32([[1, 0, 200], [0, 1, 100]])  
dst = cv2.warpAffine(img, M, (cols, rows))      

cv2.imshow('img', dst)  
k = cv2.waitKey(0)  
if k == ord('s'):  
    cv2.imwrite('Rachel3.jpg', dst)  
    cv2.destroyAllWindows()  

可以看到第7行
M = np.float32([[1, 0, 200], [0, 1, 100]])

将这个二维矩阵的值带入T,得到经过仿射变换后的点的坐标是(x+200,y+100),即将整个图像平移(200,100)


再看图像旋转的代码

import cv2  
      
img = cv2.imread('Rachel.jpg', 0)  
rows, cols = img.shape
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)  
dst = cv2.warpAffine(img, M, (cols, rows)) # 仿射变换,以后再说  
cv2.imshow('Rachel', dst)  
cv2.waitKey(0)  
cv2.destroyAllWindows()  

大部分同上类似,只是其中的 M 矩阵不同

M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1)  # 第一个参数是中心点的坐标 

cv2.getRotationMatrix2D这个函数就是生成图像旋转的所需要的矩阵


那么如何通过仿射变换任意变换图形呢?

我们需要源图像和目标图像上分别一一映射的三个点来定义仿射变换

示例代码:

img = cv2.imread('Rachel.jpg')
rows, cols, ch = img.shape

pts1 = np.float32([[0, 0], [cols - 1, 0], [0, rows - 1]])
pts2 = np.float32([[cols * 0.2, rows * 0.1], [cols * 0.9, rows * 0.2], [cols * 0.1, rows * 0.9]])

M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))

cv2.imshow('image', dst)
k = cv2.waitKey(0)
if k == ord('s'):
    cv2.imwrite('Rachel1.jpg', dst)
    cv2.destroyAllWindows()

结果:


仿射变换(Affine Transformation)是图像处理和计算机图形学中常用的一种几何变换,其核心思想是在向量空间中进行一次线性变换(乘以一个矩阵),并随后进行一次平移(加上一个向量),从而将一个坐标系中的点映射到另一个坐标系中。仿射变换保持了图像的平行性和线性关系,因此在图像旋转、缩放、平移、错切等操作中具有广泛应用。 ### 仿射变换的数学原理 仿射变换可以表示为: $$ \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} a & b & t_x \\ c & d & t_y \\ 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} $$ 其中 $(x, y)$ 是原图中的坐标点,$(x', y')$ 是变换后的坐标点,矩阵中的 $a, b, c, d$ 构成了线性变换部分,而 $t_x, t_y$ 表示平移部分。这种表示方式利用了齐次坐标,使得平移操作也能通过矩阵乘法实现。 ### 仿射变换矩阵的构成 仿射变换矩阵通常是一个 $2 \times 3$ 的矩阵,其形式如下: $$ M = \begin{bmatrix} a & b & t_x \\ c & d & t_y \end{bmatrix} $$ 该矩阵可以拆解为一个 $2 \times 2$ 的线性变换矩阵 $A$ 和一个 $2 \times 1$ 的平移向量 $B$: $$ A = \begin{bmatrix} a & b \\ c & d \end{bmatrix},\quad B = \begin{bmatrix} t_x \\ t_y \end{bmatrix} $$ 其中 $A$ 控制缩放、旋转、错切等操作,而 $B$ 控制图像的平移。 ### 常见的仿射变换类型 1. **平移变换**: $$ M_{\text{translate}} = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \end{bmatrix} $$ 2. **旋转变换**: $$ M_{\text{rotate}} = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \end{bmatrix} $$ 3. **缩放变换**: $$ M_{\text{scale}} = \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \end{bmatrix} $$ 4. **错切变换**: $$ M_{\text{shear}} = \begin{bmatrix} 1 & \tan\theta & 0 \\ \tan\phi & 1 & 0 \end{bmatrix} $$ ### 仿射变换矩阵实现 在实际应用中,仿射变换可以通过 OpenCV、NumPy 等库实现。例如,在 OpenCV 中,可以通过 `cv2.warpAffine` 函数应用仿射变换矩阵对图像进行处理。 以下是一个使用 PythonOpenCV 实现仿射变换的示例代码: ```python import cv2 import numpy as np # 读取图像 image = cv2.imread('input.jpg') # 定义仿射变换矩阵(例如:平移) M_translate = np.float32([[1, 0, 50], [0, 1, 30]]) # 应用仿射变换 transformed_image = cv2.warpAffine(image, M_translate, (image.shape[1], image.shape[0])) # 显示结果 cv2.imshow('Transformed Image', transformed_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 上述代码中,`M_translate` 是一个 $2 \times 3$ 的仿射变换矩阵,用于实现图像的平移操作。通过 `cv2.warpAffine` 函数,可以将变换矩阵应用于图像,生成新的变换后图像。 ### 仿射变换的特点 - **保持平行性**:仿射变换不会改变图像中平行线的关系,变换后的图像仍然保持平行线平行。 - **线性变换与平移结合**:仿射变换是线性变换和平移操作的结合,能够实现旋转、缩放、错切和平移等多种变换。 - **齐次坐标表示**:通过齐次坐标,可以将平移操作统一到矩阵乘法中,简化了计算过程。 ### 相关问题
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值