在 HALCON/.NET 中,您可以通过类的实例来调用 HALCON 算子。以下代码抓取图像序列的第一幅图像,并将其显示在 HSmartWindowControl 的图形窗口中:
private HWindow window; private HFramegrabber framegrabber; private HImage img;
window = windowControl.HalconWindow;
framegrabber = new HFramegrabber("File", 1, 1, 0, 0, 0, 0, "default",
-1, "default", -1, "default",
"board/board.seq", "default", 1, -1);
img = framegrabber.GrabImage();
img.GetImagePointer1(out ImgType, out imgWidth, out imgHeight);
window.SetPart(0, 0, imgHeight - 1, imgWidth - 1);
img.DispObj(window);
算子 GrabImage 通过 HFramegrabber 的实例调用。作为一名经验丰富的 HALCON 用户,您或许已经将 HFramegrabber 的构造函数识别为对算子 OpenFramegrabber 的调用。
下面,我们就来详细了解一下:
但首先,我们会向您介绍所提供的在线帮助。
有关 HALCON/.NET 算子和类的主要信息来源是参考手册,有 HTML 和 PDF 版本(注意,后者仅提供 HDevelop 语法)。在 Windows 下,您可以通过开始菜单打开这两个版本。在 Linux 下,分别在 $HALCONROOT/doc/html/reference/operators 目录下打开 index.html,以及在 $HALCONROOT/doc/pdf/reference 目录下打开 reference_hdevelop.pdf。您还可以通过 HDevelop 的帮助浏览器访问它们。
参考手册介绍了每个 HALCON 算子的功能及其签名,即通过哪些类可以调用哪些参数。此外,它还提供了所提供类的概览(但没有列出所有方法,只列出了 HALCON 算子)。
Visual Studio 还提供在线帮助:
参考手册中列出了通过哪些类可以调用 HALCON 算子。图 11.1 显示了算子 GrabImage 的相应描述部分:
|
|
| image (output_object) | image → HImage (byte / uint2) |
| acqHandle (input_control) | framegrabber → HFramegrabber / HTuple (IntPtr) |
图 11.1: GrabImage 参考手册条目的头部和参数部分。
如您所见,算子可通过三个类调用: HOperatorSet、HImage 和 HFramegrabber。通过 HOperatorSet 调用的第一个变量主要用于 HDevelop 程序的导出(参见 "使用 HDevelop 程序" 一节 )。
对于普通应用程序,我们建议通过其他类调用算子,例如 HImage 和 HFramegrabber,如下代码示例所示:
HImage Image1;
HImage Image4 = new HImage();
HFramegrabber Framegrabber = new HFramegrabber("File", 1, 1, 0, 0, 0, 0, "default", -1,
"default", -1, "default", "board/board.seq", "default", -1, -1);
Image1 = Framegrabber.GrabImage();
HImage Image3 = null;
请注意,在通过 HFramegrabber 的调用中,抓取的图像是方法的返回值,而通过 HImage 的调用则没有返回值,而是修改了调用的类实例。通常情况下,调用类实例不会被算子调用修改——但上例中的 "类构造函数" 算子调用除外。
有些算子(如 CountSeconds)可以作为类方法使用,也就是说,你可以直接通过类调用它们,而不需要实例:
double s1, s2; s1 = HSystem.CountSeconds();
在参考手册中,这些算子调用以关键字 static 开头:
|
|
图 11.2:参考手册中 CountSeconds 条目的头部。
在对象的生命周期内,即从声明到最终确定,会分配和释放不同数量的内存。
下面的声明只是声明了一个 HImage 类变量,它还没有引用任何对象:
HImage Image1;
在这种状态下,您无法使用该变量调用算子;根据编程语言的不同,您甚至可能无法将其用作输出参数(例如,在 Visual Basic 2005 中)。不过,您可以将图像对象赋值给变量,例如从算子的返回值中赋值:
Image1 = Framegrabber.GrabImage();
您也可以在声明变量时对其进行初始化:
HImage Image2 = Framegrabber.GrabImage(); HImage Image3 = null;
请注意,您可以使用 IsInitialized 方法检查类实例的初始化状态。
相反,下面的声明调用了 HImage 类的 "空" 构造函数,创建了一个单元化的类实例:
HImage Image4 = new HImage();
该类实例可用于调用 "类构造函数 "算子,如 GrabImage(使用抓取的图像进行初始化):
Image4.GrabImage(Framegrabber);
除了空构造函数外,大多数 HALCON/.NET 类还提供一个或多个构造函数,根据 HALCON 算子初始化创建的对象。例如,HImage 提供了一个基于算子 ReadImage 的构造函数:
HImage Image5 = new HImage("fuse");
您可以通过在线帮助查看提供了哪些构造函数:
.NET内存管理的主要理念是,程序员无需担心内存管理,让垃圾回收器删除所有不再使用的对象。HALCON/.NET 完全遵循这一理念,为所有类提供了相应的终结器,因此即使是未被管理的资源,例如与图像采集设备的连接,也能正确自动地删除。
对于大多数类,终结器会自动调用合适的算子(如 CloseFramegrabber)来释放资源。调用哪个算子会在类的参考手册页面中列出(例如,请参见 HFramegrabber 的条目)。如相应的参考手册条目所示,该算子不能通过类调用:
|
|
图 11.3:CloseFramegrabber 的参考手册条目头部。
如果您想用不同的参数重新打开连接,甚至不需要调用这样的算子,因为它会自动完成。
! 使用 HFramegrabber 等普通类时,请勿通过 HOperatorSet 调用 Close 或 Clear 算子。
如上所述,.NET 的理念是让垃圾回收器移除未使用的对象。然而,由于垃圾回收器只是不时删除未使用的对象,因此在此期间使用的内存会增加。更重要的是,对于垃圾回收器来说,HALCON 的图标变量(图像、区域......)似乎相当 "小",因为它们只包含对数据库中图标对象(在许多情况下相当大)的引用。因此,即使不再使用这些变量,垃圾回收器也不会释放它们。
因此,您可能需要强制移除(未使用的)对象。有两种方法可以做到这一点:
private void Timer_Tick(object sender, System.EventArgs e)
{
Action();
GC.Collect();
GC.WaitForPendingFinalizers();
}
HImage Image = new HImage("fuse");
...
Image.Dispose();
除了减少内存消耗,手动处置对象的另一个原因是释放资源,例如关闭与图像采集设备或串行接口的连接。
如果要以确定的方式释放引用的资源,还需要处理包含句柄的 HTuple 实例。
请注意,HALCON 算子总是为输出参数和返回值创建一个新的对象实例(但在修改调用实例的 "类构造函数" 算子调用中不会)。如果变量已被初始化,则其旧内容(以及为其分配的内存)仍然存在,直到垃圾回收器将其删除。如果要手动移除该变量,必须在为其分配对象之前调用 Dispose。
有些类重载了标准算子,如 +(加法),以调用 HALCON 算子。例如,下面一行通过内部调用 AddImage 来添加两幅图像:
Image5 = Image1 + Image2;
请注意, ! Visual Basic .NET 中没有算子重载。
下表列出了当前可用的算子重载。
| HImage 的算子重载 | ||
| - | (一元) | 反转图像 |
| + | (图像) | 加两幅图像 |
| - | (图像) | 从图像 1 减去图像 2 |
| ∗ | (图像) | 乘两幅图像 |
| + | (标量) | 增加一个常量灰度值偏移 |
| - | (标量) | 减去一个常量灰度值偏移 |
| ∗ | (标量) | 按指定系数缩放图像 |
| / | (标量) | 按指定除数缩放图像 |
| >= | (图像) | 使用动态阈值分割图像 |
| <= | (图像) | 使用动态阈值分割图像 |
| >= | (标量) | 使用常量阈值分割图像 |
| <= | (标量) | 使用常量阈值分割图像 |
| & | (区域) | 缩小图像的域 |
| HRegion 的算子重载 | ||
| & | (区域) | 返回区域的交集 |
| | | (区域) | 返回区域的并集 |
| / | (区域) | 返回区域的差异 |
| ! | (一元) | 返回区域的补码(可能是无限的) |
| & | (图像) | 返回区域与图像域的交集 |
| + | (区域) | 返回区域的Minkowski闵科夫斯基加法 |
| - | (区域) | 返回区域的Minkowski闵科夫斯基减法 |
| + | (标量) | 以指定半径膨胀区域 |
| - | (标量) | 以指定半径腐蚀区域 |
| + | (点) | 转换区域 |
| ∗ | (标量) | 放大区域 |
| - | (一元) | 转置区域 |
| HFunction1D 的算子重载 | ||
| + | (标量) | 为函数的 Y 值增加一个常量偏移量 |
| - | (标量) | 为函数的 Y 值减去一个常量偏移量 |
| - | (一元) | 取反函数的 Y 值 |
| ∗ | (标量) | 缩放函数的 Y 值 |
| / | (标量) | 缩放函数的 Y 值 |
| ∗ | (函数) | 组合两个函数(不是逐点乘法) |
| ! | (一元) | 计算函数的逆函数 |