机器视觉_HALCON_内存管理_C#中HObject对象申请释放解析


一、前言

使用HALCON联合C#进行开发时,若用HDevelop导出代码,可以在导出的代码文件中看到类似下面的代码,

    // Local iconic variables 
    HObject ho_Image=null;
	// Initialize local and output iconic variables 
    HOperatorSet.GenEmptyObj(out ho_Image);
    ...
    ho_Image.Dispose();
    HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1);

从用户手册中可以知道,
在这里插入图片描述
ho_为前缀的ho_Image是一个图像变量(当然,根本原因是HObject类是图像类)。
在ho_Image从图像设备中获取图像前,还有一行代码ho_Image.Dispose();在这里插入图片描述
加这行代码的理由如上图所述,导出的C#代码中图像对象由HObject表示,但是从GC的角度看,HObject是非常小的,因此可能会被忽略。但HObject的底层可能是相当大的一块内存,为了避免泄露,所以用之前要显式释放(即使用Dispose())。

那么问题来了,为什么从GC的角度看,HObject不会被回收呢?为什么那么小的HObject底层可能是一块相当大的内存呢?为什么内存申请用的是GenEmptyObj()呢,用new HObject不行吗?

本文打算从VS中反编译的结果来分析这几个问题。


二、分析

1 GenEmptyObj()

其实有过一定开发经验和C语言基础的伙伴应该会有种感觉,它底层肯定是做了内存申请。
那到底是不是这样呢?我们往函数里跟两步,

可以看到底层的对象是通过new HObject()得到的,只不过构造函数不同,并且在new之前进行了一些额外处理(一个错误码的获取)。并且在new之后,从更底层的一个proc指针处加载图像(这部分应该是HALCON内的管理机制了)。所以GenEmptyObj本质上还是new了一个对象,不过做了一些判断与管理。

2 Dispose()

接下来看Dispose(),

可以看到,它的作用是让GC不要清理该对象。并保活(引用指定的对象,从当前例程的开始到调用此方法的点,使其不会被GC回收)。

所以Dispose()压根没有进行内存清理?
并不是的,第一行有一个key的判断,
在这里插入图片描述
从前面GenEmptyObj的反编译可知,底层new出来的对象,key默认是UNDEF(继续追踪下去会会发现是表示Zero)。
在这里插入图片描述

接着找到GrabImage函数,反编译得到,
在这里插入图片描述
可以看到,内部也有HObject.LoadNew函数,且内容与GenEmptyObj底层的LoadNew一致,即先new一个对象,然后从HALCON底层读取图像数据,
在这里插入图片描述
可以大胆猜测,此时的Key发生了变化。
因此Dispose()函数之初的Key值判断,很可能为判断该HObject的Key是否确实有指向底层的图像数据,若非UNDEF(Zero),则清除。

3 能否直接new对象?

如果你看过HDevelop示例目录下的WPF模板,会发现它的图像对象生成与释放可不是用GenEmptyObj和Dispose的,而是下面这样:

HImage image = new HImage("monkey");
HRegion region;
region = image.Threshold(128, 255);

除了对象是直接new出来的之外,似乎也没有释放的代码了。
对此,在 快速向导(Quick Guide) 文档中有说明,
在这里插入图片描述
简单讲,HALCON提供了两种写法,前者(HOperatorSet.GenEmptyObj())是过程式(面向过程)的写法;而后者(直接new的)是面向对象的写法。

那为什么面向对象的写法,即直接new也是可用的呢?继续反编译,
在这里插入图片描述
可以看到,new执行的构造函数本质上是调用了基类的有参构造函数,并且带有默认参数。追溯GenEmptyObj的底层代码可以发现,其底层new对象的参数列表和直接new的参数列表是一样的。因此,两者等价。

至于为什么没有用Dispose(),我觉得仅仅是因为这个示例没有用罢了。从反编译的结果来看,在每次使用前还是要用的。


三、结语

经过反编译解析,对HALCON图像对象内存的申请与释放有更深层次的认识,虽然不见得对实际开发有显著的帮助,但是用起来心里更有底。使用时,还是建议严格按照HALCON文档中要求的来,尽量风格统一。

还有一些注意事项:

  • 图像对象的直接赋值是引用赋值,如
     ho_Img = ho_ImgSrc;
     ho_Img.Dispose();
    
    这样的代码是有潜在风险的,因为ho_ImgSrc也被释放了,而你可能未察觉到。
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Halcon是一款强大的机器视觉软件库,它提供了丰富的功能和算法用于图像处理和分析。如果您想在C#使用Halcon进行机器视觉开发,可以通过以下步骤进行: 1. 安装Halcon:首先,您需要从Halcon官方网站下载和安装Halcon开发环境。确保选择与您的操作系统和开发环境兼容的版本。 2. 配置HalconC#:在安装完成后,您需要在Visual Studio配置HalconC#的集成。这涉及到引用Halcon的相关库和设置项目属性。 3. 编写C#代码:一旦完成了配置,您就可以开始编写C#代码来调用Halcon的功能了。您可以使用Halcon提供的API来加载图像、进行图像处理、执行算法等。 以下是一个简单的示例代码,演示如何使用Halcon库在C#进行图像处理: ```csharp using HalconDotNet; class Program { static void Main(string[] args) { // 初始化Halcon引擎 HOperatorSet.OpenWindow(0, 0, 800, 600, "visible", "", out HTuple windowHandle); // 读取图像 HOperatorSet.ReadImage(out HObject image, "path/to/image.jpg"); // 显示图像 HOperatorSet.DispObj(image, windowHandle); // 进行图像处理 HOperatorSet.InvertImage(image, out HObject invertedImage); // 显示处理后的图像 HOperatorSet.DispObj(invertedImage, windowHandle); // 关闭Halcon引擎 HOperatorSet.CloseWindow(windowHandle); HOperatorSet.ClearWindow(windowHandle); } } ``` 这只是一个简单的示例,您可以根据自己的需求调用更多的Halcon功能和算法。请注意,Halcon具有非常丰富的功能,我们只是展示了其的一部分。 希望这对您有所帮助!如果您有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值