目标
- 熟练掌握图像的几何变换,缩放、翻转、仿射等等
几何变换原理说明: 几何变换的本质是像素坐标的映射 :通过数学公式将原始图像的像素坐标
(x, y)
映射到新图像的坐标(x', y')
,并根据插值算法确定新像素的值。
1.图像缩放
**解释:**调整图像的尺寸大小,可按比例或指定尺寸缩放。
函数:cv2.resize(src, dsize, fx=0, fy=0, interpolation=...)
参数:
src
:输入图像dsize
:输出尺寸(width, height)
fx/fy
:宽 / 高的缩放因子(若指定,dsize
可设为None
)interpolation
:插值方法(影响缩放质量)
插值方法选择(常用):
- 缩小图像:
cv2.INTER_AREA
(推荐,抗锯齿) - 放大图像:
cv2.INTER_CUBIC
(高质量,慢)或cv2.INTER_LINEAR
(较快)
说明:缩放的方式有两种,一是按照直接设置dsize的值,二是设置fx,fy的值
python
import cv2
img = cv2.imread('image.jpg')
# 方法1:指定输出尺寸 (宽, 高)
resized1 = cv2.resize(img, (400, 300)) # 宽400,高300
# 方法2:按缩放因子(0.5倍缩小)
resized2 = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
2. 图像翻转(Flip)
**解释:**沿水平、垂直或对角线翻转图像。
函数 :cv2.flip(src, flipCode)
flipCode = 0
:沿 x 轴翻转(垂直翻转)flipCode > 0
:沿 y 轴翻转(水平翻转),数值随便给,1,2,3都行flipCode < 0
:同时沿 x 轴和 y 轴翻转(对角翻转),数值随便给-1,-2,-3
3. 仿射变换
解释:仿射变换(Affine Transformation) 是一种保持图像 "平行性" 和 "比例性" 的几何变换,它能够将直线映射为直线,将平行线映射为平行线,但可能改变图形的角度和距离。这种变换可以理解为平移、旋转、缩放、剪切等基本变换的组合。


