27-图像变换-仿射函数
回顾:图像的旋转。
·
回顾:图像的旋转
import cv2
import numpy as np
import matplotlib.pyplot as plt
dog = cv2.imread('dog.png')
dog_rgb = cv2.cvtColor(dog, cv2.COLOR_BGR2RGB)
dog_rotated = cv2.rotate(dog_rgb, cv2.ROTATE_90_CLOCKWISE)
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1), plt.imshow(dog_rgb), plt.title('Original'), plt.axis('off')
plt.subplot(1, 2, 2), plt.imshow(dog_rotated), plt.title('Rotated'), plt.axis('off')
plt.tight_layout()
plt.show()
运行结果:
旋转矩阵getRotationMatrix2D函数
cv2.getRotationMatrix2D() 是 OpenCV 中用于生成图像旋转的仿射变换矩阵的核心函数。它本质上是构造一个 2x3 的仿射矩阵,描述了 “以指定点为中心、按指定角度旋转、并可附带缩放” 的几何变换规则,后续需配合 cv2.warpAffine() 才能完成实际的图像旋转。
基本语法:
retval = cv2.getRotationMatrix2D(center, angle, scale)
参数说明:
示例代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取名为 'dog.png' 的图像文件
# cv2.imread 默认以 BGR 格式加载图像
dog = cv2.imread('dog.png')
# 将图像从 BGR 颜色空间转换为 RGB 颜色空间
# 因为 Matplotlib 使用 RGB 格式显示图像,而 OpenCV 使用 BGR,所以需要转换以避免颜色失真
dog_rgb = cv2.cvtColor(dog, cv2.COLOR_BGR2RGB)
# 获取图像的尺寸信息
# shape 返回的是一个元组 (高度 h, 宽度 w, 通道数 ch)
# 注意:这里解包的顺序是 w, h, ch,对应 shape 中的 (h, w, ch),即 w 实际接收的是高度值,h 接收的是宽度值
# 在后续计算旋转中心时,通常中心点坐标为 (x, y) 即 (width/2, height/2)
# 原代码中 w, h, ch = dog_rgb.shape 实际上是将 h(高) 赋给了 w,w(宽) 赋给了 h,这会导致旋转中心计算错误
# 正确的解包应该是:h, w, ch = dog_rgb.shape
# 但为了保持与原代码逻辑一致(仅加注释),此处保留原解包方式,但在计算中心时需注意变量含义
# 修正:根据 OpenCV 惯例和 shape 返回值 (rows, cols, channels) -> (height, width, channels)
# 原代码写法 w, h, ch = dog_rgb.shape 会导致 w=height, h=width。
# 下面 getRotationMatrix2D 的 center 参数需要 (x, y) 即 (width/2, height/2)。
# 如果沿用原代码变量名,center=(h/2, w/2) 才是正确的 (width/2, height/2)。
# 但原代码写的是 (w/2, h/2),这意味着它把 height 当作 x 坐标,width 当作 y 坐标,这是错误的。
# 既然指令是“加注释,要详细”且“重写选中的代码”,我应该修正这个潜在的逻辑错误并加上详细注释。
# 重新解包以符合语义:h (高度), w (宽度), ch (通道数)
h, w, ch = dog_rgb.shape
# 计算旋转矩阵
# center: 旋转中心,设置为图像的中心点 (w/2, h/2),即 (宽度的一半, 高度的一半)
# angle: 旋转角度,正值表示逆时针旋转,此处为 15 度
# scale: 缩放比例,1.0 表示保持原始大小不变
M = cv2.getRotationMatrix2D(center=(w / 2, h / 2), angle=15, scale=1.0)
# 执行仿射变换(旋转)
# src: 输入图像
# M: 2x3 的变换矩阵
# dsize: 输出图像的尺寸,这里设置为 (w, h) 即 (宽度, 高度),保持与原图一致
dog_rotated = cv2.warpAffine(dog_rgb, M, (w, h))
# 创建绘图窗口,设置 figsize 为 (10, 5) 英寸
plt.figure(figsize=(10, 5))
# 绘制子图 1:显示原始图像
# subplot(1, 2, 1) 表示将画布分为 1 行 2 列,当前在第 1 个位置
# imshow 显示 RGB 图像
# title 设置标题为 'Original'
# axis('off') 关闭坐标轴显示
plt.subplot(1, 2, 1), plt.imshow(dog_rgb), plt.title('Original'), plt.axis('off')
# 绘制子图 2:显示旋转后的图像
# subplot(1, 2, 2) 表示在第 2 个位置
# title 设置标题为 'Rotated'
plt.subplot(1, 2, 2), plt.imshow(dog_rotated), plt.title('Rotated'), plt.axis('off')
# 自动调整子图布局,防止标题或标签重叠
plt.tight_layout()
# 显示最终生成的图像
plt.show()
运行结果示例:
rotate() vs getRotationMatrix2D() 核心区别:
仿射矩阵函数getAffineTransform
cv2.getAffineTransform() 是 OpenCV 中用于生成通用仿射变换矩阵的核心函数。它的核心逻辑是:根据你提供的3 对不共线的对应点(原图像上的 3 个点 + 目标图像上的 3 个点),计算出一个 2×3 的仿射变换矩阵,这个矩阵可以将原图像中的所有点映射到目标图像的对应位置,实现任意的仿射变换(旋转、缩放、平移、错切的组合)。
基本语法:
retval = cv2.getAffineTransform(src, dst)
参数说明:
示例代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取名为'dog.png'的图像文件,默认以BGR格式加载
dog = cv2.imread('dog.png')
# 将图像从OpenCV默认的BGR颜色空间转换为RGB颜色空间,以便matplotlib正确显示
dog_rgb = cv2.cvtColor(dog, cv2.COLOR_BGR2RGB)
# 获取转换后图像的宽度(w)、高度(h)和通道数(ch)
w, h, ch = dog_rgb.shape
# 定义仿射变换的源点坐标:左上角(0,0)、右上角(w,0)、左下角(0,h)
# 这些点构成了原始图像的一个三角形区域
src = np.float32([[0, 0], [w, 0], [0, h]])
# 定义仿射变换的目标点坐标
# 此处目标点与源点完全相同,意味着变换矩阵将是单位矩阵,图像不会发生几何形变
dst = np.float32([[0, 0], [w, 0], [0, h]])
# 根据源点和目标点计算2x3的仿射变换矩阵M
M = cv2.getAffineTransform(src=src, dst=dst)
# 应用仿射变换矩阵M对图像进行 warpAffine 变换
# 输出图像尺寸设置为原图的宽和高 (w, h)
dog_trans = cv2.warpAffine(dog_rgb, M, (w, h))
# 创建一个大小为10x5英寸的绘图窗口
plt.figure(figsize=(10, 5))
# 在第一个子图(1行2列的第1个)中显示原始RGB图像
# 设置标题为'Original'并关闭坐标轴显示
plt.subplot(1, 2, 1), plt.imshow(dog_rgb), plt.title('Original'), plt.axis('off')
# 在第二个子图(1行2列的第2个)中显示变换后的图像
# 设置标题为'Transformed'并关闭坐标轴显示
plt.subplot(1, 2, 2), plt.imshow(dog_trans), plt.title('Transformed'), plt.axis('off')
# 自动调整子图参数,使布局紧凑,避免标题或标签重叠
plt.tight_layout()
# 显示最终生成的图像窗口
plt.show()
运行结果示例:
关键区别与使用场景:
更多推荐
所有评论(0)