前言

将halcon 封装成函数导出 ,再让c#通过引擎太调用,这种方法当比与直接用c#去写halcon代码,有着很多好处。调用Halcon引擎有两个直接的好处:

  1. 避免C# 与Halcon代码混编时可能产生的内存泄露问题(即已分配的内存未能成功释放,导致可用内存逐渐减少的现象。)因为使用混编时,halcon的变量都需要手动释放,每一个变量用完之后,都需要Dispose()和置Null。因此有hobject的地方都要谨慎考虑内存释放问题。
  2. 修改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。

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

更多推荐