11.1 使用 HALCON/.NET 类

在 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 的调用。

下面,我们就来详细了解一下:

但首先,我们会向您介绍所提供的在线帮助。

11.1.1 在线帮助

有关 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 还提供在线帮助:

11.1.2 调用 HALCON 算子

参考手册中列出了通过哪些类可以调用 HALCON 算子。图 11.1 显示了算子 GrabImage 的相应描述部分:

static void HOperatorSet.GrabImage  
(out HObject image, HTuple acqHandle)

void HImage.GrabImage  
(HFramegrabber acqHandle)

HImage HFramegrabber.GrabImage  
()

image (output_object)image → HImage (byte / uint2)
acqHandle (input_control)framegrabber → HFramegrabber / HTuple (IntPtr)

图 11.1: GrabImage 参考手册条目的头部和参数部分。

如您所见,算子可通过三个类调用: HOperatorSetHImageHFramegrabber。通过 HOperatorSet 调用的第一个变量主要用于 HDevelop 程序的导出(参见 "使用 HDevelop 程序" 一节 )。

对于普通应用程序,我们建议通过其他类调用算子,例如 HImageHFramegrabber,如下代码示例所示:

  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 开头:

static void HOperatorSet.CountSeconds  
(out HTuple seconds)

static double HSystem.CountSeconds  
()

图 11.2:参考手册中 CountSeconds 条目的头部。

11.1.3 从声明到终结

在对象的生命周期内,即从声明到最终确定,会分配和释放不同数量的内存。

下面的声明只是声明了一个 HImage 类变量,它还没有引用任何对象:

  HImage Image1;

在这种状态下,您无法使用该变量调用算子;根据编程语言的不同,您甚至可能无法将其用作输出参数(例如,在 Visual Basic 2005 中)。不过,您可以将图像对象赋值给变量,例如从算子的返回值中赋值:

  Image1 = Framegrabber.GrabImage();

您也可以在声明变量时对其进行初始化

  HImage Image2 = Framegrabber.GrabImage();
  HImage Image3 = null;

请注意,您可以使用 IsInitialized 方法检查类实例的初始化状态。

11.1.3.1 构造函数

相反,下面的声明调用了 HImage 类的 "空" 构造函数,创建了一个单元化的类实例:

  HImage Image4 = new HImage();

该类实例可用于调用 "类构造函数 "算子,如 GrabImage(使用抓取的图像进行初始化):

  Image4.GrabImage(Framegrabber);

除了空构造函数外,大多数 HALCON/.NET 类还提供一个或多个构造函数,根据 HALCON 算子初始化创建的对象。例如,HImage 提供了一个基于算子 ReadImage 的构造函数:

  HImage Image5 = new HImage("fuse");

您可以通过在线帮助查看提供了哪些构造函数:

11.1.3.2 终结器

.NET内存管理的主要理念是,程序员无需担心内存管理,让垃圾回收器删除所有不再使用的对象。HALCON/.NET 完全遵循这一理念,为所有类提供了相应的终结器,因此即使是未被管理的资源,例如与图像采集设备的连接,也能正确自动地删除。

对于大多数类,终结器会自动调用合适的算子(如 CloseFramegrabber)来释放资源。调用哪个算子会在类的参考手册页面中列出(例如,请参见 HFramegrabber 的条目)。如相应的参考手册条目所示,该算子不能通过类调用:

static void HOperatorSet.CloseFramegrabber  
(HTuple acqHandle)

void HFramegrabber.CloseFramegrabber  
()

图 11.3:CloseFramegrabber 的参考手册条目头部。

如果您想用不同的参数重新打开连接,甚至不需要调用这样的算子,因为它会自动完成。

 ! 使用 HFramegrabber 等普通类时,请勿通过 HOperatorSet 调用 CloseClear 算子

11.1.3.3 垃圾回收

如上所述,.NET 的理念是让垃圾回收器移除未使用的对象。然而,由于垃圾回收器只是不时删除未使用的对象,因此在此期间使用的内存会增加。更重要的是,对于垃圾回收器来说,HALCON 的图标变量(图像、区域......)似乎相当 "小",因为它们只包含对数据库中图标对象(在许多情况下相当大)的引用。因此,即使不再使用这些变量,垃圾回收器也不会释放它们。

因此,您可能需要强制移除(未使用的)对象。有两种方法可以做到这一点:

除了减少内存消耗,手动处置对象的另一个原因是释放资源,例如关闭与图像采集设备或串行接口的连接。

如果要以确定的方式释放引用的资源,还需要处理包含句柄的 HTuple 实例。

请注意,HALCON 算子总是为输出参数和返回值创建一个新的对象实例(但在修改调用实例的 "类构造函数" 算子调用中不会)。如果变量已被初始化,则其旧内容(以及为其分配的内存)仍然存在,直到垃圾回收器将其删除。如果要手动移除该变量,必须在为其分配对象之前调用 Dispose

11.1.4 算子重载

有些类重载了标准算子,如 +(加法),以调用 HALCON 算子。例如,下面一行通过内部调用 AddImage 来添加两幅图像:

Image5 = Image1 + Image2;

请注意, ! Visual Basic .NET 中没有算子重载。

下表列出了当前可用的算子重载。

HImage 的算子重载

- (一元) 反转图像
+ (图像) 加两幅图像
- (图像) 从图像 1 减去图像 2
(图像) 乘两幅图像
+ (标量) 增加一个常量灰度值偏移
- (标量) 减去一个常量灰度值偏移
(标量) 按指定系数缩放图像
/ (标量) 按指定除数缩放图像
>= (图像) 使用动态阈值分割图像
<= (图像) 使用动态阈值分割图像
>= (标量) 使用常量阈值分割图像
<= (标量) 使用常量阈值分割图像
& (区域) 缩小图像的域

HRegion 的算子重载

& (区域) 返回区域的交集
| (区域) 返回区域的并集
/ (区域) 返回区域的差异
! (一元) 返回区域的补码(可能是无限的)
& (图像) 返回区域与图像域的交集
+ (区域) 返回区域的Minkowski闵科夫斯基加法
- (区域) 返回区域的Minkowski闵科夫斯基减法
+ (标量) 以指定半径膨胀区域
- (标量) 以指定半径腐蚀区域
+ (点) 转换区域
(标量) 放大区域
- (一元) 转置区域

HFunction1D 的算子重载

+ (标量) 为函数的 Y 值增加一个常量偏移量
- (标量) 为函数的 Y 值减去一个常量偏移量
- (一元) 取反函数的 Y 值
(标量) 缩放函数的 Y 值
/ (标量) 缩放函数的 Y 值
(函数) 组合两个函数(不是逐点乘法)
! (一元) 计算函数的逆函数