OpenCV : 投影变换

article/2025/10/1 17:32:22

投影变换

物体在三维空间发生了旋转,叫做投影变换.由于可能出现阴影或遮挡,所以变换后较难复原.如果物体时平面的,就可以通过投影变换物体三维变换进行模型化,这叫做专用的二维投影变换.

矩阵表示:
[ x ~ y ~ z ~ ] = [ a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ] [ x y z ] \left[\begin{matrix}\tilde{x} \\ \tilde{y}\\ \tilde{z}\end{matrix}\right] = \left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22}& a_{23}\\ a_{31} & a_{32} & a_{33}\end{matrix}\right] \left[\begin{matrix}x \\ y \\ z\end{matrix}\right] x~y~z~=a11a21a31a12a22a32a13a23a33xyz

求投影矩阵

  • getPerspectiveTransform(src, dst)
    1. src : 原坐标
    2. dst : 变换后的坐标
    3. 返回结果为:3x3的投影矩阵,数据类型为CV_64F

计算投影矩阵

#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>using namespace cv;
using namespace std;int main()
{//原坐标Point2f src[] = { Point2f(0, 0), Point2f(20, 0), Point2f(0, 20), Point2f(20, 20) };//投影后的坐标Point2f dst[] = { Point2f(10, 20),Point2f(20, 2), Point2f(50, 70), Point2f(25, 7) };Mat P =getPerspectiveTransform(src, dst);cout << P << endl;return 0;
}
#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>using namespace cv;
using namespace std;int main()
{//原坐标Mat src = (Mat_<float>(4, 2) << 0, 0, 20, 0, 0, 20, 20, 20);//投影后的坐标Mat dst = (Mat_<float>(4, 2) << 10, 2, 20, 2, 5, 7, 25, 7);Mat P =getPerspectiveTransform(src, dst);cout << P << endl;return 0;
}

图像的投影变换

  • warpPerspective(Mat src, Mat dst, Mat P, Size dsize)
    1. src : 原图
    2. dst : 输出图片
    3. P : 投影矩阵
    4. dsize : 输出图像大小
  • circle(Mat img, Point center, int radius, const Scalar & color, int thickness=1, int lineType=8, int shift=0)
    1. img : 图像矩阵(2d)
    2. center : 圆心坐标
    3. radius : 半径长度
    4. color : 颜色
    5. thickness : 线的粗细
    6. lineType : 线的类型
  • OpenCV中其他类似的方法还有:rectangle, ellipse, line(矩形,椭圆,线段)
#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>using namespace cv;
using namespace std;int main()
{Mat img = imread("./People/5g.jpg", 1);Mat src = (Mat_<float>(4, 2)<< 0, 0, 1000, 0, 0, 1000, 1000, 1000);Mat dst = (Mat_<float>(4, 2) << 0, 0, 1000, 0, 300, 1000, 600, 1000);Mat P = getPerspectiveTransform(src, dst);Mat O;cout << "rows : " << img.rows << endl;cout << "cols : " << img.cols << endl;warpPerspective(img, O, P, img.size());imshow("PerspectiveTransform", O);waitKey(0);return 0;
}

原图

在这里插入图片描述

投影后

在这里插入图片描述

通过鼠标点击事件,进行图像投影

