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

article/2025/10/1 17:35:27

        一、介绍

        投影变换也叫透射变换投影映射。透射变换是将图像投影到一个新的视平面,是一种二维坐标到三维坐标的变换。

        透射变换是仿射变换的延续,也可以说仿射变换是透射变换的一种特殊形式。其特殊性在于变换后图像的形状仍然维持原状。投影变换包括的情况很多,有可能变换前后图像的形状发生了很大的改变,如对边不再平行,或者发生了透视畸变,这时可以使用投影变换使其恢复原状。其步骤与仿射变换类似,首先计算投影变换矩阵,然后计算投影变换参数,最后将投影变换矩阵映射到对象上。

        透射变换是三维空间上的变换,因此,对于二维图像,最后一个原坐标z恒为1,变换矩阵的最后一个参数也恒为1。

        要计算投影变换矩阵,应找出投影区域的特征点的位置及其投影后的位置,通过hom_vector_to_proj_hom_mat2d算子进线换算,就可以根据已知的投影对应的点的值计算投影变换矩阵,然后使用projective_trans_image对图形进线投射变换,就能得到投影后的图像了。

        所以,透射变换的矩阵有8个未知数,要求解就需要找到4组映射点,四个点就刚好确定了一个三维空间。图像经过透视变换后通常不是平行四边形。与仿射变换类似,在经过变换之后,图像的灰度值也要经过图像插值计算,得到变换后的图像。

二维坐标(u,v)到三维坐标(x,y,z)的变换数学表达式

        二、Halcon中相关算子 

        Transformations / 2D Transformations

        根据给定点的投影计算一个同质变换矩阵

hom_vector_to_proj_hom_mat2d( : : Px, Py, Pw, Qx, Qy, Qw, Method : HomMat2D)

        Px:输入参数,图像变换前图像的顶点x坐标。

        Py:输入参数,图像变换前图像的顶点y坐标。

        Pw:输入参数,图像变换前图像的顶点w坐标。

        Qx:输入参数,图像变换后图像的顶点x坐标。

        Qy:输入参数,图像变换后图像的顶点y坐标。

        Qw:输入参数,图像变换后图像的顶点w坐标。

        Method:输入参数,变换方式选择。默认'normalized_dlt',

列表【

'dlt'算法最快速简单,但是有相对的不准确的误差

'normalized_dlt'速度与精度较好

】。

        HomMat2D:输出参数,输出齐次投影变换矩阵。

        Transformations / 2D Transformations

        根据给定点的投影计算一个投影变换矩阵

vector_to_proj_hom_mat2d( : : Px, Py, Qx, Qy, Method, CovXX1, CovYY1, CovXY1, CovXX2, CovYY2, CovXY2 : HomMat2D, Covariance)

        Px:输入参数,图像变换前图像的顶点x坐标。

        Py:输入参数,图像变换前图像的顶点y坐标。

        Qx:输入参数,图像变换后图像的顶点x坐标。

        Qy:输入参数,图像变换后图像的顶点y坐标。

        Method:输入参数,变换方式选择。默认 'normalized_dlt',

列表【

'dlt'算法最快速简单,但是有相对的不准确的误差

'gold_standard'优化较好但速度较慢

'normalized_dlt'速度与精度较好

        CovXX1:输入参数,图像变换前图像对应x值坐标的row方向的变动。默认[]。

        CovYY1:输入参数,图像变换前图像对应y值坐标的col方向的变动。默认[]。

        CovXY1:输入参数,图像变换前图像对应点的协方差。默认[]。

        CovXX2:输入参数,图像变换后图像对应x值坐标的row方向的变动。默认[]。

        CovYY2:输入参数,图像变换后图像对应y值坐标的col方向的变动。默认[]。

        CovXY2:输入参数,图像变换后图像对应点的协方差。默认[]。

        HomMat2D:输出参数,输出映射变换矩阵。

        Covariance:输出参数,输出9×9协方差矩阵的投影变换矩阵。

        Filters / Geometric Transformations

        对图像应用投影变换

projective_trans_image(Image : TransImage : HomMat2D, Interpolation, AdaptImageSize, TransformDomain : )

        Image:输入参数,输入需要变换的多通道图像。

        TransImage:输出参数,输出变换后的图像。

        HomMat2D:输入参数,输入变换矩阵。

        Interpolation:输入参数,插值的方式。默认 'bilinear',列表【 'bilinear', 'nearest_neighbor'】。

        AdaptImageSize:输入参数,是否自动调整输出图像的大小。默认'false',列表【'false', 'true'】。

        TransformDomain:输入参数,输入图像的域也应该进行变换吗?。默认'false',列表【'false', 'true'】。

        Regions / Geometric Transformations

        对区域应用投影变换

projective_trans_region(Regions : TransRegions : HomMat2D, Interpolation : )

        Regions:输入参数,输入区域。

        TransRegions:输出参数,输出变换后的区域。

        HomMat2D:输入参数,输入映射变换矩阵。

        Interpolation:输入参数,插值的方式。默认 'bilinear',列表【 'bilinear', 'nearest_neighbor'】。

         三、投影变换的案例

        1、vector_to_proj_hom_mat2d案例 

