halcon联合c#、WPF之如何通过c#调用halcon外部程序hdvp
前言
将halcon 封装成函数导出 ,再让c#通过引擎太调用,这种方法当比与直接用c#去写halcon代码,有着很多好处。调用Halcon引擎有两个直接的好处:
- 避免C# 与Halcon代码混编时可能产生的内存泄露问题(即已分配的内存未能成功释放,导致可用内存逐渐减少的现象。)因为使用混编时,halcon的变量都需要手动释放,每一个变量用完之后,都需要Dispose()和置Null。因此有hobject的地方都要谨慎考虑内存释放问题。
- 修改halcon程序时不用重新编译C#,可以实现前后端分析,和多人合作完成项目。Halcon视觉工程师,只需要专注于视觉检测算法逻辑即可。
本文详细介绍使用c#调用halcon引擎来调用hdvp外部程序。
一、使用halcon封装程序并导出
1.打开 Halcon 程序,编写脚本代码,这里以一个简单的模板匹配程序为例,读取本地目录的一张图片,生成ROI,创建模板,继续匹配该图片上是否有类似的图案。
halcon脚本代码如下:
read_image (Image, 'C:/Users/YNW1HZ2/Desktop/brake.png')
get_image_size(Image, Width, Height)
Row1 := 116
Column1 := 183
Row2 := 184
Column2 := 263
gen_rectangle1(Rectangle1, Row1, Column1, Row2, Column2)
*将图像限定在模型ROI区域内。
reduce_domain (Image, Rectangle1, ImageROI)
*创建一个形状模型,其中包括旋转角度、极性和精度等参数,结果存储在 ModelID 中。
create_shape_model (ImageROI, 4, 0, 0, 'auto', 'none', 'use_polarity', 30, 10, ModelID)
*检查形状模型,显示模型图像和区域。
inspect_shape_model (ImageROI, ShapeModelImage, ShapeModelRegion, 1, 30)
*在图像中找到模版匹配的对象
find_shape_model(Image, ModelID, -0.39, 0.79, 0.5, 20, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score)
if (|Score| > 0)
for i := 0 to |Score| - 1 by 1
gen_rectangle2_contour_xld(Rectangle1, Row[i], Column[i], Angle[i], Width/16, Height/14)
dev_display(Rectangle1)
endfor
endif
该脚本读取了本地的一张图,将左上角的圆圈,作为模板学习并保存了模型,然后继续在该该原图上进行模板匹配,并将左上角用于学习的和图中剩余的三个圆圈都找出来了。如图下图所示左上角是模板,其他三个就匹配出来的结果。

2. 导出为 HDVP 文件:
选择要封装的halcon代码创建新的过程,保存为并命名保存为 ShapeMatching.hdvp。


根据实际情况定义HDVP脚本的输入和输出,这些输入和输出变量将在后续C#代码中用上

二、在C#中通过Halcon引擎调用HDVP脚本
1.新建一个WPF项目,并配置相关halcon环境,具体操作就不赘述。在添加相关reference的时候,一定要记住把hdevenginedotnet.dll 这个引擎调用的脚本添加上。
2. 在画面上增加按钮和图像显示页面
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFshapematch"
xmlns:ha="http://schemas.mvtec.com/halcondotnet" x:Class="WPFshapematch.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ha:HSmartWindowControlWPF Name="hswControl" HorizontalAlignment="Left" Height="329" Margin="62,50,0,0" VerticalAlignment="Top" Width="483"/>
<Button Content="loadimage" HorizontalAlignment="Left" Margin="582,50,0,0" VerticalAlignment="Top" Width="90" Height="36" Click="Button_Click"/>
<Button Content="Processiamge" HorizontalAlignment="Left" Margin="582,114,0,0" VerticalAlignment="Top" Width="90" Height="35" Click="Button_Click_1"/>
</Grid>
</Window>
效果如图所示:

