4.1 仿射变换
图像的几何变换在计算机视觉和图像处理中扮演着至关重要的角色。仿射变换(Affine Transformation)是一种线性变换,它能够保持直线和平行线的特性,但不一定保持角度和长度。仿射变换广泛应用于图像旋转、缩放、剪切、平移以及图像对齐等操作中。
仿射变换的数学基础
仿射变换可以由一个2x3的矩阵表示,形式如下:

这个矩阵可以应用于图像的每个像素点 (x, y) 来得到新的位置 (x', y'):

仿射变换包括以下几种基本操作:
- 平移(Translation):将图像整体向某个方向移动。
- 缩放(Scaling):调整图像的尺寸。
- 旋转(Rotation):将图像绕某个中心点旋转一定的角度。
- 剪切(Shearing):沿水平或垂直方向倾斜图像。
使用OpenCV进行仿射变换
OpenCV提供了cv2.getAffineTransform()和cv2.warpAffine()两个主要函数来实现仿射变换。
cv2.getAffineTransform(src, dst):计算仿射变换矩阵。src:源图像中的三个点。dst:目标图像中对应的三个点。
cv2.warpAffine(src, M, dsize):应用仿射变换矩阵M到源图像。src:源图像。M:仿射变换矩阵。dsize:输出图像的尺寸,格式为(宽度, 高度)。
示例一:图像的平移
import cv2
import numpy as np
# 读取图像
image = cv2.imread('test.jpg')
if image is not None:
rows, cols = image.shape[:2]
# 定义平移矩阵,向右移动100像素,向下移动50像素
M = np.float32([[1, 0, 100],
[0, 1, 50]])
# 应用平移变换
translated = cv2.warpAffine(image, M, (cols, rows))
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Translated Image', translated)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存结果
cv2.imwrite('translated.jpg', translated)
else:
print("Error: 无法读取图像文件。")
说明:
- 平移矩阵中的
100和50分别表示图像将向右移动100像素,向下移动50像素。 cv2.warpAffine()函数根据平移矩阵将图像平移。
示例二:图像的缩放与旋转
import cv2
import numpy as np
# 读取图像
image = cv2.imread('test.jpg')
if image is not None:
rows, cols = image.shape[:2]
# 缩放因子
scale_factor = 0.5
# 定义缩放矩阵
M_scale = np.float32([[scale_factor, 0, 0],
[0, scale_factor, 0]])
# 应用缩放变换
scaled = cv2.warpAffine(image, M_scale, (int(cols * scale_factor), int(rows * scale_factor)))
# 定义旋转中心,通常为图像中心
center = (cols / 2, rows / 2)
# 定义旋转角度和缩放因子
angle = 45 # 旋转45度
scale = 1.0 # 不缩放
# 获取旋转矩阵
M_rotate = cv2.getRotationMatrix2D(center, angle, scale)
# 计算旋转后图像的尺寸,以防止图像内容被裁剪
abs_cos = abs(M_rotate[0, 0])
abs_sin = abs(M_rotate[0, 1])
bound_w = int(rows * abs_sin + cols * abs_cos)
bound_h = int(rows * abs_cos + cols * abs_sin)
# 调整旋转矩阵的平移部分
M_rotate[0, 2] += bound_w / 2 - center[0]
M_rotate[1, 2] += bound_h / 2 - center[1]
# 应用旋转变换
rotated = cv2.warpAffine(image, M_rotate, (bound_w, bound_h))
# 显示结果
cv2.imshow('Scaled Image', scaled)
cv2.imshow('Rotated Image', rotated)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存结果
cv2.imwrite('scaled.jpg', scaled)
cv2.imwrite('rotated.jpg', rotated)
else:
print("Error: 无法读取图像文件。")
说明:
- 缩放:使用仿射矩阵进行图像缩放,将图像尺寸缩小至原来的50%。
- 旋转:
- 使用
cv2.getRotationMatrix2D()获取旋转矩阵,指定旋转中心、角度和缩放因子。 - 计算旋转后图像的边界尺寸,调整旋转矩阵的平移部分,确保整个图像内容不被裁剪。
- 应用旋转矩阵进行图像旋转。
- 使用
示例三:图像的剪切(Shearing)
剪切变换通过倾斜图像来改变图像的形状。常见的剪切分为水平剪切和垂直剪切。
import cv2
import numpy as np
# 读取图像
image = cv2.imread('test.jpg')
if image is not None:
rows, cols = image.shape[:2]
# 定义水平剪切矩阵,shx为剪切因子
shx = 0.3
M_shear = np.float32([[1, shx, 0],
[0, 1, 0]])
# 应用剪切变换
sheared = cv2.warpAffine(image, M_shear, (int(cols + shx * rows), rows))
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Sheared Image', sheared)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存结果
cv2.imwrite('sheared.jpg', sheared)
else:
print("Error: 无法读取图像文件。")
说明:
- 水平剪切因子
shx = 0.3表示图像将沿水平轴倾斜30%的比例。 - 新的图像宽度通过
cols + shx * rows计算,确保剪切后的图像内容完整显示。
仿射变换的应用场景
- 图像对齐:将多幅图像对齐到同一坐标系,常用于图像拼接、全景图生成等。
- 图像增强:通过缩放、旋转等操作改善图像质量,适用于图像预处理。
- 目标跟踪与识别:在实时视频中对目标进行位姿调整,提升识别准确性。
- 图像翻译:实现图像的移动和平移,用于数据增强等。
常见问题及解决方案
-
图像部分内容被裁剪
- 原因:变换矩阵未考虑图像尺寸变化,导致部分内容超出边界。
- 解决方案:计算变换后的图像尺寸,并相应调整变换矩阵的平移部分,确保整个图像内容完整显示。
-
变换后的图像失真
- 原因:变换矩阵参数设置不当,或使用的插值方法不合适。
- 解决方案:合理设置仿射变换矩阵参数,选择适当的插值方法(如
cv2.INTER_LINEAR、cv2.INTER_CUBIC)以减少失真。
-
图像变换速度慢
- 原因:处理高分辨率图像,或在循环中重复计算变换矩阵。
- 解决方案:优化代码,预计算不变的变换矩阵,或调整图像分辨率以加快处理速度。
-
颜色空间问题
- 原因:在处理过程中颜色空间发生变化,导致变换后的图像颜色异常。
- 解决方案:确保在仿射变换前后保持一致的颜色空间,必要时进行色彩空间转换。
总结
仿射变换是图像几何变换中的基础操作,通过线性的仿射矩阵,可以实现图像的平移、缩放、旋转和剪切等多种变换。OpenCV提供了简洁高效的函数接口,使得仿射变换的应用变得简单直观。理解仿射变换的数学原理和OpenCV的实现方法,有助于开发者在计算机视觉和图像处理项目中灵活应用这些技术,解决实际问题。
4.2 透视变换
透视变换(Perspective Transformation)是一种更为复杂的几何变换,相比仿射变换,透视变换能够处理图像的非线性变形,保留投影的特性。它在图像校正、视角变换、图像拼接及增强现实等应用中具有重要作用。
使用OpenCV进行透视变换
OpenCV提供了cv2.getPerspectiveTransform()和cv2.warpPerspective()函数来实现透视变换。
cv2.getPerspectiveTransform(s

最低0.47元/天 解锁文章
3619

被折叠的 条评论
为什么被折叠?



