本文主要是Quick Guide第二章节的内容。
HALCON提供了多种开发程序的方式。不过为了充分利用整套体系,一般推荐下图的方式。
这种三步开发的方式有几点优势:
注意,在这两种情况下(HDevEngine&导出代码),应用程序仅包含HALCON功能 - HDevelop的开发工具(如助手或其他GUI元素),无法从编程语言访问。
HALCON的架构(architecture)、数据结构(data structure)和内部机制(internal mechanism)的开发是依据以下理念的:
高效意味着每个HALCON算子的执行时间尽可能短。此外,算子的设计必须使标准序列或复杂任务的组合仍然高效。
开放的架构在两方面上很重要:
标准化意味着签名、命名、算子的使用和数据结构都严格遵循一定规则。这能使得学习变得更快速,歧义少。
最后,HALCON在文档中提供了每个算子以及它们的参数的详细信息(这也是为什么称作自描述的原因)。
HALCON的基础架构如下:
其主要部分是图像处理库(Image Processing Library),它由巨量的 operator(算子) 组成。您可以以扩展包的形式开发自己的算子包。你可以通过像HALCON/C++这样的编程语言接口的形式,在应用程序中使用算子。这些库允许在不同编程语言中直接使用算子。HDevelop也用了语言接口,但对用户来讲是透明的(即用户是看不到的)。
HALCON提供了名为 Image Acquisition Interface(图像采集接口) 的通用接口来访问图像采集设备。它以一种通用的方式来使用各种采集设备。该库包含特定设备的实现,在需要时会动态加载。
类似地,访问I/O设备也有专门的I/O设备接口。这些接口允许以同一种方式访问不同的I/O设备。这些库也是在需要时动态被加载。
HALCON中,图像处理库(包含大量算子)是核心。上层用户可以通过各种编程语言去调用这些算子。底层,HALCON有通用接口去访问图像采集设备和I/O设备。
HALCON库中的任何功能,都是通过算子来完成的。当前版本(笔者用的18.1)有超过2000个算子。大部分算子内部包含多个函数,可以通过参数去选择调用它们。所有算子的完整列表可以在HDevelop的算子对话框或参考手册中找到。算子重要特征如下:
小结:
- 算子间独立、并列,不存在复杂的依赖关系。
- 算子逻辑上也是有分组的,可以在类中查看到。
- 可以扩展HALCON的算子。
- 许多算子可以自动并行执行,大大提升执行效率。
基本概念:
基本概念:
Pixel Data(像素数据)
几乎任何值都可以是像素数据,从标准的8位灰度值到描述导数的浮点数。
对于整数,1、2、4字节(有无符号)都可用。除此之外,浮点数和复杂的图像数据也可用。它还支持用于描述边缘方向或色调值的特殊数据类型。
Image Channels(图像通道)
一个通道对应一个图像矩阵。每个图像最多能有65535个通道。一个图像所有通道的尺寸相同。
通常:单通道的灰度值图像、彩色图像带有三通道(如RGB)或来自多光谱传感器的多通道图像作为纹理滤波的结果。
图像通道,这个我觉得可以结合图像的来源进行理解。
简单讲一下相机输出图像的过程,
首先物体的光进入镜头成像后,像是打在感光芯片上的。芯片上有许多微小颗粒的传感器,每个(或每几个)传感器都会将光线变化转换为电信号变化,输出到外部系统。所以图像的每个像素点,实际上是对应相机的感光传感器的,两者间就像有通道连接一样,传感器对外界光线的变化导致像素变化,组合到图像上就是图像的变化。
黑白图像,可能只需要对应一个灰度通道。彩色的对应多个通道,然后根据色彩比例显示结果。
Coordinate System(坐标系)
图像的原点位于左上角像素的中心。使用行和列坐标访问独立的像素(就跟矩阵一样)。坐标的范围是从(0, 0)到(height - 1, width - 1)。
注意,由于原点是在左上像素的中心,所以像素的角具有非整数坐标。例如,左上角像素具有Corner Coordinate角坐标 (-0.5, -0,5), (-0.5, +0.5), (0.5,-0.5)和 (0.5, 0.5)。(如下图,假设该正方形就是图像左上)
基本概念:
区域属于图像数据。
区域被定义为一个像素集。区域的像素不需要彼此相连。这表示任意像素集都能当作单个区域来处理。使用算子 connection ,可以将一个区域划分为 connected components,即由连接的像素组成的组件。
区域的底层实现是基于runlength encoding(游程编码)的,它很高效。这种编码优点是:low memory consumption(低内存消耗)、efficient processing(性能卓越)和easy handling of ROI(易于处理ROI)。
游程编码其实是一种简单的无损压缩编码方式。
比如 aaabbbccc这个字符串,用游程编码表示就是3a3b3c。很明显在有大量连续相同的数据出现时,使用该编码方式压缩率很高。这边具体是怎么应用的,不讨论。
由于是基于游程编码实现的,随着连接组件的扩展,可能会出现重叠区域。这在基于标签图像的经典实现中是不会出现的。
区域内像素的坐标不限于给定图像的坐标,该区域可以大于图像,这可能是扩张操作导致的。可以使用参数值为 clip_region 的算子 set_system 来控制是否将区域截取到图像最大范围。
请注意,默认情况下,区域将裁剪为当前图像大小。只要没有创建或加载图像,他们就会被裁剪为默认图像大小(HDevelop:512✖512; 编程语言:128✖128)。为了防止不想要裁剪,建议在创建或加载区域之前创建或加载一个图像。
应用程序的区域数量可以任意多个。
基本概念:
基本概念:
如果学过编程的话,对句柄应该不陌生。引用一些复杂、抽象的结构时,往往是通过句柄。比如WinForm编程中的窗口句柄,一些底层资源的获取控制也是通过句柄。
元组这个概念可以先浅浅地理解一下,
元组(tuple),多个数据项捆绑在一起而形成的一个新的元素,用来表达一个复杂概念。
常见到的形式是这样的,(“小明”, “8岁”, “135m”, “30kg”)。
基本概念:
HALCON支持并行编程(例如,多线程编程。并且是线程安全和可重入的)。这意味着多个线程可以同时调用HALCON算子。除了支持并行编程外,若在多处理器或多核硬件(如dual-Pentium板)上运行,HALCON还会自动并行化算子。例如,对于四处理器的板子,图像会被分成四部分,然后由执行相同算子的四个线程并行处理。结合HALCON处理图像和区域的理念,这种形式的并行化非常高效,因为不需要复制图像。并行化程序会在线优化,以减小并行化开销。例如,非常小的图像不会被并行处理,因为并行的开销会超过并行化加速的提升。此外,并非所有的HALCON算子都适合并行化。
要注意的是,HALCON是为共享内存的系统设计的,即多个处理器共享一个公共内存的系统,这是典型的多处理器或多核板的情况。主要原因是,只有在共享内存系统中,线程才能共享HALCON对象数据库,且不需要拷贝图像。这种限制意味着HALCON的并行化技术不适合在工作站集群或其他不提供共享内存的多处理器或多核硬件上使用。
HALCON支持GPU处理,使用GPU能显著加速你的程序。在HALCON上,只需要选择开/关就能在GPU上执行代码,非常简单易用,它的实现依赖于OpenCL,因此独立于生产商,甚至不限制显卡。
它支持所有的新NVIDIA和ATI卡。兼容显卡的列表可以在下面网址查阅:
始终安装最新的驱动。对于AMD来说,Stream SDK仍然需要被安装。
许多HALCON算子支持计算设备。在参考手册中可以查阅到算子是否支持计算设备。若算子支持计算设备,如 edges_sub_pix ,在’并行化(parallelization)'部分中会提到。
正如前面所说的,GPU处理非常简单易用。GPU使用算子 init_compute_device 进行初始化。GPU处理使用 activate_compute_device 打开,使用 deactivate_compute_device 关闭。
要注意,在GPU上计算,数据将会从CPU转移到GPU上。转移数据会消耗一些处理时间。因此,为了充分加快GPU处理流程,推荐:
但是,使用计算设备并不总是能提高运行性能。有些情况,一般的CPU处理也许更快:
当在GPU上计算时,默认只有一张显卡会被使用。当然,你也可以使用多张显卡(计算设备)。多计算设备下,每个设备会使用一个线程。
HALCON对常规尺寸的图像做了优化,即尺寸不大于32768✖32768。但是,特别是线扫描相机应用,通常会提供大图,它的高度往往超过32768。对于这些应用,你可以使用HALCON XL,它不会对图像尺寸做出限制。
但它仍然会有一些其它限制:
目前,HALCON以动态链接库(Windows上是DLL,类Unix上是共享库)的形式为超过50种图像采集卡(frame grabber)和数百种工业相机(analog、Camera Link、USB 2.0、IEEE 1394和GigE)提供了接口。这些库和HALCON库一起被安装,它们的名字以hAcq为前缀;HALCON XL使用的库以xl为后缀结尾。
HALCON图像采集接口库是图像采集设备制造商提供的软件与HALCON之间的桥梁。它们生成一个通用的接口,只需要(调用)一些算子即可。
若你成功安装了图像采集设备,从HALCON中访问它你需要做的就是调用 open_framegrabber 算子,指定图像采集接口的名称和一些额外参数,如:要连接的相机等。然后,通过调用 grab_image(或grab_image_async) 算子来获取图像。
注意,HALCON图像采集接口可能比HALCON库本身变更更频繁。原因之一是MVTec会不断开发新接口;此外,若图像采集设备制造商提供的软件发生变化,例如,如果集成了新功能,则会添加相应的HALCON接口去适配它。你可以在这里查找最新的信息和可下载的接口及文档。
HALCON为多种I/O设备(有时也称I/O模块)提供接口以启用数据采集。这些接口也是通过动态链接库中使用的。库的名称以hio为前缀;同样,HALCON XL用的库以xl为后缀。
HALCON I/O设备接口使用一小组算子提供对不同I/O设备统一的访问方式。在你安装完I/O设备后,使用算子 open_io_device 建立一个连接,指定I/O设备接口的名称并选择一些设备指定参数。一旦建立连接,就可用通过调用 open_io_channel 打开一个传输通道(transmission channel)。要在该通道上读写值,分别使用 read_io_channel 和 write_io_channel 。
注意,HALCON I/O设备接口也可能变动比HALCON库本身更频繁。
HDevelop是一款用于原型和应用程序开发的强大IDE,简单易用。
在Windows下就和一般软件一样,安装完双击HDevelop图标即可启动。
要加载一个示例,选中 文件> 打开程序 ,会出现一个文件选择框,该框内会展示HDevelop示例(Windows下)的主要目录。对于初学者,推荐从中选一个示例进行学习。你也可以使用菜单中的 文件> 浏览HDevelop示例程序 ,选中某个类别的例程后打开(这种方式相比之前的选择目录更直观)。
在加载例程后,相应的程序代码会在程序窗口展现。使用的变量在变量监测窗口中可用看到(还未被实例化)。程序现在准备好执行了。
运行程序的步骤:
除了 运行 按钮,HDevelop还提供了一个用于逐句执行程序(step through program)的按钮——执行单行并随后立即显示结果。 若该过程包含一定步骤, 则 单步跳入(step into) 和 单步跳出(step out) 会很有用。
若要再次执行已运行完的程序,点击 重置程序执行(set program to initial state) 然后 运行 。
要将某个部分再次执行,用鼠标点击想要执行代码行的左侧,使得程序计数器(绿色箭头)重新定位,然后点击 运行 。
理解程序的提示:
在主窗口的底部,HDevelop提供了一个状态栏,它会显示一些有用的提示信息。尤其是在执行期间,当程序停止以可视化结果或等待用户交互时,它会给出相应的指示/提示。
对于个别程序行的信息,双击它们使得应用的算子名称及其参数显示在 算子/过程 窗口中。帮助按钮会提供具体信息。
许多程序会自动将相关数据显示在图像窗口中。手动可视化可以通过双击变量监测窗口中的图标轻松实现。
一些示例包含过程。包含过程的程序行会被颜色标记,颜色由菜单栏的 编辑(Edit)> 参数选择(Preferences)> 用户接口(User Interfaces)> 程序窗口(Program Window) 指定。
你可以通过程序窗口中的"程序"组合框在程序间进行切换。
在许多示例中,会出现赋值、算术运算(两者在程序中通常用":="表示)或循环之类的控制结构。
更多HDevelop提示:
正如架构图中所呈现,HALCON提供了编程语言接口。语言接口是库,使你能够以一种简单的方式调用算子和使用HALCON库的数据类型。它为两种语言设计了专门的语言接口,它们是C和C++。相反,.NET接口可以被不同的语言使用,如VB、C#。
与你选择的编程语言无关,一个适配的接口库(halconc.,halconcpp.,halconx.*)与HALCON库必须被链接到应用程序。除此之外,C和C++对应的头文件也必须被引入;若是.NET程序,对应的程序集 halcondotbet.dll 必须被引用。
要开始开发,推荐首先检查准备运行(ready-to-run)示例程序之一。该示例中,你可以看到工程如何被安装以及如何使用算子和数据类型。
每种编程语言接口中的类和类型的命名,算子的命名规范等,可能会不同于该编程语言传统的命名规则。
编程语言调用有多种(C++、C、C#),我这边就介绍下C#的,因为该项目开发主要用C#。
C#和VB .NET都是通过.NET接口使用HALCON。
和C++相似,.NET调用提供了两种风格:面向过程(procedural)和面向对象(object-oriented)。面向过程风格的,HOperatorSet提供所有HALCON算子,其中HObject用于处理图像数据,HTuple用于处理控制数据;对于面向对象,像HDataCode2d、HMeasure和HShapeModel这样的类被提供用于核心功能。此外,图像数据的类,可以用HImage和HRegion。
下面代码展示了一个C#示例程序来读取一个图像并且应用基本的blob分析。
HImage image = new HImage("monkey");
HRegion region;
region = image.Threshold(128, 255);
HALCON很容易被新的算子扩展。尽管HALCON已经包含超过2000个用于处理各种任务的算子,但你仍可能需要新的算子以满足你的需求,例如,为了访问一个特殊的硬件或实现一种非传统的算法。为了做到这些,HALCON提供了 扩展包接口(extension package interface) ,它允许以扩展包的形式集成新算子(在C中实现)。它包含了一些预定义好的规则和宏,用于在C中简单处理图像和内存对象。一旦新的算子被成功集成,它就能像其它HALCON算子那样被使用。
使用的是相似的机制,图像采集接口使用动态库集成。它允许你集成未支持的图像采集设备,而无需进一步更改系统的其余部分。如何创建和集成一个图像采集接口在图像采集接口程序员手册中有详细描述。HALCON还带有一个模板源代码,可以用作集成基础。
同样类似,I/O接口也使用动态库集成。它允许你在不进一步改动系统的情况下,集成未支持的I/O设备。创建和集成一个I/O设备接口的方式在 %HALCONEXAMPLES%\io_integration\README.txt 详细描述。HALCON带有模板源代码,可以用作集成基础。
使用HALCON XL,HALCON以前的许多限制会被移除。下面列举了剩余的一些与使用HALCON进行典型应用程序开发相关的其余内容。
目前,以下限制应用在计算设备的使用中。
基于纹理的算子被限制在显卡的最大尺寸。目前限制为 8192×8192 。下列是相关算子:
进一步的限制,如下
使用OpenGL用于视觉化(visualization)的算子需要OpenGL 2.1、GLSL 1.2 和 OpenGL扩展 GL_EXT_framebuffer_object 和 GL_EXT_framebuffer_blit 。因此,这些算子无法通过Windows远程桌面或SSH转发使用。