【halcon】set_part 实现平移和缩放 彻悟版

2024-05-25 13:52

本文主要是介绍【halcon】set_part 实现平移和缩放 彻悟版,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

之前写了一篇关于set_part 的文章 ,确实也实现了平移和缩放。平移是对的,但是缩放其实有畸变。这个问题一直都困扰着我,知道昨天连续测试了好几个小时,直到晚上11点终于完美解决。

坐标和高宽

坐标

再讲set_part 之前,我们先理一下,坐标和高宽
平时,我们通常使用 X, Y 来描述一个二维的坐标系。坐标原点一般是左下角。
而在halcon中,我们通常是使用 row 和 column来描述。
row 对应的是 Y, (row是一行行的,是Y方向走向)
column对应的是X。(colunm是一列列的,是X方向走向)
坐标原点在左上角。

高宽

高: 是 row 之间的差值(Y方向)。
宽: 是 column 之间的差值(X方向)

set_part 是 Halcon 中用于修改显示图像部分的算子。该算子允许你定义要在窗口中显示的图像的感兴趣区域(ROI),并可以根据需要进行缩放。下面我们详细解读 set_part 算子的用法及参数:

set_part 算子简单说明

1. 名称

set_part — 修改显示的图像部分。

2. 签名

set_part( : : WindowHandle, Row1, Column1, Row2, Column2 : )

3. 描述

set_part 修改在窗口中显示的图像部分。参数 (Row1, Column1) 表示图像部分的左上角,(Row2, Column2) 表示图像部分的右下角。
如果只显示图像的一部分,该部分将被缩放到整个窗口大小。可以使用 set_part_style 设置缩放插值方法。get_part 可以返回显示的图像部分的值。

除了直接设置图像部分外,还支持以下特殊模式:

  • Row1 = Column1 = Row2 = Column2 = -1:
    窗口大小被选择为图像部分,即不执行图像缩放。

  • Row1, Column1 > -1Row2 = Column2 = -1:
    选择最后显示的图像大小为图像部分,即图像可以完全显示在窗口中。如果需要,图像将被缩放。

4. 参数

  • WindowHandle (input_control) : 窗口句柄,类型为 integer

  • Row1 (input_control) : 所选图像部分左上角的行坐标,类型为 integer。默认值为 0

  • Column1 (input_control) : 所选图像部分左上角的列坐标,类型为 integer。默认值为 0

  • Row2 (input_control) : 所选图像部分右下角的行坐标,类型为 integer。默认值为 -1。限制:Row2 >= Row1Row2 == -1

  • Column2 (input_control) : 所选图像部分右下角的列坐标,类型为 integer。默认值为 -1。限制:Column2 >= Column1Column2 == -1

set_part 深度理解

从上面的说明,我们需要理解一点。set_part 的坐标参数,它的参考系是图片坐标的原点就是图片的左上角那个点! **图片动原点就跟着在变化!**理解这一点至关重要。

其实,一开始困扰的我的就是这个问题,一开始我认为,坐标系应该是以窗口为基准的,因为他是不会动的。但其实坐标系是以图片为基准的。坐标的原点就是图片的左上角那个点

再有就是,图片是显示在窗口里的,那窗口的坐标系是什么样子的呢?首先窗口本身有自己的坐标系,窗口的左上角那个点就是窗口的坐标原点。

是如何跟图片的坐标系关联的呢?很简单,看图片在哪!
如果图片的原点(图片的左上角那个点)在和窗口的左上角那个点重合。那么窗口的坐标系是和图的坐标系重合的。

图片的缩放

那现在理解一下:
set_part(WindowHandle, 0, 0, 100, 100)
这句话是说明意思?
用在窗口这个视野内,显示图片的一个部分,哪个部分?就是Rect(0, 0, 100, 100)这个部分。
更具体的理解就是:
将图片(0,0)这个点放到,窗口的左上角!,将图片100, 100这个点到窗口的右下角!仔细体会这个字!
扯,其实就是图片放大的一种差值算法。

例子1:
如果,窗口的大小是100x100,图片的大小也是 100x100。那其实图片就刚刚好放到窗口之中。

例子2:
窗口的大小是100100,图片的大小是 100100。
但此时我修改程序为: set_part(WindowHandle, 0, 0, 50, 50)
图片(0,0)这个点被固定在窗口的左上角,同时图片(50, 50) 这个点会被扯到窗口的右下角(100,100),图片就被放大了一倍。也就是说窗口大小如果不变,看到图片的区域越小,图片就会被’扯’的越大.

畸变是如何产生的

