7.6透视变换

基本概念

在计算机视觉和图像处理领域中,透视变换(Perspective Transformation)是一种重要的几何变换,用于模拟从一个视角到另一个视角的变换,比如从鸟瞰视角到正面视角的变换。透视变换通常用于图像配准、增强现实、三维重建等场景。

透视变换的基本概念

透视变换是一种非线性的几何变换,它通过一个3x3的矩阵来描述,这个矩阵可以将一个平面的坐标映射到另一个平面上。

OpenCV中的透视变换

在OpenCV中,透视变换可以通过 warpPerspective 函数来实现。这个函数需要一个3x3的变换矩阵来指定变换。

函数原型

void warpPerspective(InputArray src,OutputArray dst,InputArray M,Size dsize,int flags = INTER_LINEAR,int borderMode = BORDER_CONSTANT,const Scalar& borderValue = Scalar()
);参数说明
•src:输入图像。
•dst:输出图像。
•M:一个3x3的透视变换矩阵。
•dsize:输出图像的大小。
•flags:插值方法,默认为 INTER_LINEAR(双线性插值)。
•borderMode:边界处理方法,默认为 BORDER_CONSTANT。
•borderValue:如果使用了 BORDER_CONSTANT,则需要指定边界值。

创建透视变换矩阵

透视变换矩阵通常是通过一组对应点来计算的。给定四组对应点,可以使用 findHomography 或 getPerspectiveTransform 函数来计算变换矩阵。

示例代码1

下面是一个使用OpenCV C++实现透视变换的示例代码:

#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;// 定义透视变换
void applyPerspectiveTransform(const Mat &src, Mat &dst, const Mat &M, Size dsize) 
{warpPerspective(src, dst, M, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar(0));
}int main(int argc, char** argv) 
{//if (argc != 2)//{//	cout << "Usage: ./PerspectiveTransform <Image Path>" << endl;//	return -1;//}// 加载图像Mat img = imread("586.jpeg");if (!img.data) {cout << "Error opening image" << endl;return -1;}// 定义对应点vector<Point2f> pts1, pts2;// 输入图像的四个角点pts1.push_back(Point2f(0, 0));pts1.push_back(Point2f(img.cols, 0));pts1.push_back(Point2f(img.cols, img.rows));pts1.push_back(Point2f(0, img.rows));// 输出图像的目标四个角点pts2.push_back(Point2f(0, 0));pts2.push_back(Point2f(img.cols / 2, 0));pts2.push_back(Point2f(img.cols / 2, img.rows));pts2.push_back(Point2f(0, img.rows));// 计算透视变换矩阵Mat M = getPerspectiveTransform(pts1, pts2);// 定义输出图像大小Size dsize(img.cols, img.rows);// 初始化输出矩阵Mat transformed;// 应用透视变换applyPerspectiveTransform(img, transformed, M, dsize);// 显示结果namedWindow("Original Image", WINDOW_NORMAL);imshow("Original Image", img);namedWindow("Flipped Center", WINDOW_NORMAL);imshow("Flipped Center", transformed);waitKey(0);destroyAllWindows();return 0;
}代码解释
1. 加载图像:使用 imread 函数加载图像。
2. 定义对应点:定义输入图像的四个角点和输出图像的目标四个角点。
3. 计算透视变换矩阵:使用 getPerspectiveTransform 函数计算透视变换矩阵。
4. 定义输出图像大小:保持输出图像大小不变。
5. 初始化输出矩阵:创建一个新的矩阵来存储变换后的图像。
6. 应用透视变换:使用 warpPerspective 函数应用透视变换。
7. 显示结果:使用 imshow 函数显示原始图像和变换后的图像。

运行结果1

在OpenCV中,透视变换是一种非常强大的图像处理技术,它允许你在二维平面上模拟三维空间中的视点变化。这种变换特别适用于需要进行图像校正或模拟不同视角的应用场景,例如文档扫描、图像拼接等。

透视变换通常涉及一个3x3的矩阵,该矩阵可以将输入图像中的四点映射到输出图像中的另外四点。在C++中使用OpenCV进行透视变换的基本步骤如下:

