当前位置: 首页 > news >正文

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}
]

  • 绕任意点(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()

输出结果为:
在这里插入图片描述

五、注意事项与常见问题

  1. 坐标顺序问题:OpenCV中图像shape为(height, width),旋转中心坐标需按(width/2, height/2)传入,避免图像拉伸。
  2. 旋转方向:角度为正值时逆时针旋转,负值时顺时针旋转(如angle=-30表示顺时针30度)。
  3. 图像读取失败:检查文件路径是否正确,确保图像格式为OpenCV支持的格式(png、jpg等),避免后缀名伪造。
  4. 内存与速度:Lanczos和双三次插值计算量大,处理超大图像时可能卡顿,需根据需求权衡。

六、扩展应用场景

  • 图像校正:如倾斜文档、车牌的旋转校正。
  • 数据增强:在深度学习中,旋转图像生成更多训练样本。
  • 视觉效果:如图片预览、视频播放中的旋转功能。
http://www.dtcms.com/a/581091.html

相关文章:

  • 关键词解释:DAG 系统(Directed Acyclic Graph,有向无环图)
  • 【Linux】基础开发⼯具
  • 那些网站可以给产品做推广个人网站备案填写
  • 现代汽车确认遭遇数据泄露, 攻击者连续窃密9天获取用户驾照信息
  • 如何进行数据脱取
  • 将linux操作系统装入U盘20251107
  • 工业级部署指南:在西门子IOT2050(Debian 12)上搭建.NET 9.0环境与应用部署
  • ​AI大模型时代下的全栈技术架构:从深度学习到云原生部署实战
  • 手机版网站推荐银川网站建设哪家不错
  • maven与springBoot环境配置
  • C++程序设计实验(黑龙江大学)
  • 全屋智能家居定制小程序
  • 做电影网站需多大的空间网站建设意义
  • 拓普建站推广wordpress域名变更
  • 深度学习从入门到精通(一):深度学习的分类
  • 进制转换--c
  • opencv 学习: 05 像素操作
  • Mamba YOLO: 基于状态空间模型的目标检测简单基线
  • Java 大视界 --Java 大数据在智慧农业农产品市场价格预测与种植决策支持中的应用实战
  • K8s的标签应用和调度
  • 如何应用动作捕捉技术让户外重体力工作更安全
  • rust中的Cargo.toml文件
  • PD快充诱骗芯片 XSP15 支持获取快充电压可与外部MCU共用D+D-网络与电脑传输数据
  • 蓝牙钥匙 第58次 蓝牙钥匙交互反馈设计:构建多感官无缝用户体验
  • spiderdemo第22题与webassembly的跨域
  • 【MySQL | 基础】通用语法及SQL分类
  • 【爬虫】分析天气网后,整理的一点理论上的理解
  • Web安全-文件上传漏洞-黑白名单及其它绕过思路(附思维导图)
  • WPF 高级 UI 定制:深入解析 VisualStateManager 与 Adorner
  • 全景相机市占率“罗生门”:影石的数据迷雾