dev_set_draw('margin')
read_image(Image,'ecc200_to_preprocess_001.png')
*灰度阈值分割出区域
threshold(Image, Region, 0, 90)
*改变区域的形状为凸性
shape_trans(Region, RegionTrans, 'convex')
*生成XLD亚像素级轮廓,'border'边框像素的外边框作为轮廓点
gen_contour_region_xld(RegionTrans, Contours, 'border')
*将XLD轮廓分割成线段。
segment_contours_xld(Contours, ContoursSplit, 'lines', 5, 10, 1)
*保存四边形的顶点X坐标
X:=[]
*保存四边形的顶点y坐标
Y:=[]
*根据轮廓的相对位置排序
sort_contours_xld(ContoursSplit, SortedRegions, 'lower_left', 'true', 'row')
*计算元组中的数量
count_obj(SortedRegions, Number)
for Index:=1 to Number by 1*按顺序选择数据select_obj(SortedRegions, ObjectSelected, Index)*拟合直线fit_line_contour_xld(ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)*统一整合元组tuple_concat(X,RowBegin,X)tuple_concat(Y,ColBegin,Y)   
endfor
*为每个输入点生成一个十字形状的XLD轮廓线
gen_cross_contour_xld(Cross,X,Y,10, 0.785398)
*根据给的变换前和变换后的数据计算一个投影矩阵
*[0,400,400,0],[0,0,400,400]这里的顺序一定要注意!!!,必须按照上面X和Y元组中的变换前的点的顺序
*且每个元组内是4这,因为要和上面变换前的坐标数量对应
vector_to_proj_hom_mat2d(X,Y,[0,400,400,0],[0,0,400,400],'normalized_dlt', [], [], [], [], [], [], HomMat2D, Covariance)
*对图像应用投影变换
projective_trans_image(Image,TransImage1, HomMat2D, 'bilinear', 'false', 'false')
ecc200_to_preprocess_001.png

        2、hom_vector_to_proj_hom_mat2d 案例

read_image(Image,'ecc200_to_preprocess_001.png')
X:=[130,225,290,63]
Y:=[101,96,289,269]
hom_vector_to_proj_hom_mat2d(X,Y,[1,1,1,1],[0,400,400,0], [0,0,400,400],[1,1,1,1],'normalized_dlt', HomMat2D)
projective_trans_image(Image, TransImage, HomMat2D, 'bilinear', 'false', 'false')

        3、案例3

*关闭当前显示窗口,清空屏幕
*dev_close_window ()
*读取测试图像
read_image (Image_display, 'display.jpg')
*将图像转化为灰度图像
rgb1_to_gray (Image_display, GrayImage)
*获取图像的尺寸
get_image_size(Image_display,imageWidth, imageHeight)
*新建显示窗口,适应图像尺寸
dev_open_window (0, 0, imageWidth, imageHeight, 'black', WindowHandle1)
dev_display (GrayImage)
*初始化角点坐标
XCoordCorners := []
YCoordCorners := []
*阈值处理,提取较暗的区域
threshold(GrayImage,DarkRegion,0, 80)
*分离不相连的区域
connection (DarkRegion, ConnectedRegions)
*选择面积最大的暗色区域,即屏幕区域
select_shape_std (ConnectedRegions, displayRegion, 'max_area', 70)
*裁剪屏幕区域
reduce_domain (GrayImage, displayRegion, displayImage)
*创建边缘轮廓
gen_contour_region_xld (displayRegion, Contours, 'border')
*将轮廓分割为边
segment_contours_xld (Contours, ContoursSplit, 'lines', 5, 4, 2)
*获取边的数量
count_obj (ContoursSplit, Number)
*存储每条边的起点位置
for index:=1 to Number by 1select_obj(ContoursSplit, ObjectCurrent, index)*拟合每条边fit_line_contour_xld (ObjectCurrent, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)*存储每条边的顶点x坐标tuple_concat (XCoordCorners, RowBegin, XCoordCorners)*存储每条边的顶点y坐标tuple_concat (YCoordCorners, ColBegin, YCoordCorners)
endfor
* 投影变换给四个特征点与校正后的坐标建立关联
XOff:= 100
YOff:= 100*imageHeight/imageWidth
hom_vector_to_proj_hom_mat2d (XCoordCorners, YCoordCorners, [1,1,1,1], [YOff,YOff,imageHeight-YOff,imageHeight-YOff], [XOff,imageWidth-XOff,imageWidth-XOff,XOff], [1,1,1,1], 'normalized_dlt', HomMat2D)
*投影变换
projective_trans_image (Image_display, Image_rectified, HomMat2D, 'bilinear', 'false', 'false')
* 显示校正结果
dev_display (Image_rectified)
display.jpg

 


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

相关文章

投影变换原理和用法

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

基于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…

如何在idea中打debug断点

在调试代码的时候&#xff0c;你的项目得debug模式启动&#xff0c;也就是点那个绿色的甲虫启动服务器&#xff0c;然后&#xff0c;就可以在代码里面断点调试啦。 下面不要在意&#xff0c;这个快捷键具体是啥&#xff0c;因为&#xff0c;这个keymap是可以自己配置的&#xf…