在C++中使用OpenCV进行透视变换的基本步骤如下:1. 导入必要的头文件
首先确保你的项目中包含了OpenCV的头文件。
#include <opencv2/opencv.hpp>
using namespace cv;2. 加载图像
使用imread函数读取一幅图像,并检查是否正确加载。
Mat src = imread("path/to/image.jpg");
if (src.empty()) {std::cout << "Error: Image not found or unable to open" << std::endl;return -1;
}3. 定义源点和目标点
你需要定义源图像上的四个角点以及目标图像上的对应位置。这些点应该按照顺序(例如顺时针或逆时针)指定。
Point2f src_pts[4];
Point2f dst_pts[4];// 源点
src_pts[0] = Point2f(0, 0);
src_pts[1] = Point2f(src.cols - 1, 0);
src_pts[2] = Point2f(src.cols - 1, src.rows - 1);
src_pts[3] = Point2f(0, src.rows - 1);// 目标点
dst_pts[0] = Point2f(0, 0);
dst_pts[1] = Point2f(dst.cols - 1, 0);
dst_pts[2] = Point2f(dst.cols - 1, dst.rows - 1);
dst_pts[3] = Point2f(0, dst.rows - 1);4. 计算透视变换矩阵
使用getPerspectiveTransform函数来计算从源点到目标点的透视变换矩阵。
Mat M = getPerspectiveTransform(src_pts, dst_pts);5. 应用透视变换
利用warpPerspective函数应用计算出的变换矩阵来对原始图像进行变形。
Mat dst;
warpPerspective(src, dst, M, Size(dst.cols, dst.rows));6. 显示结果
最后,你可以使用imshow函数显示变换后的图像,并等待用户按键后退出。
namedWindow("Result", WINDOW_NORMAL);
imshow("Result", dst);
waitKey(0); // Wait for a keystroke in the window请注意,上述代码示例中的目标图像尺寸(dst.cols 和 dst.rows)需要根据实际情况设定。如果你想要创建一个新的大小,而不是直接复制源图像的大小,可以在调用warpPerspective时指定新的尺寸。透视变换的原理较为复杂,涉及到线性代数中的矩阵运算,如果你对数学原理感兴趣,建议深入学习相关的数学背景知识。

示例代码2


#include <opencv2/opencv.hpp>
using namespace cv;int main()
{Mat src = imread("89.jpeg");if (src.empty()){std::cout << "Error: Image not found or unable to open" << std::endl;return -1;}Point2f src_pts[4];Point2f dst_pts[4];//Mat dst(src.cols / 2, src.rows/2,CV_8SC3);// 源点src_pts[0] = Point2f(0, 0);src_pts[1] = Point2f(src.cols - 1, 0);src_pts[2] = Point2f(src.cols - 1, src.rows - 1);src_pts[3] = Point2f(0, src.rows - 1);// 目标点dst_pts[0] = Point2f(0, 0);
//	dst_pts[1] = Point2f(dst.cols - 1, 0);
//dst_pts[2] = Point2f(dst.cols - 1, dst.rows - 1);
//	dst_pts[3] = Point2f(0, dst.rows - 1);dst_pts[1] = Point2f(src.cols/2 - 1, 0);dst_pts[2] = Point2f(src.cols / 2 - 1, src.rows/2 - 1);dst_pts[3] = Point2f(0, src.rows / 2 - 1);Mat M = getPerspectiveTransform(src_pts, dst_pts);Mat dst;warpPerspective(src, dst, M, Size(dst.cols, dst.rows));namedWindow("源图", WINDOW_NORMAL);imshow("源图", src);namedWindow("Result", WINDOW_NORMAL);imshow("Result", dst);waitKey(0); // Wait for a keystroke in the windowreturn 0;
}

运行结果2

透视变换的常见应用场景

•图像配准:将两张或多张图像对齐,使它们之间的相对位置一致。

•三维重建:通过多视角的图像重建三维模型。

•增强现实:在实时视频流中添加虚拟对象,使其看起来像是在现实世界中存在。

示例代码3

计算透视变换矩阵的示例

