Opencv-C++笔记 (12) : opencv-仿射变化

2023-11-12

一、概述

介绍完图像的缩放和翻转后,接下来将要介绍图像的旋转,但是在OpenCV
4中并没有专门用于图像旋转的函数,而是通过图像的仿射变换实现图像的旋转。实现图像的旋转首先需要确定旋转角度和旋转中心,之后确定旋转矩阵,最终通过仿射变换实现图像旋转。

二、GetRotationMatrix2D

针对这个流程,OpenCV4提供了getRotationMatrix2D()函数用于计算旋转矩阵和warpAffine()函数用于实现图像的仿射变换。首先介绍计算旋转矩阵getRotationMatrix2D()函数,该函数的函数原型在代码清单3-31中给出。

Mat cv::getRotationMatrix2D (Point2f center,double  angle,double  scale)
  • center:图像旋转的中心位置。
  • angle:图像旋转的角度,单位为度,正值为逆时针旋转。
  • scale:两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1。
    在这里插入图片描述
    在这里插入图片描述

三、warpAffine()

函数进行仿射变换,就可以实现图像的旋转,在代码清单3-32中给出了warpAffine()函数的函数原型。

 void cv::warpAffine(InputArray src,
                    OutputArray dst,
                    InputArray M,
                    Size dsize,
                    int  flags = INTER_LINEAR,
                    int  borderMode = BORDER_CONSTANT,
                    const Scalar& borderValue = Scalar()
)
  • src:输入图像。
  • dst:仿射变换后输出图像,与src数据类型相同,但是尺寸与dsize相同。
  • M:2×3的变换矩阵。
  • dsize:输出图像的尺寸。
  • flags:插值方法标志,可选参数及含义在表3-3和表3-4中给出。
  • borderMode:像素边界外推方法的标志。
  • borderValue:填充边界使用的数值,默认情况下为0。

该函数拥有多个参数,但是多数都与前面介绍的图像尺寸变换具有相同的含义。函数中第三个参数为前面求取的图像旋转矩阵,第四个参数是输出图像的尺寸。函数第五个参数是仿射变换插值方法的标志,这里相比于图像尺寸变换多增加了两个类型,可以与其他插值方法一起使用,这两种类型在表3-4中给出。函数第六个参数为像素边界外推方法的标志,其可以的标志和对应的方法在表3-5中给出。第七个参数是外推标志选择BORDER_CONSTANT时的定值,默认情况下为0。

在这里插入图片描述
在这里插入图片描述

在了解函数每个参数的含义之后,为了更好的理解函数作用,需要介绍一下仿射变换的概念。仿射变换就是图像的旋转、平移和缩放操作的统称,可以表示为线性变换和平移变换的叠加。仿射变换的数学表示是先乘以一个线形变换矩阵再加上一个平移向量,其中线性变换矩阵为2×2的矩阵,平移向量为2×1的向量,至此你可能理解了为什么函数需要输入一个2×3的变换矩阵。假设我们存在一个线性变换矩阵和平移矩阵,两者与输入的矩阵之间的关系如式(3.13)中所示。
在这里插入图片描述
根据旋转矩阵和平移矩阵以及图像像素值,仿射变换的数学原理可以用式(3.14)来表示。
在这里插入图片描述

  • src[]:原图像中的三个像素坐标。
  • dst[]:目标图像中的三个像素坐标。

该函数两个输入量都是存放浮点坐标的数组,在生成数组的时候像素点的输入顺序无关,但是需要保证像素点的对应关系,函数的返回值是一个2×3的变换矩阵。

有了前面变换矩阵的求取,就可以利用warpAffine()函数实现矩阵的仿射变换,我们在代码清单3-34的例程中实现了图像的旋转以及图像三点映射的仿射变换,最终结果在图3-23中给出。

#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"

using namespace std;
using namespace cv;

