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

OpenCV 图像仿射变换之旋转

一、知识点
1、void warpAffine(InputArray src, 
                  OutputArray dst, 
                  InputArray M, 
                  Size dsize, 
                  int flags = INTER_LINEAR, 
                  int borderMode = BORDER_CONSTANT, 
                  const Scalar & borderValue = Scalar());

(1)、对图像应用仿射变换(旋转、平移、缩放)。
(2)、参数说明:
    src: 输入图像。
    dst: 输出图像,大小为dsize,数据类型与src相同。
    M: 2 * 3转换矩阵(两行三列)。
    dsize: 输出图像的大小。
    flags: 插值方法,InterpolationFlags枚举值。可和WARP_INVERSE_MAP组合,意味着M是逆变换(dst-->src)。
    borderMode: 边界模式,像素外推方法,BorderTypes枚举值。
    borderValue: 边界值。 当borderMode为BORDER_CONSTANT时,borderValue为边界的像素颜色。
(3)、仿射变换公式:

dst(x,y) = src(M11x + M12y + M13, M21x + M22y + M23)| M11 M12 M13 |     | x ||             |  *  | y || M21 M22 M23 |     | 1 |


2、在OpenCV中,旋转矩阵M为:

    | cosθ   sinθ   0 ||                 || -sinθ  cosθ   0 |


3、在OpenCV中,平移矩阵M为:

    | 1   0   dx ||            || 0   1   dy |


4、但是2、3的矩阵只相对于原点变换,实际工作中,经常是2、3的结合。 
  对于绕任意点的旋转矩阵,OpenCV中提供getRotationMatrix2D()获取。

5、Mat getRotationMatrix2D(Point2f center, double angle, double scale);
  (1)、计算2D旋转的仿射矩阵,可以用来对图像进行旋转。
  (2)、参数说明:
      center: 源图像的旋转中心点,即源图像要围绕此点旋转。
      angle: 旋转的角度,以度为单位,正值逆时针旋转,负值顺时针旋转。
      scale: 缩放因子。 1.0不改变大小,0.5缩小一半,2.0放大一倍。
  (3)、原点在源图像的左上角。
    
6、旋转后新的图像大小计算:

  nw = w * cosθ + h * sinθ;nh = h * cosθ + w * sinθ;

二、示例代码

#include <iostream>
#include <opencv2/opencv.hpp>int main()
{//1.获取源图像cv::Mat src = cv::imread("../images/9.png");if (src.empty()){std::cout << "load src image error..." << std::endl;return -1;}cv::imshow("源图像", src);//2.获取源图像宽、高int w = src.cols;int h = src.rows;//3.获取围绕源图像中心点,逆时针旋转45度,不缩放的矩阵cv::Mat M = cv::getRotationMatrix2D(cv::Point2f(w / 2, h / 2), 45, 1.0);//4.仿射变换,但是旋转后图像四角被截断,并且有黑色背景cv::Mat dst1;cv::warpAffine(src, dst1, M, cv::Size(w, h));cv::imshow("绕中心点逆时针旋转45度", dst1);//5.改变旋转后图像大小,源图像四角不被截断double cosTheta = cv::abs(M.at<double>(0, 0));double sinTheta = cv::abs(M.at<double>(0, 1));int nw = w * cosTheta + h * sinTheta;int nh = h * cosTheta + w * sinTheta;M.at<double>(0, 2) += (nw / 2.0 - w / 2.0);M.at<double>(1, 2) += (nh / 2.0 - h / 2.0);cv::Mat dst2;cv::warpAffine(src, dst2, M, cv::Size(nw, nh));cv::imshow("改变大小,源图像四角不被截断", dst2);//6.填充背景cv::Scalar backColor(src.at<cv::Vec3b>(0, 0)[0], src.at<cv::Vec3b>(0, 0)[1], src.at<cv::Vec3b>(0, 0)[2]);cv::Mat dst3;cv::warpAffine(src, dst3, M, cv::Size(nw, nh), cv::INTER_LINEAR, 0, backColor);cv::imshow("填充背景", dst3);cv::waitKey(0);return 0;
}

输出结果:

http://www.lryc.cn/news/571339.html

相关文章:

  • flutter的widget的执行顺序,单个组建的执行顺序
  • 什么是数据清洗?数据清洗有哪些步骤?
  • 算法导论第九章:顺序统计的艺术 - 高效查找中位数与第K小元素
  • 【AI分享:LangGraph 开源项目的深度分析报告
  • Spring Boot 数据校验: Bean Validation 注解、分组校验与全局异常处理
  • SSRF3 任意文件读取
  • 游戏引擎学习路径与技术栈指南
  • 基于Qt的配置管理界面实现:保存与加载配置文件
  • SpringCloud + Zookeeper + Feign整合及Feign原理
  • JSON-RPC 2.0 与 1.0 对比总结
  • java面试总结-20250616
  • 字符操作函数续上
  • 图扑 HT 3D 场景视频嵌入应用功能
  • cuda编程笔记(4)--纹理内存
  • OpenCV——图像形态学
  • Docker 快速搭建一个基于 GPT-Vis 组件的统计图表生成服务
  • 【超详细】讯飞智能车PC电脑烧录指南(高级系统部署与恢复)
  • 系统思考:越用力推系统,系统反弹性越大
  • Flask入门指南:从零构建Python微服务
  • Appium环境安装
  • 关于人工智能未来的趋势
  • B站PWN教程笔记-12
  • 计算机视觉| 分割大模型Segment Anything(SAM)从0到1使用
  • Muon:神经网络隐藏层的革命性优化器
  • 从零到一:C语言基础入门学习路线与核心知识点全解析
  • 香橙派3B学习笔记12:C语言操作GPIO_<wiringPi.h>_点灯通用输入输出
  • FPGA 44 ,SDC 时序约束标准( 深度解析 SDC 标准 )
  • 期末作业swing水果店管理系统
  • 二分算法深度解析
  • 简说 python