下面是使用 findHomography 计算透视变换矩阵的示例代码:
#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;void calculatePerspectiveTransform(const Mat &src, Mat &M, const vector<Point2f> &pts1, const vector<Point2f> &pts2)
{// 使用findHomography计算透视变换矩阵M = findHomography(pts1, pts2);
}// 定义透视变换
void applyPerspectiveTransform(const Mat &src, Mat &dst, const Mat &M, Size dsize)
{warpPerspective(src, dst, M, dsize, INTER_LINEAR, BORDER_CONSTANT, Scalar(0));
}int main(int argc, char** argv)
{/*if (argc != 2){cout << "Usage: ./PerspectiveTransform <Image Path>" << endl;return -1;}*/// 加载图像Mat img = imread("896.png");if (!img.data) {cout << "Error opening image" << endl;return -1;}// 定义对应点vector<Point2f> pts1, pts2;// 输入图像的四个角点pts1.push_back(Point2f(0, 0));pts1.push_back(Point2f(img.cols, 0));pts1.push_back(Point2f(img.cols, img.rows));pts1.push_back(Point2f(0, img.rows));// 输出图像的目标四个角点pts2.push_back(Point2f(0, 0));pts2.push_back(Point2f(img.cols / 2, 0));pts2.push_back(Point2f(img.cols / 2, img.rows));pts2.push_back(Point2f(0, img.rows));// 计算透视变换矩阵Mat M;calculatePerspectiveTransform(img, M, pts1, pts2);// 定义输出图像大小Size dsize(img.cols, img.rows);// 初始化输出矩阵Mat transformed;// 应用透视变换applyPerspectiveTransform(img, transformed, M, dsize);// 显示结果namedWindow("Original Image", WINDOW_NORMAL);imshow("Original Image", img);namedWindow("Transformed Image", WINDOW_NORMAL);imshow("Transformed Image", transformed);waitKey(0);destroyAllWindows();return 0;
}代码解释
1. 加载图像:使用 imread 函数加载图像。
2. 定义对应点:定义输入图像的四个角点和输出图像的目标四个角点。
3. 计算透视变换矩阵:使用 findHomography 函数计算透视变换矩阵。
4. 定义输出图像大小:保持输出图像大小不变。
5. 初始化输出矩阵:创建一个新的矩阵来存储变换后的图像。
6. 应用透视变换:使用 warpPerspective 函数应用透视变换。
7. 显示结果:使用 imshow 函数显示原始图像和变换后的图像。

运行结果3

通过这些示例,你应该能够理解如何在OpenCV中使用C++实现透视变换。透视变换是一个强大的工具,用于模拟复杂的视角变换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1549663.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

《志愿军·存亡之战》首映礼热血与感动并存,陈飞宇一年后再报这串番号

9月27日&#xff0c;国庆档电影《志愿军&#xff1a;存亡之战》在北京举行首映礼。导演陈凯歌&#xff0c;总制片人陈红&#xff0c;编剧张珂&#xff0c;演员朱一龙、辛柏青、张子枫、朱亚文、陈飞宇、张宥浩等在映后齐亮相。其中陈飞宇饰演的孙醒&#xff0c;作为贯穿一、二两…

如何快速自定义一个Spring Boot Starter!!

目录 引言&#xff1a; 一. 我们先创建一个starter模块 二. 创建一个自动配置类 三. 测试启动 引言&#xff1a; 在我们项目中&#xff0c;可能经常用到别人的第三方依赖&#xff0c;又是引入依赖&#xff0c;又要自定义配置&#xff0c;非常繁琐&#xff0c;当我们另一个项…

【C++报错已解决】std::ios_base::floatfield

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

8609 哈夫曼树

### 思路 1. **选择最小权值节点**&#xff1a;在哈夫曼树构建过程中&#xff0c;选择两个权值最小且父节点为0的节点。 2. **构建哈夫曼树**&#xff1a;根据权值构建哈夫曼树&#xff0c;确保左子树权值小于右子树权值。 3. **生成哈夫曼编码**&#xff1a;从叶子节点到根节点…

极限基本类型小结

极限基本类型小结 在之前的文章中已经看过了极限的多种基本类型&#xff0c;下面展示一些各种基本类型的代表性的图像&#xff0c;通过观察下面的图像可以帮助我们回顾函数在趋近于某一点时函数值的行为&#xff08;这也叫极限值&#xff09;&#xff0c;也生动的描述了各种极…

初始爬虫9

1.元素定位后的操作 “find_element“仅仅能够获取元素&#xff0c;不能够直接获取其中的数据&#xff0c;如果需要获取数据需要使用以下方法”。下面列出了两个方法&#xff1a; 获取文本 element.text 通过定位获取的标签对象的 text 属性&#xff0c;获取文本内容 获取属性…

C语言进阶版第13课—字符函数和字符串函数2

文章目录 1. strstr函数的使用和模拟实现1.1 strstr函数的使用1.2 模拟实现strstr函数1.3 strstr函数和strncpy函数、puts函数的混合使用 2. strtok函数的使用**3. strerror函数的使用** 1. strstr函数的使用和模拟实现 1.1 strstr函数的使用 strstr函数是用来通过一个字符串来…

Linux进程-2

一&#xff1a;进程优先级 基本概念 cpu资源分配的先后顺序&#xff0c;就是指进程的优先权&#xff08;priority&#xff09;。 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用&#xff0c;可以改善系统性能。 还可以把进程运行到指定的CPU上&#…