int main(int argc,char** argv) {
    cout<<"OpenCv Version: "<<CV_VERSION<<endl;
    Mat img=imread("699342568.jpg");
    if(img.empty()){
        cout<<"请确认输入的图像;路径是否正确"<<endl;
        return -1;
    }
    Mat img_;
    resize(img,img_,Size(img.rows/2,img.cols/2));
    imshow("src",img_);
    Mat rotation0,rotation1,img_warp0,img_warp1;
    double angle=30;//设置图像旋转的角度
    Size dst_size(img_.rows,img_.cols);//设置输出图像的尺寸
    Point2f center(img_.rows/2.0,img_.cols/2.0);//设置图像的旋转中心
    rotation0=getRotationMatrix2D(center,angle,1);//计算放射变换矩阵
    warpAffine(img_,img_warp0,rotation0,dst_size);//进行仿射变换
    imshow("img_warp0",img_warp0);
    //根据定义的三个点进行仿射变换
    Point2f src_points[3];
    Point2f dst_points[3];
    src_points[0]=Point2f(0,0);//原始图像的三个点
    src_points[1]=Point2f(0,(float)(img_.cols-1));
    src_points[2]=Point2f((float)(img_.rows-1),(float)(img_.cols-1));
    //仿射变换后图像中的三个点
    dst_points[0]=Point2f((float)(img_.rows)*0.11,(float)(img_.cols)*0.20);
    dst_points[1]=Point2f((float)(img_.rows)*0.15,(float)(img_.cols)*0.70);
    dst_points[0]=Point2f((float)(img_.rows)*0.81,(float)(img_.cols)*0.85);
    rotation1=getAffineTransform(src_points,dst_points);//根据对应点求取放射变换矩阵
    warpAffine(img_,img_warp1,rotation1,dst_size);//进行放射变换
    imshow("img_warp1",img_warp1);
    waitKey(0);
    return 0;
}

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Opencv-C++笔记 (12) : opencv-仿射变化 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器