仿射变换实现步骤:
-
计算变换矩阵
使用
cv2.getAffineTransform(srcPoints, dstPoints)
函数,通过3 对对应点(源图像 3 个点→目标图像 3 个点)计算变换矩阵。3 对 points 不能共线,否则矩阵无法唯一确定。 -
应用变换矩阵
使用
cv2.warpAffine(src, M, dsize)
函数,将变换矩阵应用到图像上。
## 变换矩阵函数: cv2.getAffineTransform(srcPoints, dstPoints)
解释说明: 该函数用于通过3 对对应点(源图像点→目标图像点)计算仿射变换矩阵(2×3 矩阵),是仿射变换的 "核心计算工具"。
参数详解:
srcPoints
:
- 类型:
numpy.ndarray
(必须是 32 位浮点数类型np.float32
) - 形状:
(3, 2)
或(1, 3, 2)
(3 个点,每个点含 x、y 坐标) - 含义:源图像中用于计算变换的 3 个非共线点(若共线,矩阵无法唯一确定,会报错)。
- 示例:
np.float32([[x1,y1], [x2,y2], [x3,y3]])
dstPoints
:
- 类型:
numpy.ndarray
(同srcPoints
,需为np.float32
) - 形状:与
srcPoints
一致((3, 2)
或(1, 3, 2)
) - 含义:目标图像中与
srcPoints
一一对应的 3 个点,定义了源点经过仿射变换后应到达的位置。 - 示例:
np.float32([[x1',y1'], [x2',y2'], [x3',y3']])
## 仿射函数: cv2.warpAffine(src, M, dslags)
参数解释:
- src:类型:
numpy.ndarray
(图像矩阵),输入的原始图像(可以是单通道灰度图或多通道彩色图)。 M
:仿射变换矩阵,定义了像素坐标的映射规则。类型为numpy.ndarray
,2×3 的矩阵(必须是cv2.getAffineTransform()
的返回值或符合格式的自定义矩阵)dsize
:输出图像的尺寸大小(宽 × 高),需根据变换后的图像范围设置,避免内容被截断- 类型为元组
(width, height),
示例:(600, 400)
表示输出图像宽 600 像素,高 400 像素。 - flags:表示差值的方法,自己去查,不想写了
例子:
python
import cv2
import numpy as np
# 读取图像
img = cv2.imread('image.jpg')
h, w = img.shape[:2]
# 1. 定义3对对应点(源点→目标点)
src = np.float32([[50, 50], [200, 50], [50, 200]]) # 源图像中的三角形顶点
dst = np.float32([[100, 100], [250, 80], [120, 220]]) # 目标图像中的对应顶点
# 2. 计算仿射矩阵
M = cv2.getAffineTransform(src, dst)
# 3. 应用仿射变换(设置输出尺寸、插值方法、边界填充)
result = cv2.warpAffine(
src=img,
M=M,
dsize=(w + 100, h + 100), # 扩大输出尺寸避免截断
flags=cv2.INTER_CUBIC, # 高质量插值
borderMode=cv2.BORDER_CONSTANT, # 固定值填充
borderValue=(255, 255, 255) # 白色填充边缘
)
cv2.imshow('Result', result)
cv2.waitKey(0)
4. 图像旋转
说明:其实缩放、翻转、旋转等等都属于仿射变换的一种 。旋转通常以图像中心或自定义点为中心
旋转步骤:
1. 获得旋转矩阵
函数:cv2.getRotationMatrix2D(center, angle, scale)
作用 :该函数用于计算旋转所需的2×3 仿射变换矩阵,是旋转操作的核心。
参数:
center
:旋转中心坐标,类型:元组(cx, cy),
示例:(w//2, h//2)
表示以图像中心为旋转中心(w
为宽,h
为高)。angle
:旋转角度,正值为逆时针旋转。负值,顺时针旋转。示例:30
表示逆时针旋转 30 度,-45
表示顺时针旋转 45 度。scale
:旋转后图像的缩放因子。1.0
:不缩放(默认);>1.0
:放大(如1.2
表示放大 1.2 倍);<1.0
:缩小(如0.8
表示缩小到 80%)。
2. 执行旋转操作
函数:cv2.warpAffine(src, M, dsize[, flags[, borderMode[, borderValue]]])
说明: 该函数通过旋转矩阵 M
对图像执行旋转,与仿射变换共用(旋转本质是特殊的仿射变换)
参数:
src
:输入图像(numpy
数组,支持单通道或多通道)。M
:cv2.getRotationMatrix2D()
生成的 2×3 旋转矩阵。dsize
:输出图像尺寸,元组(width, height)
。- 若旋转后图像可能超出原尺寸(如旋转非 90° 倍数的角度),需设置更大的
dsize
避免内容被截断(计算方法见下文示例)。
- 若旋转后图像可能超出原尺寸(如旋转非 90° 倍数的角度),需设置更大的
flags
:插值方法(影响旋转后图像的清晰度):cv2.INTER_LINEAR
:双线性插值(默认,平衡速度和质量);cv2.INTER_CUBIC
:双三次插值(质量更高,速度较慢);cv2.INTER_NEAREST
:最近邻插值(速度快,可能产生锯齿)。
borderMode
:边缘填充模式(旋转后边缘的空白区域处理):cv2.BORDER_CONSTANT
:固定颜色填充(需配合borderValue
);cv2.BORDER_REPLICATE
:复制边缘像素填充;cv2.BORDER_REFLECT
:镜像填充(如abc → cba bc
)。
borderValue
:填充颜色(仅borderMode=cv2.BORDER_CONSTANT
时生效):- 灰度图:单值(如
255
表示白色); - 彩色图:BGR 三通道值(如
(0, 255, 0)
表示绿色)。
- 灰度图:单值(如
例子:
python
import cv2
import numpy as np
import math
# 读取图像
img = cv2.imread('image.jpg')
h, w = img.shape[:2] # 原图高、宽
# 1. 定义旋转参数
center = (w // 2, h // 2) # 以图像中心为旋转中心
angle = 30 # 逆时针旋转30度
scale = 1.0 # 不缩放
# 2. 计算旋转矩阵
M = cv2.getRotationMatrix2D(center, angle, scale)
# 3. 计算旋转后的输出尺寸(避免内容截断)
theta = math.radians(angle) # 角度转弧度
new_w = int(w * abs(math.cos(theta)) + h * abs(math.sin(theta)))
new_h = int(w * abs(math.sin(theta)) + h * abs(math.cos(theta)))
# 4. 调整旋转矩阵以适应新尺寸(避免图像偏移)
M[0, 2] += (new_w / 2) - center[0]
M[1, 2] += (new_h / 2) - center[1]
# 5. 执行旋转
rotated = cv2.warpAffine(
src=img,
M=M,
dsize=(new_w, new_h),
flags=cv2.INTER_CUBIC, # 高质量插值
borderMode=cv2.BORDER_CONSTANT, # 固定颜色填充边缘
borderValue=(255, 255, 255) # 白色填充
)
# 显示结果
cv2.imshow('Original', img)
cv2.imshow('Rotated', rotated)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:这是我拍的小猫咪
