Opencv(九) : 图像旋转
文章目录
- 思维导图
- 一、核心原理
- 1. 旋转矩阵与仿射变换
- 2. 关键参数说明
- 二、插值方法
- 1. 五种常用插值方法
- 2. 插值方法选择建议
- 三、边缘填充
- 1. 填充方式详解
- 2. 填充方式对比示例
- 四、代码实现
- 1. 图像中心旋转(双线性插值+反射101填充)
- 2. 不同插值方法对比代码
- 3. 自定义边缘填充颜色
- 五、注意事项与常见问题
- 六、扩展应用场景
思维导图

一、核心原理
图像旋转是将图像中所有像素点围绕指定旋转中心,按设定角度旋转后重新排列的过程,本质是二维平面的仿射变换。仿射变换能保持图形的平直性和平行性,是图像旋转的核心数学基础。
1. 旋转矩阵与仿射变换
-
以图像左上角为原点、逆时针为正方向时,像素点(x0,y0)(x_0,y_0)(x0,y0)旋转θ\thetaθ角后的坐标(x,y)(x,y)(x,y)由旋转矩阵计算:
![[
\begin{bmatrix}x \ y\end{bmatrix} = \begin{bmatrix}\cos\theta & -\sin\theta \ \sin\theta & \cos\theta\end{bmatrix} * \begin{bmatrix}x_0 \ y_0\end{bmatrix}
]](https://i-blog.csdnimg.cn/direct/fa4db0f4ab08403a86f9b98c8460f628.png)
-
绕任意点(tx,ty)(t_x,t_y)(tx,ty)旋转时,需经过“平移到原点→旋转→平移回原位置”三步,最终形成3×3的仿射变换矩阵,可通过OpenCV的
cv2.getRotationMatrix2D()直接获取。
2. 关键参数说明
- 旋转中心(center):二维坐标(x,y)(x,y)(x,y),常用图像中心点(imgshape[1]/2,imgshape[0]/2)(img_shape[1]/2, img_shape[0]/2)(imgshape[1]/2,imgshape[0]/2)。
- 旋转角度(angle):单位为度,逆时针为正方向,顺时针需传入负值。
- 缩放比例(scale):旋转后图像相对于原图的缩放系数,1为等比例不变。
二、插值方法
旋转或缩放过程中,像素坐标可能出现小数,或存在像素缺失/冗余,插值方法用于计算目标像素的准确值,直接影响图像质量。
1. 五种常用插值方法
| 方法 | 核心逻辑 | 优缺点 |
|---|---|---|
| 最近邻插值(INTER_NEAREST) | 取距离目标坐标最近的原像素值 | 速度最快,易出现锯齿和失真 |
| 双线性插值(INTER_LINEAR) | 利用周围4个像素加权计算 | 速度中等,图像平滑,无明显锯齿,OpenCV默认 |
| 像素区域插值(INTER_AREA) | 缩小取区域均值,整数倍放大类似最近邻,非整数倍用双线性 | 缩小效果好,放大效果一般 |
| 双三次插值(INTER_CUBIC) | 利用周围16个像素加权计算 | 速度较慢,图像细节保留好,失真极小 |
| Lanczos插值(INTER_LANCZOS4) | 利用周围64个像素(8×8)加权计算 | 速度最慢,放大/缩小效果最优,细节丰富 |
2. 插值方法选择建议
- 追求效率(如实时处理):选择最近邻插值。
- 平衡速度与质量(通用场景):选择双线性插值。
- 专业图像处理(如印刷、高清展示):选择双三次或Lanczos插值。
三、边缘填充
图像旋转后会出现空白区域,需通过填充方式补全,OpenCV提供五种常用边缘填充策略:
1. 填充方式详解
- 边界复制(BORDER_REPLICATE):复制图像边界像素填充空白,效果自然。
- 边界反射(BORDER_REFLECT):以图像边缘为轴反射填充,类似镜像效果。
- 边界反射101(BORDER_REFLECT_101):反射时不含边缘像素,避免边缘重复。
- 边界常数(BORDER_CONSTANT):用指定常数填充,默认值为0(黑色),可自定义颜色。
- 边界包裹(BORDER_WRAP):将图像视为循环纹理,用对侧像素填充。
2. 填充方式对比示例
- 日常场景:边界复制或反射101,效果自然无违和感。
- 特定需求(如黑色背景):边界常数填充(指定
borderValue=(0,0,0))。
四、代码实现
以下代码基于OpenCV-Python,以lena.png为例,涵盖不同插值方法和边缘填充的组合使用,直接可运行。
1. 图像中心旋转(双线性插值+反射101填充)
import cv2if __name__ == "__main__":# 读取图像path = "./lena.png"image_np = cv2.imread(path)if image_np is None:print("图像读取失败,请检查路径是否正确")exit()# 获取图像尺寸(height, width, channel)img_shape = image_np.shapeheight, width = img_shape[0], img_shape[1]# 旋转参数:中心、45度逆时针、缩放0.5倍center = (width / 2, height / 2)angle = 45scale = 0.5# 生成旋转矩阵M = cv2.getRotationMatrix2D(center, angle, scale)# 执行旋转(双线性插值+反射101填充)rotation_image = cv2.warpAffine(image_np, M, (width, height),flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_REFLECT_101)# 显示结果cv2.imshow("image", image_np)cv2.imshow("rotation_image", rotation_image)cv2.waitKey(0)cv2.destroyAllWindows()
输出结果为:


2. 不同插值方法对比代码
import cv2if __name__ == "__main__":path = "./lena.png"image_np = cv2.imread(path)img_shape = image_np.shapecenter = (img_shape[1]/2, img_shape[0]/2)angle = 90scale = 1.0# 生成旋转矩阵M = cv2.getRotationMatrix2D(center, angle, scale)# 四种插值方法对比# 最近邻插值rot_nearest = cv2.warpAffine(image_np, M, (img_shape[1], img_shape[0]), flags=cv2.INTER_NEAREST)# 双线性插值rot_linear = cv2.warpAffine(image_np, M, (img_shape[1], img_shape[0]), flags=cv2.INTER_LINEAR)# 双三次插值rot_cubic = cv2.warpAffine(image_np, M, (img_shape[1], img_shape[0]), flags=cv2.INTER_CUBIC)# Lanczos插值rot_lanczos = cv2.warpAffine(image_np, M, (img_shape[1], img_shape[0]), flags=cv2.INTER_LANCZOS4)# 显示对比cv2.imshow("最近邻插值", rot_nearest)cv2.imshow("双线性插值", rot_linear)cv2.imshow("双三次插值", rot_cubic)cv2.imshow("Lanczos插值", rot_lanczos)cv2.waitKey(0)cv2.destroyAllWindows()
3. 自定义边缘填充颜色
import cv2if __name__ == "__main__":path = "./lena.png"image_np = cv2.imread(path)img_shape = image_np.shapecenter = (img_shape[1]/2, img_shape[0]/2)# 生成旋转矩阵(180度旋转,等比例)M = cv2.getRotationMatrix2D(center, 180, 1.0)# 边界常数填充,自定义白色背景(BGR格式)rotation_image = cv2.warpAffine(image_np, M, (img_shape[1], img_shape[0]),flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT,borderValue=(255, 255, 255))cv2.imshow("180度旋转(白色背景)", rotation_image)cv2.waitKey(0)cv2.destroyAllWindows()
输出结果为:

五、注意事项与常见问题
- 坐标顺序问题:OpenCV中图像shape为(height, width),旋转中心坐标需按(width/2, height/2)传入,避免图像拉伸。
- 旋转方向:角度为正值时逆时针旋转,负值时顺时针旋转(如
angle=-30表示顺时针30度)。 - 图像读取失败:检查文件路径是否正确,确保图像格式为OpenCV支持的格式(png、jpg等),避免后缀名伪造。
- 内存与速度:Lanczos和双三次插值计算量大,处理超大图像时可能卡顿,需根据需求权衡。
六、扩展应用场景
- 图像校正:如倾斜文档、车牌的旋转校正。
- 数据增强:在深度学习中,旋转图像生成更多训练样本。
- 视觉效果:如图片预览、视频播放中的旋转功能。