随机推荐

  • Nginx Lua 实战

    在 nginx conf 中配置 在 http 节点中配置 location staticitem get default type text html content by lua file lua staticitem lua 创建 s
  • vue中axios的参数位置整理

    每次在进行前后端联调的时候 总是因为参数放不对而影响进度 我人都麻了 真的记不住 还是整理一下以便后续开发 一 vue2和vue3的接口请求头 vue 2 const res await this axios get vue 3 const
  • 数据结构课程设计——客运订票系统

    目录 2需求分析 2 1系统功能 3总体设计 3 1功能模块图 4详细设计 4 1 详细的设计思路 车次设置 订票模块的功能 退票模块的功能 管理员模块的功能 4 2 算法流程图 5编码 5 1数据结构定义 1 乘客信息 2 候补队列乘客信
  • JAVA代码审计从入门到精通2-JAVA WEB动态调试

    动态调试 在代码开发和代码分析的过程中需要对代码进行动态调试 动态调试是指利用集成环境 IDE 自带的调试器跟踪软件运行 协助解决和分析软件的bug 动态调试需要对程序设置断点 通过对程序的某行代码设置断点 当程序运行到此代码处会自动停止
  • Qt:自定义信号变量类型

    1 定义变量类型 struct User STRUCT 预测结果 2 在定义后面添加声明 告知所有用到该信号变量的对象 建议1 2 3 放在一个头文件 供所有类包含 Q DECLARE METATYPE User STRUCT 3 incl
  • ajax实验,基于Ajax技术的实验管理系统

    摘要 本文的研究来源于常州纺织服装职业技术学院实验教学管理系统 是常州纺织服装职业技术学院教务管理系统的子系统 该系统主要完成制定实验教学计划 网上选课 三方互动 在深入研究Ajax技术原理和工作流程的基础上 提出一个基于Ajax技术的实验
  • 自定义类型-结构体

    注 本文为C语言初阶内容 目录 1 结构体 1 1结构体的基础知识 声明和自引用 1 2结构体变量的定义和初始化 1 3结构体内存对齐和修改默认对齐数 1 4结构体传参 1 结构体 1 1结构体的基础知识 声明 初始化和自引用 结构体是一些
  • js实现高德地图实现科技感3d建筑模型显示示例

  • java创建数组的方式_Java创建数组的几种方式总结

    1 一维数组的声明方式 type arrayName 或 type arrayName 附 推荐使用第一种格式 因为第一种格式具有更好的可读性 表示type 是一种引用类型 数组 而不是type类型 建议不要使用第二种方式 下面是典型的声明
  • 如何从Process维度评估芯片面积

    如何从Process维度评估芯片面积 文章右侧广告为官方硬广告 与吾爱IC社区无关 用户勿点 点击进去后出现任何损失与社区无关 最近在小编知识星球上有不少星友问到工艺 Metal Stack 的相关问题 今天小编将从最基础的 Metal S
  • R语言中的t分布函数:学生t分布实践

    R语言中的t分布函数 学生t分布实践 学生t分布是统计学中常用的概率分布之一 在数据分析和假设检验中具有重要的应用 本文将介绍如何在R语言中使用学生t分布函数进行实践 并提供相应的源代码 首先 我们需要了解学生t分布的基本特性和应用场景 学
  • 华为OD机试 - 五子棋迷(Java)

    题目描述 张兵和王武是五子棋迷 工作之余经常切磋棋艺 这不 这会儿又下起来了 走了一会儿 轮张兵了 对着一条线思考起来了 这条线上的棋子分布如下 用数组表示 1 0 1 1 1 0 1 0 1 1 棋了分布说明 1代表白子 0代表空位 1
  • 华为OD机试 - 比较两个版本号的大小(Java )

    题目描述 输入两个版本号 version1 和 version2 每个版本号由多个子版本号组成 子版本号之间由 隔开 由大小写字母 数字组成 并且至少有一个字符 按从左到右的顺序比较子版本号 比较规则如下 子版本号前面的0不参与比较 比如
  • 利用强化学习进行股票操作实战(四)

    本次实战代码仍是在之前基础上进行了一些修改 之前只在一支股票上进行训练 这次我将模型放在多支股票上训练 并在多支股票上进行了测试 对于多支股票的训练策略 没有参考过别人的训练方案 做这个的比较少 我按自己的理解去训练 每一轮训练 都将每支股
  • 芯片面积估计方法

    一 概念 芯片面积的主要涵盖部分分为三部分 IO 芯片的信号及电源pad等 Standard cell 实现芯片的功能逻辑 Macro block 第三方IP PLL DAC POR Memory etc 芯片面积估计就是通过目标工艺的库信
  • Python:使用 print 打印“Hello World!”以及其它字符内容

    哈喽 大家好 我是wangzirui32 这是我的第一篇博文 发现内容有误还请多多提出 谢谢 今天 我们将使用Python的print 来帮助我们让程序输出指定内容 如果你的Python版本是3 x print 将作为一个Python内置函
  • 第五周总结&实验报告三

    实验三 String类的应用 实验目的 掌握类String类的使用 学会使用JDK帮助文档 实验内容 1 已知字符串 this is a test of java 按要求执行以下操作 要求源代码 结果截图 1 统计该字符串中字母s出现的次数
  • 全国计算机等级考试题库二级C操作题100套(第79套)

    第79套 给定程序中 函数fun的功能是 求ss所指字符串数组中长度最短的字符串所在的行下标 作为函数值返回 并把其串长放在形参n所指变量中 ss所指字符串数组中共有M个字符串 且串长
  • js 查找字符串中指定字符 模糊查询 不区分大小写

    js 查找特定字符 模糊查询 不区分大小写 var str hello world hello coder 查找 HELLO 是否存在 找不到返回null var reg new RegExp HELLO i var isHas str m
  • Opencv-C++笔记 (12) : opencv-仿射变化

    文章目录 一 概述 二 GetRotationMatrix2D 三 warpAffine 一 概述 介绍完图像的缩放和翻转后 接下来将要介绍图像的旋转 但是在OpenCV 4中并没有专门用于图像旋转的函数 而是通过图像的仿射变换实现图像的旋