仿射变换的数学原理

仿射变换是二维平面中的线性变换,可用以下矩阵方程表示: [ \begin{bmatrix} x' \ y' \end{bmatrix} = \begin{bmatrix} a & b \ d & e \end{bmatrix} \begin{bmatrix} x \ y \end{bmatrix} + \begin{bmatrix} c \ f \end{bmatrix} ] 其中:

  • ( (x,y) ) 是原坐标
  • ( (x',y') ) 是变换后坐标
  • 矩阵元素 ( a,b,d,e ) 控制旋转、缩放和剪切
  • ( c,f ) 控制平移

该变换保持直线和平行性,但不保持角度和长度。

OpenCV 的核心函数

cv2.getAffineTransform(src, dst)
输入三个源点坐标和三个目标点坐标,返回2x3变换矩阵。

cv2.warpAffine(src, M, dsize)
应用仿射矩阵M到图像上,dsize指定输出图像尺寸。

cv2.getRotationMatrix2D(center, angle, scale)
生成绕指定中心点旋转的变换矩阵,angle为角度制,scale为缩放因子。

图像旋转实战案例

import cv2
import numpy as np

img = cv2.imread('input.jpg')
h, w = img.shape[:2]

# 生成旋转矩阵(中心点、角度、缩放)
M = cv2.getRotationMatrix2D((w/2, h/2), 45, 0.8)

# 应用变换
rotated = cv2.warpAffine(img, M, (w, h))
cv2.imwrite('rotated.jpg', rotated)

三点映射变换案例

# 定义原始三角形和目标三角形
src_pts = np.float32([[50,50], [200,50], [50,200]])
dst_pts = np.float32([[10,100], [200,50], [100,250]])

# 计算变换矩阵
M = cv2.getAffineTransform(src_pts, dst_pts)

# 执行变换
warped = cv2.warpAffine(img, M, (w, h))

透视变换与仿射变换的区别

虽然两者都使用2x3矩阵,但存在本质差异:

  • 仿射变换:平行线保持平行,6自由度
  • 透视变换:平行线可能相交,8自由度

OpenCV中透视变换使用cv2.getPerspectiveTransform()cv2.warpPerspective()

实际应用场景

文档校正
通过检测文档四个角点,计算仿射变换矩阵将倾斜文档拉直。

图像配准
将不同视角拍摄的图像通过特征点匹配后,用仿射变换对齐。

数据增强
在深度学习训练中,对图像施加随机仿射变换扩充数据集。

性能优化技巧

  1. 对于批量处理,预先计算好变换矩阵
  2. 使用cv2.INTER_LINEAR作为默认插值方法
  3. 指定borderMode=cv2.BORDER_REPLICATE处理边界像素
  4. 对于大图像,考虑先降采样处理再上采样

常见问题排查

黑边问题
变换后图像出现黑边时,可调整输出尺寸或设置borderValue参数。

坐标越界
目标坐标超出图像范围时,使用cv2.warpAffinedsize参数控制输出画布大小。

精度损失
多次连续变换时应合并变换矩阵:( M_{final} = M_2 \times M_1 )

https://github.com/darthfeltr/ozk_6kni
https://github.com/midtzc/giq_ylj2
https://github.com/sangpathac/a9b_38pa
https://github.com/suitpaint5/989_nitn
https://github.com/fear5healt/v02_49r6

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