如果窗口的大小是200*100,而图片是是 50*50。
我还是这么写set_part(WindowHandle, 0, 0, 100, 100)
这样的画会发送什么?
同样,图片(0,0)这个点被固定在窗口的左上角。图片(100, 100)右下角,被扯到了窗口的右下角(200*100)。
此时,你会发现,图片的宽是之前的4倍,而高是之前的两倍.
这样宽高的放大比例不同,导致图像产生了畸变!
那要确保不发生畸变,就是要保证宽和高的放大比例相同即可!
如何扯?红色是窗口,蓝色是图片
那怎么扯,可以保证,图片不变型
很明显,窗口的宽高比为2:1 = 2, 而图片的宽高比为1:1 = 1
窗口的宽高比 > 图片宽高比。
所以, 当图片的宽高同时缓慢放大时,如果图片的高已经和窗口的高一致时,此时应该停止放大了!
放大后
这样,图片宽和高都放大了一倍,为发送形变。那此时set_part应该输入写呢?

前情提要:窗口的大小是200*100,而图片是是 50*50。

写法为:set_part(WindowHandle, 0, 0, 50, 100)
在这里插入图片描述

含义就是,图片的左上角固定在图片的窗口的左上角,当图片的(50,100)
这个点,被扯到窗口的右下角(200,100)时停止!
这里,可能有人会说了,图片就 50*50。 哪来的(50,100)?
这里就需要引入一个自定义概念(就是自己根据情景编造的):图片的延生坐标。此时,你就想象图片本身就在一个巨大的弹性巨好的画布上。画布就是图片的延时。(50,100)虽然不在图片上但是在这个画布上。我们扯画布,图片也会跟着形变。
那,这个50, 100这个点是怎么计算来的呢?这个点有几个个前提:

  1. 图片不发生形变
  2. 图片显示完全的情况下,实现最大的放大倍数。

很明显,对应上面这种情况,图片的高可以顶格显示,而宽度则需要留白。
所以:
set_part(WindowHandle, 0, 0, 50, ?)

高: 是 row 之间的差值(Y方向)。

所以图片的右下角 row值,可以扯到窗口的底部(row的最大位置。)以到达高度顶格显示的目的。
那最后一点怎么算?因为现在图片高度拉满,就是图片的高度50,那么用50再乘以窗口的宽高比,得到就是的第四个坐标的位置。

另外一种情况
在这里插入图片描述
图片的宽高比,大于窗口的宽高比。
就是图片的宽度可以顶格显示,高度留白。
假设图片的宽度是w,那么、column方向向拉满:
set_part(WindowHandle, 0, 0, ?, w)
?怎么求? w 除以 窗口的宽高比

做个小结:
首先就是需要分类讨论,窗口的宽高比和图片的宽高比哪个更大?从而判断
图片的那一条边可以顶格显示,从而计算另一个坐标的位置。
具体程序如下:

//计算缩放比例
double winWHRatio = WindowWidth.D / WindowHeight.D;
double picWHRatio = imgw.D / imgh.D;double dispWidth;
double dispHeight;//设置整个图像为显示的部分
if (picWHRatio >= winWHRatio)
{dispHeight = imgw / winWHRatio / PosEnlarge;dispWidth = imgw / PosEnlarge; HOperatorSet.SetPart(HalconWindow, 0, 0, dispHeight, dispWidth);
}
else
{dispHeight = imgh.D / PosEnlarge;dispWidth = imgh.D * winWHRatio / PosEnlarge;var offseth = row - dispHeight / 2;var offsetw = column- dispWidth / 2;HOperatorSet.SetPart(HalconWindow, 0, 0, dispHeight, dispWidth);}

不发生畸变的任意倍数放大

上面是加了一个添加的放大,就是
图片显示完全的情况下,实现最大的放大倍数。
现在,我想任意倍速放大!怎么实现?

//计算缩放比例
double winWHRatio = WindowWidth / WindowHeight;
double picWHRatio = imgw / imgh;double dispWidth;
double dispHeight;//设置整个图像为显示的部分
if (picWHRatio >= winWHRatio)
{dispHeight = imgw / winWHRatio;dispWidth = imgw; HOperatorSet.SetPart(HalconWindow, 0, 0, dispHeight, dispWidth);
}
else
{dispHeight = imgh;dispWidth = imgh * winWHRatio;HOperatorSet.SetPart(HalconWindow, 0, 0, dispHeight, dispWidth);
}

不发生畸变的任意倍数放大

上面是加了一个添加的放大,就是
图片显示完全的情况下,实现最大的放大倍数
现在,我想任意倍速放大!怎么实现?
我们,现在就定义,图片显示完全的情况下,实现最大的放大倍数。时为图像放大一个倍数!也就是自适应的做大化显示为一倍!

那如果,我要放大PosEnlarge倍,代码修改如下:

//计算缩放比例
double winWHRatio = WindowWidth / WindowHeight;
double picWHRatio = imgw / imgh;double dispWidth;
double dispHeight;//设置整个图像为显示的部分
if (picWHRatio >= winWHRatio)
{dispHeight = imgw / winWHRatio / PosEnlarge;dispWidth = imgw / PosEnlarge; HOperatorSet.SetPart(HalconWindow, 0, 0, dispHeight, dispWidth);
}
else
{dispHeight = imgh / PosEnlarge;dispWidth = imgh * winWHRatio / PosEnlarge;HOperatorSet.SetPart(HalconWindow, 0, 0, dispHeight, dispWidth);
}

改动不大,就是将之前的dispHeight 和 dispWidth 多除以了一个PosEnlarge!比如如果是放大两边就是 PosEnlarge = 2即可。
这是因为,窗口大小没变(视口不变),但是显示的区域变小,图片被拉大。
这次,不会畸变的原因是,此时在原来的基础上,同时宽高放大的一样的比例,所以不会畸变。放大的中心是(0,0)

图像的平移

SetPart 图像的缩放就讲完了,如何设置通过SetPart 进行平移?
在这里插入图片描述
首先,我们之前图片的原点和窗口左上角是重合的,此时没有平移。
如果图片向左上方平移(25,25),那么此时,窗口的左上角应该显示的是图片(25,25)这个点。那窗口的右下角的点应该随之变化 (25,25)及 row,column都加25。 这样显示的图片范围就是不变的而保证图片是仅仅发生平移,而没有形变。
那公式就是:
SetPart(HWindow, offseth, offsetw, dispHeight + offseth, dispWidth + offsetw);

这样,就能通过,offseth, offsetw 来控制 平移

平移加上缩放

现在,我有一个需求,我可以设定放大倍数,而且当我输入一个点时,需要将这个点移动到屏幕的中间!
接下来直接给出最终的代码:

    /// <summary>/// 将某个目标位置移动到中间/// </summary>public void MoveSm2Center(HObject img, HTuple row, HTuple column){HTuple win_Width, win_Height, win_Col, win_Row;HOperatorSet.GetWindowExtents(hSmart.HalconWindow, out win_Row, out win_Col, out win_Width, out win_Height);//获取窗体大小规格HTuple WindowWidth = win_Width;HTuple WindowHeight = win_Height;HTuple imgw;HTuple imgh;HOperatorSet.GetImageSize(img, out imgw, out imgh);//计算缩放比例double winWHRatio = WindowWidth.D / WindowHeight.D;double picWHRatio = imgw.D / imgh.D;double dispWidth;double dispHeight;//设置整个图像为显示的部分if (picWHRatio >= winWHRatio){dispHeight = imgw / winWHRatio / GlobalData.Instance.saveInfo.PosEnlarge;dispWidth = imgw /  GlobalData.Instance.saveInfo.PosEnlarge; HOperatorSet.SetPart(hSmart.HalconWindow, 0, 0, dispHeight, dispWidth);}else{dispHeight = imgh.D / GlobalData.Instance.saveInfo.PosEnlarge;dispWidth = imgh.D * winWHRatio / GlobalData.Instance.saveInfo.PosEnlarge;//var offseth = row - imgw / 2;//var offsetw = column - imgh / 2; var offseth = row - dispHeight / 2;var offsetw = column- dispWidth / 2;HOperatorSet.SetPart(hSmart.HalconWindow, offseth, offsetw, dispHeight + offseth, dispWidth + offsetw);}}

其中: GlobalData.Instance.saveInfo.PosEnlarge 是被定义为一个全局的变量。控制放大倍数。
HTuple row, HTuple column 传入指定的点。
这里需要主义的是:
//var offseth = row - imgw / 2;
//var offsetw = column - imgh / 2;

var offseth = row - dispHeight / 2;
var offsetw = column- dispWidth / 2;
为了移到,屏幕的中间,我用的是 dispHeight / 2 和 dispWidth / 2
而不是 图片大小的一半,或是 窗口大小的一半。

这是应为,不管是图片还是窗口,他们的一半是固定大小的。 而图片是缩放了的。
dispHeight 和 dispWidth 是图片缩放后的结果。

好了就到这里了!!!!!!

这篇关于【halcon】set_part 实现平移和缩放 彻悟版的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1001691

相关文章

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤

《SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤》本文主要介绍了SpringBoot+MyBatis-Flex配置ProxySQL的实现步骤,文中通过示例代码介绍的非常详... 目录 目标 步骤 1:确保 ProxySQL 和 mysql 主从同步已正确配置ProxySQL 的

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点:

nginx部署https网站的实现步骤(亲测)

《nginx部署https网站的实现步骤(亲测)》本文详细介绍了使用Nginx在保持与http服务兼容的情况下部署HTTPS,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值... 目录步骤 1:安装 Nginx步骤 2:获取 SSL 证书步骤 3:手动配置 Nginx步骤 4:测