3. 最后就是编写按钮和显示的程序,载入图片的按钮程序也不过多赘述, 重点说明一下如何通过Processiamge这个按钮实现对halcon hdvp程序的调用
3.1 首先需要创建 Halcon 引擎实例
HDevEngine MyEngine = new HDevEngine();
作用:初始化 Halcon 的 HDevEngine,这是执行 Halcon 过程(.hdvp 或 .hdev)的核心引擎。
注意:每个应用程序通常只需一个引擎实例。
3.2 声明过程与过程调用对象**
HDevProcedure Procedure;
HDevProcedureCall ProcCall;
HDevProcedure:表示一个 Halcon 过程(.hdvp文件),包含过程的元数据(如输入输出参数定义)。HDevProcedureCall:用于调用具体的过程实例,管理执行时的输入输出参数。
3.3 设置过程文件搜索路径**
MyEngine.SetProcedurePath(@"C:\Development\Halconpro");
- 作用:告诉 Halcon 引擎在指定目录中查找
.hdvp文件。 - 关键点:
- 路径必须存在且包含
ShapeMatching.hdvp文件。 - 可设置多个路径(用分号分隔):
MyEngine.SetProcedurePath(@"C:\Path1;C:\Path2");
- 路径必须存在且包含
3.4 加载指定过程**
Procedure = new HDevProcedure("ShapeMatching");
- 作用:从设置的路径中加载名为
ShapeMatching的.hdvp文件。 - 错误风险:
- 若文件未找到,抛出
HalconException(错误代码6001)。 - 文件内容必须合法(通过 Halcon 导出生成)。
- 若文件未找到,抛出
3.5 创建过程调用实例
ProcCall = new HDevProcedureCall(Procedure);
- 作用:基于加载的
Procedure创建一个可执行的实例。 - 注意:一个
HDevProcedure可创建多个独立的HDevProcedureCall实例(并行安全)。
3.6 设置输入参数
ProcCall.SetInputIconicParamObject("Image", ho_Image);
- 作用:将
ho_Image(类型为HObject的图像)传递给过程的输入参数Image。 - 关键点:
- 参数名
"Image"必须与.hdvp文件中定义的输入参数名 完全一致(区分大小写)。 - 若参数类型不匹配(例如期望图像但传入了区域),会抛出异常。
- 参数名
3.7 执行过程
ProcCall.Execute();
- 作用:运行
ShapeMatching过程中定义的 Halcon 代码逻辑。 - 错误处理:
- 执行过程中若 Halcon 代码出错(如找不到模板),抛出
HalconException。
- 执行过程中若 Halcon 代码出错(如找不到模板),抛出
3.8 结果处理
定义HTuple 变量,接收执行过程后的结果,这些结果就是之前在halcon封装hdvp时候定义的输出,最后可以根据输出值把结果打印在图片上以及对其进行标记。最终运行结果如下:

完整代码参考代码如下:
HDevEngine MyEngine = new HDevEngine(); //初始化halcon engine
HDevProcedure Procedure; // 概括一个Procedure,其输入输出参数的数量、名字等其他信息
HDevProcedureCall ProcCall; //管理一个Procedure的实例,比如运行等其他操作
MyEngine.SetProcedurePath(@"C:\Development\Halconpro");
Procedure = new HDevProcedure("ShapeMatching"); //指定具体Procedure名字
ProcCall = new HDevProcedureCall(Procedure); //实际运行的实例
ProcCall.SetInputIconicParamObject("Image", ho_Image);
ProcCall.Execute(); //执行Proc
HTuple Row = ProcCall.GetOutputCtrlParamTuple("Row");
HTuple Column = ProcCall.GetOutputCtrlParamTuple("Column");
HTuple Angle = ProcCall.GetOutputCtrlParamTuple("Angle");
HTuple Score = ProcCall.GetOutputCtrlParamTuple("Score");
HTuple hFonts = hswControl.HalconWindow.QueryFont();//可以在窗体设置的字体列表
string FontStr = hFonts.TupleSelect(1);//选择第一个字体
int size = 25;//设置字体大小
hswControl.HalconWindow.SetFont(string.Format("{0}-Normal-{1}", FontStr, size));
hswControl.HalconWindow.SetColor("green");
hswControl.HalconWindow.SetTposition(50, 50);
hswControl.HalconWindow.WriteString("find " + Score.TupleLength() + " area");
if ((int)(new HTuple((new HTuple(Score.TupleLength())).TupleGreater(0))) != 0)
{
for (i = 0; i <= Score.TupleLength() - 1; i = i +1)
{
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
HOperatorSet.GenRectangle2ContourXld(out ho_Rectangle1,
Row.TupleSelect(i), Column.TupleSelect(i), Angle.TupleSelect(i),
hv_Width / 16, hv_Height / 14);
hswControl.HalconWindow.DispObj(ho_Rectangle1); ;
}
ho_Rectangle1.Dispose();
}
}
总结
至此,我们实现了使用c#调用halcon外部程序hdvp
更多推荐


所有评论(0)