OpenCV仿射变换和透视变换函数(C++)

news/2024/9/20 1:26:54/ 标签: opencv, c++, 人工智能

文章目录

    • 引言
    • 图像仿射变换 warpAffine()
      • 图像的旋转
      • 仿射变换
    • 透视变换 warpPerspective()
    • 透视变换例子
    • 参考文献

**仿射变换相关函数**
cv::transform():对一组点进行仿射变换
cv::warpAffine():对整幅图像进行仿射变换
cv::getAffineTransform():从一组点计算仿射变换矩阵
cv::getRotationMatrix2D():计算旋转矩阵
**投影变换相关的函数**
cv::perspectiveTransform():对一组点进行透射变换/投影变换
cv::warpPerspective():对整幅图像进行透视变换/投影变换
cv::getPerspectiveTransform():获取透视变换/投影变换矩阵
cv::findHomography():计算单应性矩阵

引言

图像的几何变换通常包括拉伸、缩放、扭曲和旋转等操作。

对于平面区域来说,分为两类几何转换:

  • 仿射变换(affine transform),基于2x3矩阵进行变换。指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够保持图像的平直性和平行性。平直性是指图像经过仿射变换后,直线仍然是直线;平行性是指图像在完成仿射变换后,平行线仍然是平行线
  • 透视变换(perspective transform),基于3x3矩阵进行变换。透视变换将视锥体转换为长方体形状,视锥体的近端比远端小,具有扩大相机附近物体的效果。透视变换可以改变平行关系,将矩形映射为任意四边形。

图像仿射变换 warpAffine()

图像的旋转

getRotationMatrix2D()函数通过输入旋转中心、旋转角度、旋转过程两轴的比例因子,获得一个Mat类型的旋转矩阵对象:

