详解 OpenCV 中的仿射变换:原理与实战案例
目录
什么是仿射变换?
仿射变换的数学原理
如何确定仿射变换矩阵?
OpenCV 实现仿射变换的完整代码
代码解析
仿射变换的应用场景
总结
什么是仿射变换?
仿射变换(Affine Transformation)是计算机视觉中一种重要的图像变换技术,它通过线性变换加平移的组合来实现图像的空间变换。与普通的线性变换不同,仿射变换能够保持图像的直线性和平行性,但会改变图形的形状,产生旋转、缩放、平移、剪切等效果。
通俗来说,仿射变换可以理解为:将图像上的所有点都按照相同的规则进行变换,变换后直线依然是直线,平行线依然保持平行,但角度和长度可能发生改变。
仿射变换的数学原理
仿射变换的数学表达式可以表示为:
对于图像上的任意一点 \((x, y)\),变换后的坐标 \((x', y')\) 满足:
\(\begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} a & b \\ c & d \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} + \begin{bmatrix} e \\ f \end{bmatrix}\)
其中:
- 矩阵 \(\begin{bmatrix} a & b \\ c & d \end{bmatrix}\) 负责图像的旋转、缩放和剪切
- 向量 \(\begin{bmatrix} e \\ f \end{bmatrix}\) 负责图像的平移
在 OpenCV 中,这个变换通常用一个 2×3 的矩阵表示:
\(M = \begin{bmatrix} a & b & e \\ c & d & f \end{bmatrix}\)
如何确定仿射变换矩阵?
确定一个仿射变换矩阵只需要三对对应点。这是因为 2×3 的变换矩阵包含 6 个未知数,而每对对应点可以提供 2 个方程,3 对对应点正好可以求解出 6 个未知数。
在 OpenCV 中,我们可以使用cv2.getAffineTransform()
函数,通过输入源图像和目标图像的三对对应点,自动计算出仿射变换矩阵。
OpenCV 实现仿射变换的完整代码
下面是一个使用 OpenCV 实现图像仿射变换的完整示例:
OpenCV仿射变换示例代码
import numpy as np
import cv2
import matplotlib.pyplot as plt# 读取图像
img = cv2.imread('test_image.jpg')
# 转换为RGB格式(OpenCV默认读取为BGR)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 获取图像的高度和宽度
height, width = img.shape[:2]# 定义源图像中的三个点(源点集)
# 这里选择左上角、左下角和右上角三个点
src_points = np.float32([[0, 0], # 左上角[0, height - 1], # 左下角[width - 1, 0] # 右上角
])# 定义目标图像中对应的三个点(目标点集)
# 这些点决定了图像变换后的形状
dst_points = np.float32([[0, 0], # 左上角保持不变[100, height - 100], # 左下角向右上方移动[width - 100, 100] # 右上角向左下方移动
])# 计算仿射变换矩阵
M = cv2.getAffineTransform(src_points, dst_points)# 执行仿射变换
# 参数dsize指定输出图像的尺寸,这里保持与原图像相同
dst = cv2.warpAffine(img, M, (width, height))
# 转换为RGB格式用于显示
dst_rgb = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)# 使用matplotlib显示结果
plt.figure(figsize=(12, 6))plt.subplot(121)
plt.imshow(img_rgb)
plt.title('原始图像')
plt.axis('off')plt.subplot(122)
plt.imshow(dst_rgb)
plt.title('仿射变换后图像')
plt.axis('off')plt.tight_layout()
plt.show()
代码解析
让我们逐行解析上面的代码,理解仿射变换的实现过程:
-
库导入与图像读取:
import numpy as np import cv2 import matplotlib.pyplot as pltimg = cv2.imread('test_image.jpg') img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) height, width = img.shape[:2]
首先导入必要的库,读取图像并转换颜色空间(OpenCV 默认使用 BGR 格式,而 matplotlib 使用 RGB 格式),然后获取图像的尺寸信息。
-
定义对应点集:
src_points = np.float32([[0, 0], [0, height - 1], [width - 1, 0]]) dst_points = np.float32([[0, 0], [100, height - 100], [width - 100, 100]])
这里定义了三对对应点,源点集是原始图像中的三个点,目标点集是这些点在变换后图像中的位置。
-
计算变换矩阵:
M = cv2.getAffineTransform(src_points, dst_points)
使用
cv2.getAffineTransform()
函数计算仿射变换矩阵,这个矩阵包含了所有的变换信息。 -
执行仿射变换:
dst = cv2.warpAffine(img, M, (width, height))
使用
cv2.warpAffine()
函数应用变换矩阵,对整个图像进行仿射变换。 -
结果显示:使用 matplotlib 将原始图像和变换后的图像并排显示,便于对比效果。
仿射变换的应用场景
仿射变换在计算机视觉中有广泛的应用:
- 图像校正:纠正倾斜的文档、照片等
- 视角转换:模拟从不同角度观察物体
- 图像对齐:将多幅图像对齐到同一坐标系
- 人脸识别:对齐不同姿态的人脸图像
- 增强现实:将虚拟物体正确地叠加到真实场景
总结
仿射变换是一种强大的图像变换技术,通过三对对应点可以实现复杂的图像空间变换。本文介绍了仿射变换的基本原理和数学表达,并通过 OpenCV 实现了一个完整的仿射变换示例。
理解仿射变换是学习更复杂计算机视觉技术的基础,例如透视变换、图像拼接等。在实际应用中,选择合适的对应点对变换效果至关重要,需要根据具体需求进行调整。
希望本文能帮助你理解并掌握仿射变换的基本使用方法,为你的计算机视觉项目提供参考。