Mysql数据库相关操作总结

目录 1.背景知识 2.创建数据库 2.1创建指令 2.2字符集 3.查看数据库 3.选中数据库 4.删除数据库 5.数据表的操作 5.1基本数据类型 5.2创建表 5.3查看所有的表 5.4查看表的结构 5.5删除表 6.CRUD增删查改 6.1新增和效果查看 6.3删除 6.4查找 1.背景知识 数据库就…

哈希知识点总结:哈希、哈希表、位图、布隆过滤器

目录 哈希 哈希表 哈希常用方法 1、直接定址法 2、存留余数法 哈希冲突 哈希冲突的解决办法 1、闭散列&#xff1a;开放定址法 &#xff08;1&#xff09;线性探测法 &#xff08;2&#xff09;二次探测法 2、开散列 哈希桶 / 拉链法 哈希的运用 位图 set操作 …

3-3 AUTOSAR RTE 对SR Port的作用

返回总目录->返回总目录<- 一、前言 RTE作为SWC和BSW之间的通信机构,支持Sender-Receiver方式实现ECU内及ECU间的通信。 对于Sender-Receiver Port支持三种模式: 显式访问:若运行实体采用显示模式的S/R通信方式,数据读写是即时的;隐式访问:当多个运行实体需要读取…

Docker安装与应用

前言 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言开发。Docker 可以让开发者打包他们的应用以及依赖包到一个轻 量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互 之间…

关于Fake Location定位,运动世界校园问题

不好意思&#xff0c;之前那个文章其实是很早之前的&#xff0c;不知道为什么审核了很久一直没有通过&#xff0c;然后前几周莫名其妙点了一下重新发布&#xff0c;竟然发布成功了&#xff0c;这个方法已经失效了&#xff0c;要可以稳定&#xff0c;我建议是买一台root的手机&a…

鸿蒙开发(NEXT/API 12)【硬件(传感器开发)】传感器服务

使用场景 Sensor Service Kit&#xff08;传感器服务&#xff09;使应用程序能够从传感器获取原始数据&#xff0c;并提供振感控制能力。 Sensor&#xff08;传感器&#xff09;模块是应用访问底层硬件传感器的一种设备抽象概念。开发者可根据传感器提供的相关接口订阅传感器…

Docker容器的使用

前提条件 Linux环境安装好Docker&#xff0c;可参考Rocky Linux9下安装Docker和卸载Docker Docker命令图 帮助命令 帮助命令&#xff0c;查看有哪些命令可以用 [rootlocalhost ~]# docker --help ​ 查看某个命令的帮助&#xff0c;例如&#xff1a;run [rootlocalhost ~]# …

深入探索机器学习中的目标分类算法

在当今数据驱动的世界中&#xff0c;机器学习&#xff08;Machine Learning, ML&#xff09;正逐渐成为解决问题的重要工具。在众多机器学习任务中&#xff0c;目标分类&#xff08;Classification&#xff09;算法尤其受到关注。本文将深入探讨目标分类算法的基本概念、常见类…

【刷点笔试面试题试试水】 i++与++i哪个效率更高?

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: 都应该知道,i是先增加再参与计算. i是先计算再增加. 原理是i,是直接返…

免费的录屏软件有哪些?可以试试这4款。

录屏软件已经被用于很多的领域和场景当中&#xff0c;能够帮助我们进行在线教学&#xff0c;线上培训&#xff0c;游戏直播与分享&#xff0c;视频记录等等。并且很多的录屏软件都有免费的功能&#xff0c;它们让大家的录屏变得更加的方便。如果大家需要录屏工具的话&#xff0…

认知杂谈92《菜鸟的自我修炼:守住存款,识别诱惑》

内容摘要&#xff1a; “快速致富"的口号在网络和广告中无处不在&#xff0c;它们吸引着渴望改变生活的人。然而&#xff0c;这些诱惑常常是精心设计的骗局&#xff0c;利用人的贪婪本性。成功学导师们宣扬的"成功秘诀"和"快速通道”&#xff0c;让人陷入不…

【MATLAB代码】三维空间上的RSS(信号强度)定位,n个锚点自适应(锚点数>3即可)(源代码下载链接)

文章目录 代码概况源代码运行结果RSS定位原理讲解1.基本概念2.信号强度与距离关系3. 定位原理 其他情况 代码概况 基于MATLAB的定位程序&#xff0c;使用RSS&#xff08;接收信号强度&#xff09;来估计距离&#xff0c;再由距离计算位置&#xff0c;用于三维空间上的定位。调…