【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

相关文章

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Python实现精确小数计算的完全指南

《Python实现精确小数计算的完全指南》在金融计算、科学实验和工程领域,浮点数精度问题一直是开发者面临的重大挑战,本文将深入解析Python精确小数计算技术体系,感兴趣的小伙伴可以了解一下... 目录引言:小数精度问题的核心挑战一、浮点数精度问题分析1.1 浮点数精度陷阱1.2 浮点数误差来源二、基础解决

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

Java实现远程执行Shell指令

《Java实现远程执行Shell指令》文章介绍使用JSch在SpringBoot项目中实现远程Shell操作,涵盖环境配置、依赖引入及工具类编写,详解分号和双与号执行多指令的区别... 目录软硬件环境说明编写执行Shell指令的工具类总结jsch(Java Secure Channel)是SSH2的一个纯J