【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

相关文章

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

c++ 类成员变量默认初始值的实现

《c++类成员变量默认初始值的实现》本文主要介绍了c++类成员变量默认初始值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录C++类成员变量初始化c++类的变量的初始化在C++中,如果使用类成员变量时未给定其初始值,那么它将被

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核