Mat cv::getRotationMatrix2D(Point2f center,double angle,double scale   //两轴的比例因子,输入1则不缩放)    

旋转变换是仿射变换的一个特殊情况,将此矩阵用于仿射变换函数即可仅作图像旋转

仿射变换

仿射变换又称为三点变换。如果知道目标变换前后的三个像素点坐标之间的关系,即可求出仿射变换矩阵M。

opencv提供了getAffineTransform函数用于计算仿射变换矩阵:

//只需要提供原图像和目标图像的三个点的坐标
Mat cv::getAffineTransform(const Point2f src[],const Point2f dst[]   //输入点类数组)
void cv::warpAffine(InputArray src,OutputArray dst,InputArray M,        //仿射变换矩阵MSize dsize,int flags = INTER_LINEAR,    //插值方法int borderMode = BORDER_CONSTANT,    //像素边界外推方法const Scalar & nprderValue = Scalar())

注:仿射变换的矩阵M是2×3的矩阵

透视变换 warpPerspective()

透视变换:按照物体的成像投影规律将图像重新投影。常见用例是修正镜头与拍摄目标存在斜角时产生的图像畸变。
在这里插入图片描述

使用getPerspectiveTransform()函数获取变换矩阵

//只需要提供原图像和目标图像的四个点的坐标
Mat cv::getPerspectiveTransform(const Point2f src[],const Point2f dst[],int solveMethod = DECOMP_LU //求解方法                             )

在不知道四个坐标点的情况下,可以使用原图和目标图的匹配点计算变换矩阵:

Mat cv::findHomography	(	InputArray 	srcPoints,InputArray 	dstPoints,int 	method = 0,double 	ransacReprojThreshold = 3,OutputArray 	mask = noArray(),const int 	maxIters = 2000,const double 	confidence = 0.995 
)

method参数详解:

method	计算单应矩阵所使用的方法。不同的方法对应不同的参数,具体如下:
0 - 利用所有点的常规方法
RANSAC - RANSAC-基于RANSAC的鲁棒算法
LMEDS - 最小中值鲁棒算法
RHO - PROSAC-基于PROSAC的鲁棒算法

使用warpPerspective()函数应用透视变换

void cv::warpPerspective(InputArray src,OutputArray dst,InputArray M,        //变换矩阵MSize dsize,int flags = INTER_LINEAR,    //插值方法int borderMode = BORDER_CONSTANT,    //像素边界外推方法const Scalar & nprderValue = Scalar())

注:透视变换的矩阵M是3×3的矩阵

透视变换例子

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;struct callbackP
{Mat src;int clickTimes = 0;        //在图像上单击次数vector<Point2f> srcTri;
};void onMouse(int event, int x, int y, int flags, void *utsc)
{callbackP cp = *(callbackP*)utsc;  // 先转换类型,再取数据if (event == EVENT_LBUTTONUP)      //响应鼠标左键事件{circle((*(callbackP*)utsc).src, Point(x, y), 2, Scalar(0, 0, 255), 2);  //标记选中点imshow("wait ", (*(callbackP*)utsc).src);(*(callbackP*)utsc).srcTri.push_back(Point2f(x, y));cout << "x:" << x << " " << "y:" << y << endl;(*(callbackP*)utsc).clickTimes++;if ((*(callbackP*)utsc).clickTimes == 4){cout << "按任意键继续!" << endl;}}
}int main(int argc, char *argv[])
{vector<Point2f> dstTri(4);Mat dst;callbackP utsc;utsc.src = imread("tt.jpg");namedWindow("src", WINDOW_AUTOSIZE);imshow("src", utsc.src);cout << "从需要透视变换区域的左上角开始,顺时针依次点矩形的四个角!" << endl;setMouseCallback("src", onMouse, (void*)&utsc);  //类型转换waitKey();if (utsc.clickTimes == 4){dstTri[0].x = 0;dstTri[0].y = 0;dstTri[1].x = utsc.srcTri[1].x - utsc.srcTri[0].x;dstTri[1].y = 0;dstTri[2].x = utsc.srcTri[1].x - utsc.srcTri[0].x;dstTri[2].y = utsc.srcTri[2].y - utsc.srcTri[1].y;dstTri[3].x = 0;dstTri[3].y = utsc.srcTri[2].y - utsc.srcTri[1].y;//计算透视矩阵Mat M = findHomography(utsc.srcTri, dstTri, RANSAC);//图像透视变换warpPerspective(utsc.src, dst, M, Size((utsc.srcTri[1].x - utsc.srcTri[0].x), (utsc.srcTri[2].y - utsc.srcTri[1].y)));imshow("output", dst);imwrite("3p.jpg", dst);cout << "透视变换矩阵:" << M << endl;waitKey();}else{cout << "需要从左上角开始,顺时针依次点矩形的四个角!" << endl;cout << "现在点击了" << utsc.clickTimes << "次" << endl;}在这里插入图片描述cv::destroyAllWindows();return 0;
}

在这里插入图片描述

参考文献

图像几何变换(仿射变换和透视变换…)及python-opencv实现
OpenCV学习笔记 02
opencv的单应性矩阵


http://www.ppmy.cn/news/1523450.html

相关文章

Qt篇——Qt在msvc编译下提示“C2001:常量中有换行符“的错误

在pro文件中添加以下配置即可&#xff1a; msvc{QMAKE_CFLAGS /utf-8QMAKE_CXXFLAGS /utf-8 }

Flask中的上下文(Context)

Flask中的上下文&#xff08;Context&#xff09;是一个核心概念&#xff0c;它对于理解和使用Flask框架进行Web开发至关重要。上下文在编程中通常指的是程序执行到某一时刻时&#xff0c;环境所提供的一系列状态信息&#xff0c;这些状态信息可以是变量、函数、类等&#xff0…

[Redis] Redis中的String类型

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

【机器学习】12. 线性回归 Residual 残差系数 R方

Sum of Squares Total (SST) 单个数据点&#xff08;观测值&#xff09;于响应变量的均值差的平方和。 Sum of Squares Regression (SSR) 预测值ŷi与响应变量均值差的平方和。 Sum of Squares Error (SSE) 预测值ŷi与观测值差的平方和。 R 2 1 − S S E / S S T S S R / …

前端技术(七)——less 教程

一、less简介 1. less是什么&#xff1f; less是一种动态样式语言&#xff0c;属于css预处理器的范畴&#xff0c;它扩展了CSS语言&#xff0c;增加了变量、Mixin、函数等特性&#xff0c;使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 &#xff0c;也可以借助Node.js在服…

一台笔记本电脑的硬件都有哪些以及对应的功能

一台笔记本电脑的硬件通常包括多个关键组件&#xff0c;这些组件共同协作&#xff0c;确保电脑的正常运行。以下是笔记本电脑的主要硬件及其功能&#xff1a; 1. 中央处理器&#xff08;CPU&#xff09; 功能&#xff1a;CPU 是电脑的“大脑”&#xff0c;负责处理所有的计算…

bit-fields 生成macros

‌Bit-Fields Macros定义‌ Bit-fields macros是在C或C语言中&#xff0c;‌利用宏定义&#xff08;‌macros&#xff09;‌来方便地创建和操作位字段&#xff08;‌bit-fields&#xff09;‌的一种方式。‌位字段常用于节省内存&#xff0c;‌通过在一个字节中打包多个布尔值或…

【PHP小课堂】简单入门PHP中的过滤器相关函数

简单入门PHP中的过滤器相关函数 一般在业务开发中&#xff0c;我们对于一些参数数据的过滤大部分还是使用传统的 if 以及正则进行判断过滤。但其实 PHP 中也提供了一些过滤器&#xff0c;可以帮助我们方便地进行数据的过滤筛选以及部分替换操作。今天我们就来简单的学习一下这些…

设计模式之状态模式 (C++ 实现)

设计模式是软件开发中的一项重要技能&#xff0c;它提供了一种通用的解决方案以应对不同的设计问题。状态模式是一种行为型设计模式&#xff0c;适用于对象在不同状态下表现出不同的行为。通过实现状态模式&#xff0c;可以让代码更清晰、更易扩展与维护。本文将通过C实现状态模…

【开发工具】Maven Dependency Helper:IntelliJ IDEA的贴心助手,助力梳理依赖关系

一、引言 在Java项目开发过程中&#xff0c;依赖管理是一个至关重要的环节。Maven作为一个优秀的构建工具&#xff0c;已经成为了Java项目标配。然而&#xff0c;在管理项目依赖时&#xff0c;我们常常会遇到各种问题&#xff0c;如依赖冲突、依赖版本不兼容等。为了让开发者更…

菜鸟养成记第10集(滑窗算法)

固定窗口 示例 假设有一个数组 nums [1, 3, -1, -3, 5, 3, 6, 7]&#xff0c;我们需要找到长度为 3 的最大子数组之和。 nums [1, 3, -1, -3, 5, 3, 6, 7] window_size 3 max_sum float(-inf)for i in range(len(nums) - window_size 1):current_sum sum(nums[i:i wi…

华为OD机试 - 最大相连男生数 - 矩阵(Java 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

数据结构代码集训day16(适合考研、自学、期末和专升本)

本题来自B站up&#xff1a;白话拆解数据结构 今日题目就一个&#xff1a;约瑟夫环问题。 一个圈共有N个人&#xff08;N为不确定的数字&#xff09;&#xff0c;第一个人的编号为0或者1&#xff08;两个都可以&#xff0c;看你的程序如何编写&#xff09;&#xff0c;假设这边我…

通过SSH服务远程操作Linux(ubuntu)主机

首先SSH是什么&#xff1f;SSH&#xff08;Secure SHell&#xff09;是Linux、Unix、Mac及其他网络设备最常用的远程CLI管理协议&#xff0c;SSH使用秘钥对数据进行加密&#xff0c;保证了远程管理数据的安全性。Secure Shell (SSH) 是一种网络协议&#xff0c;允许用户通过加密…

算法设计与分析第一堂课笔记复习

算法是解决问题的一种方法或一个过程&#xff0c;是由若干条指令组成的又穷序列&#xff0c; 算法的性质 输入&#xff1a;有零个或多个输出&#xff1a;“至少一个”确定性&#xff1a;组成算法的每条指令清晰无歧义有限性&#xff1a;算法中每条指令和执行次数和执行时间都是…

NASA数据集:ASTER L2 地表辐射率 VNIR 和 SWIR V003

目录 简介 摘要 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ASTER L2 地表辐射率 VNIR 和 SWIR V003 简介 ASTER 地表辐照度可见近红外和短波红外(AST_09)是一个多文件产品(https://lpdaac.usgs.gov/documents/996/ASTER_Earthdata_Search_Order_Instruct…

考场考生行为检测数据集 7000张 带标注 voc yolo

数据集名称&#xff1a; 考场考生行为检测数据集 数据集规模&#xff1a; 图像数量&#xff1a;7000张标注类型&#xff1a;行为检测&#xff08;例如&#xff1a;作弊、玩手机、睡觉等&#xff09;格式兼容性&#xff1a;支持VOC和YOLO标注格式 数据集内容&#xff1a; 该…

K8S介绍及Kubeadm方式安装K8S(前期工作)

1.K8S介绍 1.Kubernetes简介 Kubernetes 缩写&#xff1a;K8S&#xff0c;k 和 s 之间有八个字符&#xff0c;所以因此得名。 Kubernetes 由 google 的 Brog 系统作为原型&#xff0c;后经 Go 语言延用 Brog 的思路重写&#xff0c;并捐献给 CNCF 基金会开源。 Kubernetes …

算法类学习笔记 ———— 障碍物检测

文章目录 介绍基于图像的障碍物检测基于二维图像的障碍物检测YOLO系列障碍物检测SSD障碍物检测Faster RCNN障碍物检测 基于图像的三位障碍物检测 基于激光雷达的障碍物检测基于几何特征和网格边缘模板的创建非最大值抑制原理提取边缘信息 VoxelNet障碍物检测 基于视觉和激光雷达…

计算机毕业设计 智能推荐旅游平台 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…