HALCON 快速入门手册
1 什么是 HALCON
HALCON 是德国 MVtec 公司开发的一套完善的标准的机器视觉算法包,拥有应用广泛
的机器视觉集成开发环境。它节约了产品成本,缩短了软件开发周期——HALCON 灵活的
架构便于机器视觉,医学图像和图像分析应用的快速开发。在欧洲以及日本的工业界已经
是公认具有最佳效能的 Machine Vision 软件。
2 获取与安装 HALCON
各个版本下载地址: https://pan.baidu.com/s/1ecI5KMuzJRmyzX6XvPCj2A
License 下载地址: https://www.51halcon.com/thread-387-1-1.html
若不可用,也可以网上自行查找下载。
3 HALCON 的界面与功能
HALCON 的界面包括菜单栏与工作区,菜单栏包括了文件、编辑、执行等必须的操
作,工作区则是我们在新建文件后的主要界面,它包括四个部分,也就是四个窗口,分别
是图形窗口,算子窗口,变量窗口以及程序窗口。
3.1 图形窗口
图形窗口是我们观察图像的区域。我们可以在程序中通过代码打开,关闭,清空该窗口,
以及调整窗口的形状大小。
3.2 算子窗口
算子窗口可以用来很方便的查找我们所需要的 HALCON 算子,同时可以在窗口中设置相
关的参数, 设置完毕后点击下方的“输入”,便会自动的将所生成的相应代码插入到程序窗
口的光标位置。
所有运算子的参数都是以相同的方式排列: 输入图像,输出图像,输入控制,输出控制。
(某一项参数可以缺失,但是顺序不能乱)
3.3 程序窗口
程序窗口即是我们编写程序的面板,执行程序时,我们可以在菜单界面上选择单步执行
与直接执行 两种方式。
3.4 变量窗口
变量窗口用来监视程序中涉及到的变量。
HALCON 有两种基本的数据型态 : 图像数据 (iconic ,例如影像 ) 以及控制数
据 ( control ,例如 变量,整数,字符串, handle 等等 ) 。
说明: 这四个窗口都是可以灵活控制所在位置与开闭状态的,如果已经关闭的窗口,需要
打开,可以在上方菜单栏的“窗口”中找到打开。
4 HALCON 操作流程
4.1 获取图像
获取图像有实时采集与读取文件两种方式,在助手--->打开新的 ImageAcquisition 当
中可以非常方便的帮助我们选择我们获取图像的方式及相关参数。
4.1.1 读取图像文件:
菜单栏中的助手--->打开新的 ImageAcquisition--->图像文件--->选择文件--->代码生成
--->插入代码
点击插入代码之后,可以看到在程序窗口中自动添加了代码。其中第一行是注释,以“*”开
头。
第二行即是读取图像文件的代码。 Read_image 即为读取图像的算子,括号中,第一个参数
是给所选择图片的命名,第二个参数为所选择图片的路径。
4.1.2 实时采集
菜单栏中的助手--->打开新的 ImageAcquisition--->自动获取接口或者选择接口--->在连
接中进一步选择设备及端口等参数--->代码生成
4.2 使用算子处理图像
以下是读取一张图片并对该图片进行图像增强的程序。
*读取图片
read_image (Image, 'F: /architecture-building-business-2339009.jpg')
*得到该图片的尺寸大小
get_image_size (Image, Width, Height)
*关闭初始化的图形窗口
dev_close_window ()
*打开新的跟图片长宽比例符合的合适大小的图形窗口
dev_open_window (0, 0, Width/10, Height/10, 'black', WindowID)
*在新窗口上显示图片
dev_display(Image)
*图像增强处理,五个参数分别为:所处理的图像名称,处理后得到图像的命名,掩模的
宽,掩模的高,增强的系数 Factor
emphasize (Image, ImageEmphasize, 7, 7, 2)
4.3 导出文件
如需与其他语言进行联合编程,可以在文件--->导出中导出所需要的相应语言。
5 使用 HALCON 进行模板匹配(基于形状) 的步骤
代码部分可参考 Halcon 中自带的例程,位于浏览例程--->模版匹配(基于形状--->
第一个例程。
本步骤最后可通过基于形状的模板匹配得到匹配图像的轮廓线。
(1)对要创建模版的物体进行拍摄
(2)根据模版的形状创建相应的区域
本例创建的为一个矩形区域,可根据不同的要求建立不同的图像区域,便于后续的区
域采集
gen_rectangle1( Rectangle, Row1, Column1, Row2, Column2 ) 根据对角线上的两点坐
标(图像像素点)建立一个矩形区域
(3) 将模版所在区域从图像中分离出来
reduce_domain(Image, Region, ImageReduced)
注: Image:由步骤(1)得到的图像变量
Region: 由步骤(2)生成的几何区域
ImageReduced:分离后得到的图像
(4)创建模版
create_shape_model(Template,NumLevels,AngleStart,AngleExtent, AngleStep,
Optimization, Metric, Contrast, MinContrast ,ModelID)
注: Template:由步骤(3)得到的分离后的图像
NumLevels:图像金字塔级数,该值越小,模版匹配时间越长,可设置为“auto”
AngleStart:模版起始角度
AngleExtent:模版角度幅度,若目标有旋转,模版需做不同角度
AngleStep:角度步长,可设置自动“auto”
Optimization:模版点存储模式,设为“none”时,全点储存。当模版较大时,可较小点
数,用于提速。
Metric:图像与模版中对比度差异不大时,选择“use_polarity”即可
ModelID:输出模版 ID。唯一确定模版(在多模版情况下)
(5)得到的模板的轮廓
get_shape_model_contours( ModelContours, ModelID, Level )
注: ModelContours:得到的模板轮廓
ModelID:由步骤(4)得到的模板 ID
Level:返回模板的金字塔水平
(6)在另一幅图像中寻找模板对应的区域
find_shape_model(Image, ModelID, AngleStart, AngleExtent, MinScore, NumMatches,
MaxOverlap, SubPixel, NumLevels, Greediness , Row, Column, Angle, Score)
注: Image:待搜索的图像
ModelID:搜索模版对象的 ID
AngleStart:搜索起始角度
AngleExtent:搜索角度幅度(匹配时,搜索设定角度范围内的模板)
MinScore:最小匹配分值。此参数定义模版匹配时,至少有个什么样的质量参数才算
是在图像中找到模版。 MinScore 设置的越大,搜索的就越快。
NumMatches:匹配个数。若满足匹配分值的结果个数大于该值,则返回质量系数最
好的结果;若满足匹配分值的结果个数小于等于该值,则返回所有结果。设置为 0 时,返
回所有满足的结果。
MaxOverLap:定义两个目标区域最多重叠的系数,以便于将其分开为两个不同的目标
区域分别返回。
SubPixel:精度控制。该参数的选择影响定位结果参数。此值越高速度也越慢。
None(不使用亚像素) 'interpolation'(差值亚像素) 'least_squares_high'(最小二乘亚像
素) 'least_squares_high'(最小二乘亚像素) 'least_squares_very_high'(最小二乘亚像
素)
NumLevels:搜索时使用金字塔层数。可选为 0
Greeddiness:用于控制定位加速。此值越大,匹配速度越快,找丢模板的几率也越
大。推荐值为 0.7-0.8
Row:图像中与模板匹配的区域的像素横坐标(多个区域时以元组形式存在)
Column: 图像中与模板匹配的区域的像素纵坐标(多个区域时以元组形式存在)
Angle: 图像中与模板匹配的区域的角度(多个区域时以元组形式存在)
Score:图像中与模板匹配区域的个数
(7) 确定匹配位置的轮廓
vector_angle_to_rigid(Row1, Column1, Angle1, Row2, Column2, Angle2, HomMat2D)
从点和角度确定一个刚体仿射变换(矩阵)
注:
Row1、 Column1 及 Angle1 : 分别为初始模板的像素横纵坐标和旋转角度。可设置为
0, 0, 0。
Row2、 Column2 及 Angle2 分别为步骤(6)所确定的 Row 和 Column。
HomMat2D: 最后得到的结果。
affine_trans_contour_xld(Contours, ContoursAffinTrans , HomMat2D )
得到匹配图像的轮廓线
注:
Contours:模板的轮廓线
ContoursAffinTrans:匹配图像的轮廓线
HomMat2D:上一个函数得到的刚体仿射变换矩阵
6 HALCON 常见函数
6.1 图像分割
(1) threshold( Image , Region , MinGray , MaxGray )
通过确定 MinGray(最小灰度)和 MaxGray(最大灰度)值对一幅灰度图像进行分割,满
足区域灰度值介于最小最大之间的图像区域保存至 Region 变量中
注:此函数重点在于确定 MinGray 和 MaxGray 的数值,以下介绍如何使用 Halcon 中的工
具进行确定。
1.选择一幅图片,并且使其在 Halcon 中的“图形窗口”中打开,如下图:
2.鼠标右键单击图像,选择“灰度直方图”,出现下图所示窗口。
3.点击 后即可通过移动直方图中的绿线和红线进行最小最大灰度值值确定,在移动两条
线的过程中步骤 1 中打开的图像上会有红色区域的变化,此区域即为分割后的图像区域。
4.确定完成后,将步骤 2 中的灰度直方图窗口中最小化和最大化的数值填入函数中即可。
(2) connection( Region , ConnectedRegions )
计算 threshold 函数分割出图像的连通分量
注: Region 为 threshold 函数输出的结果
ConnectedRegions 为此函数最后的结果
(3) select_shape(Regions , SelectedRegions , Features , Operation , Min , Max )
通过不同的特征选择出期望的图像
注: Regions 为处理前的图像
SelectedRegions 为特征处理后的图像
Features 为指定的特征,常用的值如下所示:
‘area’ ‘width’ ‘height’ ‘contlength’ ‘holes_num’ ‘area_holes’ | 对象的面积 区域的宽度 区域的高度 轮廓线的总长 区域内洞数 所有洞面积 |
以上条件可并列处理,在 Operation 中输入‘and’即可
Min 和 Max 为特征的取值范围
(4) fill_up( Region , RegionFillUp )
将区域中的洞填满
注: Region 为处理前的图像
RegionFillUp 为处理后的图像
此函数处理后的图像可方便进行目标物体的外轮廓提取。
(5) area_center( Regions , Area , Row , Column )
获取指定图形的像素面积以及图形中心点坐标
注:
Regions 为指定图形。
Area 为得到的图形像素面积。
Row 为图形中心像素横坐标。
Col 为图形中心像素纵坐标。
6.2 轮廓提取、处理
(1) gen_contour_region_xld( Regions , Contours , Mode )
提取出指定图像的外轮廓
注:
Regions | 为指定图像 |
Contours 为提取出的轮廓线 | |
Mode ‘center’ ‘border’ | 为轮廓线的模式,可取值如下: 边缘像素点的中心作为轮廓点 边缘像素点的外边作为轮廓点 |
(2) segment_contours_xld( Contours , ContoursSplit , Mode , SmoothCont ,
MaxLineDist1 , MaxLineDist2 )
将轮廓线分为多个部分
注: Contours 为待分割的轮廓线
ContoursSplit 为分割后的轮廓线片段
Mode 指定分割轮廓的方式,可取值如下:
‘lines’ ‘lines_circles’ ‘lines_ellipses’ | 使用直线分割 使用直线段和圆进行分割 使用直线段和椭圆弧进行分割 |
SmoothCont 轮廓平滑的参数,若此值取得大于 0 的数值,则在分割之前会进行
轮廓的平滑处理。
MaxLineDist1:在第一次迭代过程中轮廓线和近似直线的最大距离。默认取值为
4。
MaxLineDist2: 在第二次迭代过程中轮廓线和近似直线的最大距离。默认取值为
2。
(3) select_contours_xld( Contours , SelectedContours , Feature , Min1 , Max1 ,
Max2 , Max2 )
通过不同的特征,提取出分割后轮廓中满足要求的轮廓线段。
注:
Contours 为一组由原始轮廓分割后的片段。
SelectedContours 为提取出满足条件的线段。
Feature: 为提取条件,常用取值如下:
‘contour_length’ 围, Min2 和 Max2 没有作用。 ‘direction’ | 长度,指定此值后,通过 Min1 和 Max1 即可确定范 |
方向,由倾斜角度表示;指定此值后,通过 Min1 和 | |
Max1 即可确定范围, Min2 和 Max2 没有作用。 | |
‘closed’ ‘open’ | 起始点和终止点距离的上限;由 Max1 即可确定。 起始点和终止点距离的下限;由 Min1 即可确定。 |
‘Min1’,‘Max1’分别为取值的范围
(4) select_obj(Objects , ObjectSelected , Index )
通过编号选择出某一对象,可用于从轮廓线段集合中选择指定线段。
注:
Objects 为待选择的对象集合
ObjectSelected 为选择得到的对象
Index 为指定的对象编号
(5) get_contour_xld( Contour , Row , Col )
获取指定轮廓上点的像素坐标
注:
Contour | 为指定的轮廓线段 |
Row | 为返回的像素点横坐标 |
Col | 为返回的像素点的纵坐标 |
(6) reduce_domain( Image , Region , ImageReduced )
将位于轮廓线 Region 内的图像提取出来
注:
Image 为待提取的图像。
Region 为轮廓线。
ImageReduced 为提取后的图像。
(7) distance_cc_min( Contour1 , Contour2 , Mode , DistanceMin)
计算两个轮廓线之间最小的距离
注:
Contour1 和 Contour2 为两条待比较的轮廓线。
Mode 为计算距离的类型,可取值如下:
‘point_to_point’ 两轮廓线中点之间的最短距离。
‘point_to_segment’ 两轮廓线中线段之间的最短距离。
DistanceMin 为最终得到的结果。
7 halcon 与 C#联合编程
Halcon 作为一款强大的图形图像处理软件,可对工作中遇到的各种图像进行处理,同
时还有功能强大的算子以及很全面的例程,作为进行处理的主程序是非常不错的。但是,
halcon 依旧有缺陷,就是无法做到图形化界面的建立,故需要和其他软件联合编程才行。
恰好, halcon 可以导出成各个语言进行二次开发。本文即介绍如何用 halcon 和 C#进行联
合开发。
(1)显示图像
C#与 Halcon 联合编程第一步就是调用 Halcon 图像处理数据库,是否调用成功,通常是利
用 Halcon 的图像显示控件能否正确显示图像进行判断。下面就简单介绍一下如何利用 C#
调用 Halcon 图像显示控件来显示图像。
1.创建 C#项目,创建一个 Windows 窗体应用程序。
2.在项目中引用 Halcon 的 DLL 文件。鼠标右键单击“引用”–“添加引用”,如下图:
在弹出的引用管理器中点击下方的“浏览”按钮。选择 Halcon 安装目录下的 halcondotnet.dll
文件,点击添加–确定。本文以 halcon12 为例子,如下图:
引用成功后 halcondotnet 会出现在引用项目里。
3.添加 halcon 图像显示控件。在 Visual Studio 左侧点击“工具箱”,在空白区域点击鼠标右
键,选择“选择项”。在".NET Framework 组件“这一页中点击”浏览“按钮,同样添加刚刚引用
的那个 halcondotnet.dll 文件。
添加成功后,在常规一类中会出现 HWindowControl 这个控件。如下图。
将该控件添加到界面上。如下图:
查看添加的这个 HWindowControl 控件的属性可以看到控件的名称为 hWindowControl1,
这个名称在程序中会用到。如下图:
4.在程序中进行图像的显示。添加的语句都有注释。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;//添加这一句
namespace HalconWindows
{
public partial class Form1 : Form
{
HWindow win = null;//定义一个 Halcon 窗口对象
HImage image = null;//定义一个 Halcon 图像变量
public Form1()
{
//win = hWindowControl1.HalconWindow;这句放在 InitializeComponent()函
数前执行会报错
InitializeComponent();
win = hWindowControl1.HalconWindow;//将 Halcon 窗口对象与控件进行关
联
image = new HImage();//实例化图像变量
image.ReadImage(@"e:\rmb.png");//读取图像
int width = 0, height = 0;//创建变量用于接收图像尺寸
image.GetImageSize(out width, out height);//获取图像尺寸
win.SetPart(0, 0, height - 1, width - 1);//设置 Halcon 控件中图像的显示尺寸
win.DispObj(image);//显示图像
}
}
}
此外,在引用 dll 文件后,可能在运行的时候会报错,可以尝试修改一下项目的框架版本。
具体位置:鼠标右键单击项目文件—属性—应用程序----目标框架
(2) 通过打开电脑上的图片文件显示图像
首先,即先将代码导出,导出为 C#格式。
选择 C#-HALCON/.NET,窗口导出时选择使用 halcon 窗口,找到导出的文件用 VS 打开。
对于导出后的代码, halcon 原有的程序放在 action 中,需要自己对 action 中的文件进行分
类归纳,同样也可在 halcon 中直接进行函数封装后再导出。
对于导出的程序,是无法直接运行的,编译器会首先在这一句报错:
using HalconDotNet;
这是由于还未将 halcondotnet.dll 文件添加进入你的工程中,首先右键资源管理器,然后添
加->引用->浏览,找到你的这个文件,这个
库文件是放在你的安装程序文件夹下 C:\Program Files\MVTec\HALCON-
10.0\bin\dotnet35(这个是我的安装位置),然后添加进入。现在程序中的报错已经没有了,
可以正确运行了。
你可以在一个 Form 窗口上创建一个 button,然后在设计窗口双击该 button,进行 button
编辑。然后一点点的将 action 中的东西拿来用
做成一个界面图像处理的小软件。同时, halcon 中提供的画面显示窗口并不好用,如果想
在界面上直接显示图像的话,最好在界面上添加一个 halcon 封好的固定窗口。方式,点击
工具箱,拉到最下,有个 halcon 的小图标,那个就是窗口,拖到 Form 上,作为显示窗
口,调用的接口是:
hWindowControl.HalconWindow
下面是一个打开文件并显示的例程,可供参考。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
// halcon 命名空间
using HalconDotNet;
using namespace example
{
public partial class test Form
{
HDevelopExportModel HD = new HDevelopExportModel();
public Htuple hv_ExpDefaultWinHandleModel;
private void CreatModel(object sender, EventArgs e)
{
//这个是我在窗口上创建的一个 button,点击该 button 后,打开文件选择一
张图片,并将图片进行显示。
// 建立模板按钮
string ImagePath; // 定义模板图片的路径
HObject readImage = null; // 定义一个图像常量
OpenFileDialog openFileDialog1 = new OpenFileDialog(); //打开文件进行选择
openFileDialog1.Filter = "BMP 文件|*.bmp*|PNG 文件|*.png*|JPEG 文件|*.jpg*";
//图片的文件格式
openFileDialog1.RestoreDirectory = true;
openFileDialog1.FilterIndex = 1;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// 如果可以打开该文件路径,将该文件路径的图片显示在
hWindowControl2 窗口,并将图片变量赋值给 readImage
ImagePath = openFileDialog1.FileName;
readImage = HD.ReadPicture(hWindowControl2.HalconWindow,
ImagePath);
// 读取这张图片并将图片赋值给 readImage,这句就是直接调的 halcon
类了,下边 public 定义的的是他的类
}
}
}
public partial class HDevelopExportModel
{
public HObject ReadPicture(HTuple window, string ImagePath)
{
// 得到图片显示的窗口句柄
hv_ExpDefaultWinHandleModel = window; //从上个函数传进来的窗口句柄
HOperatorSet.GenEmptyObj(out ho_Image);
ho_Image.Dispose();
HOperatorSet.ReadImage(out ho_Image, ImagePath); //从这个路径读取图片
HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height); //得到
他的大小
HOperatorSet.SetWindowAttr("background_color", "black");
//调整窗口显示大小以适应图片,这句一定要加上,不然图片显示的不全
HOperatorSet.SetPart(hv_ExpDefaultWinHandleModel, 0, 0, hv_Height - 1,
hv_Width - 1);
HOperatorSet.DispObj(ho_Image, hv_ExpDefaultWinHandleModel); //将图像
在该窗口进行显示
return ho_Image; //返回这个图像
}
} //end HDevelopExportModel
}// end example
你可以在 HDevelopExportModel 类中添加各种函数以便在窗体上操作时进行调用,这
个就靠自己开发了。
在调用时, 尽量要将 action 中的程序封装成多个子函数进行调用, 否则在程序越写越
大时就会不易控制。