#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>using namespace cv;
using namespace std;Mat I_img;    // 输入图片
Mat P_img;  // 投影后的图片
Point2f src_point[4];    // 原坐标
Point2f dst_point[4];    // 投影后的坐标
int i = 0, j = 0;               // 记录点击次数
Point2f point_i, point_p;// 同鼠标事件获得原图中坐标
void mouse_I(int event, int x, int y, int flags, void* param)
{switch (event){case CV_EVENT_LBUTTONDOWN:point_i = Point2f(x, y);break;case CV_EVENT_LBUTTONUP:src_point[i] = point_i;circle(I_img, src_point[i], 7, Scalar(0), 3);   //画出点击的坐标i += 1;break;default:break;}
}// 在画布上选择投影后的坐标
void mouse_pI(int event, int x, int y, int flags, void* param)
{switch (event){case CV_EVENT_LBUTTONDOWN:point_p = Point2f(x, y);break;case CV_EVENT_LBUTTONUP:dst_point[j] = point_p;circle(P_img, dst_point[j], 7, Scalar(0), 3);j += 1;break;default:break;}
}int main()
{I_img = imread("./People/5.jpg", CV_LOAD_IMAGE_GRAYSCALE);if (!I_img.data)return -1;P_img = 255 * Mat::ones(I_img.size(), CV_8UC1);namedWindow("Original Image");setMouseCallback("Original Image", mouse_I, NULL);namedWindow("Output Image");setMouseCallback("Output Image", mouse_pI, NULL);imshow("Original Image", I_img);imshow("Output Image", P_img);while (!(i == 4 && j == 4)){imshow("Original Image", I_img);imshow("Output Image", P_img);if (waitKey(50) == 'q')break;}imshow("Original Image", I_img);imshow("Output Image", P_img);// 撤销鼠标事件setMouseCallback("Original Image", NULL, NULL);setMouseCallback("Output Image", NULL, NULL);// 计算投影矩阵Mat P = getPerspectiveTransform(src_point, dst_point);// 投影变换Mat R;warpPerspective(I_img, R, P, I_img.size());imshow("Persepctive Result", R);waitKey(0);return 0;
}

选择原坐标

在这里插入图片描述

选定投影后的坐标

在这里插入图片描述

投影后的图片

在这里插入图片描述


http://chatgpt.dhexx.cn/article/Vk7WoBOJ.shtml

相关文章

Halcon 第七章『图像的几何变换』◆第2节:投影变换

一、介绍 投影变换也叫透射变换、投影映射。透射变换是将图像投影到一个新的视平面&#xff0c;是一种二维坐标到三维坐标的变换。 透射变换是仿射变换的延续&#xff0c;也可以说仿射变换是透射变换的一种特殊形式。其特殊性在于变换后图像的形状仍然维持原状。投影变换包括的…

投影变换原理和用法

一、定义&#xff1a;投影变换也叫透射变换、投影映射。透射变换是将图像投影到一个新的视平面&#xff0c;是一种二维坐标到三维坐标的变换。 透射变换是仿射变换的延续&#xff0c;也可以说仿射变换是透射变换的一种特殊形式。其特殊性在于变换后图像的形状仍然维持原状。投影…

基于libVLC的视频播放器之四:直接使用libVLC

一.效果 播放本地文件 播放网络url:rtsp://3.84.6.190/vod/mp4:BigBuckBunny_115k.mov 二.实现 既然有VLC-Qt,为什么还要直接调用libVLC呢,因为直接调用会加深对整个播放流程的理解,方便后面修改VLC-Qt源码。

MFC调用vlc动态库libvlc.dll实现简单播放器 中文路径处理

一、简单说明 本文讲解利用MFC调用vlc&#xff08;2.0.0&#xff09;的动态库实现简单的播放器&#xff0c;实现播放、暂停、停止、音量控制、进度控制&#xff0c;支持中文路径等。 VLC 中文路径转码问题<转> 最近用MFC编写调用libVLC的程序时碰到中文路径不能打开的问题…

VLC-Android编译

1.环境 硬核条件----------linux(这里用ubuntu代替)15.5.1 build-15018445 PS&#xff1a;这里安装好虚拟机以后&#xff0c;尽可能分配大内存(8GB起步)&#xff0c;如果电脑本地不允许开这么大的内存给虚拟机&#xff0c;则本博文后面的内容可能帮助不大。 安装好虚拟机后&am…

VLC介绍以及库的使用

VLC原指VideoLAN客户端(VideoLANClient)&#xff0c;是一款开源的、跨平台的、可扩展的、多媒体播放器、流媒体服务器及框架&#xff0c;可播放大多数多媒体文件&#xff0c;以及DVD、音频CD、VCD及各类流媒体协议&#xff0c;现更名为VLC media player&#xff0c;最新版本为2…

LibVLC —— 常用函数解析

函数 ● LIBVLC_API libvlc_instance_t *libvlc_new( int argc , const char *const *argv ); 功能&#xff1a;创建libvlc_instance_t对象。 用法&#xff1a; libvlc_instance_t *VlcInstance libvlc_new(0, nullptr);参数&#xff1a;                具体…

【玩转VLC】--- 基于libvlc写个最简单的播放器

通过【玩转VLC】--- ubuntu下编译vlc 我们已经把vlc编译哦了。生成了一系列的bin和libvlc.so. 接下来我们就用编译好的libvlc.so搞一个最简单的播放器。 我认为vlc的伟大之处有一点就是他并没有把整个播放器写成一个硬生生的bin。而是独立出来个libvlc库&#xff0c;其他的玩…

最简单的基于libVLC的例子:最简单的基于libVLC的推流器

最简单的基于libVLC的例子文章列表&#xff1a; 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器&#xff08;图形界面版&#xff09; 最简单的基于libVLC的例子&#xff1a;最简…

C++调用libVLC播放视频

1、下载libVLC的sdk Index of /pub/videolan/vlc/ 注意下载.7z结尾的 2、Visual Studio建立C的windows控制台项目 3、文件准备 &#xff08;1&#xff09;sdk文件夹解压缩到项目文件夹下 &#xff08;2&#xff09;在Debug下方压缩包内的几个文件 、 4、配置项目属性 注意…

最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器(图形界面版)

最简单的基于libVLC的例子文章列表&#xff1a; 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器&#xff08;图形界面版&#xff09; 最简单的基于libVLC的例子&#xff1a;最简…

基于libVLC的视频播放器之二:使用VLC-Qt播放RTSP流

此篇是 使用VLC浏览器插件播放RTSP流的姊妹篇。 一.直接使用libVLC libVLC是VLC media player多媒体框架的核心引擎和接口&#xff0c;开发者使用它能轻松的创建大量具有VLC特性的应用。 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器详细介绍了libVL…

最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器

最简单的基于libVLC的例子文章列表&#xff1a; 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器&#xff08;图形界面版&#xff09; 最简单的基于libVLC的例子&#xff1a;最简…

用VLC开发视频播放器/组件(两种方式:libVLC / VLC-Qt)

测试环境 MSVC-2015Qt 5.14.2QCreator 1. libVLC&#xff08;关键步骤&#xff09; 参考&#xff1a;心流剑 libVLC 各版本 下载链接 我的下载版本为&#xff1a;3.0.11 sdk/lib文件夹目录 qmake vlc 部分的配置&#xff08;路径根据自己的修改&#xff09;只需要&#…

idea如何取消debug所有断点

1、debug模式下&#xff0c;在idea左下方找到【View Breakpoints】按钮或者直接按【CtrlShiftF8】快捷键&#xff0c;如下图&#xff1a; 2、在左侧窗口中&#xff0c;点击【Java Line Breakpoints】前方的全选框&#xff0c;如下图&#xff1a; 3、取消 【Java Line Breakp…

Idea断点for循环调试

前言 作为一个开发&#xff0c;最高兴和痛苦的事情就是排查问题&#xff0c;调试代码解决问题&#xff0c;掌握一些技巧可以提升效率&#xff0c;今天就讲讲for循环断点调试的技巧for循环断点调试 操作步骤&#xff1a; 1.在断点调试处加断点 2.点击断点处&#xff0c;鼠标右击…

IntelliJ IDEA-Debug断点调试 看这篇文章就够了

详解IntelliJ IDEA-Debug断点调试 如今&#xff0c;IntelliJ IDEA 目前深受广大开发者喜爱&#xff0c;我们在实际开发工作中&#xff0c;不管是用来阅读源码还是在开发过程中都需要进行代码调试。 以下为大家准备了一篇关于IntelliJ IDEA-Debug断点调试的文章&#xff0c;如…

IDEA 的基本介绍使用及断点调试

文章目录 1、IDE&#xff08;集成开发环境&#xff09;- IDEA2、IDE&#xff08;集成开发环境&#xff09;- Eclipse3、IDEA 的基本介绍和使用3.1、设置字体 和 颜色主题3.2、编译文件和源代码3.3、IDEA 常用快捷键3.4、模板/自定义模板 4、断点调试(debug)4.1、实际需求4.2、定…

idea debug调式进不了断点

问题&#xff1a; 在启动debug断点调试时&#xff0c;代码无法进入断点。 解决方案&#xff1a; 在网上搜索解决方案&#xff0c;看到说在settings——>Debugger下勾选如下位置即可。本人并未亲自测试&#xff0c;所以就做了一波搜集党。 我的解决方法&#xff1a;去掉如下…

idea断点调试jar包

本文以springbootdemo-0.0.1-SNAPSHOT.jar 为例&#xff0c;jar内容需与idea保持一致。 1、启动命令 常规jar启动&#xff1a;java -jar springbootdemo-0.0.1-SNAPSHOT.jar jar包断点调试启动&#xff1a;java -Xdebug -agentlib:jdwptransportdt_socket,servery,suspendn,ad…