Halcon联合C#开发最新版实用框架 实际项目应用验证过的版本,源码,修改了大量Bug以适合...

Halcon联合C#开发最新版实用框架 实际项目应用验证过的版本,源码,修改了大量Bug以适合实际项目应用 采用仿Visionpro拖拉流程形式,很适合学习使用,可修改参考用于项目。 注:软件能够正常编译运行,使用中遇到Bug自行摸索解决,主要是源码学习参考为主。

工业视觉项目的甲方总喜欢在验收前一天提出"能不能加个旋转检测"这种需求。去年用Halcon+C#折腾出的那套框架,最近被我改造成了VisionPro风格的拖拉拽工具,实测在口罩机外观检测项目里扛住了每天12小时连续运转。今天就带大家扒开这个框架的代码骨架,看看怎么用WPF把Halcon算子玩出花。

流程设计器的界面布局直接照抄了VisionPro的经典三栏结构(别问,问就是致敬)。左侧的算子库用TreeView实现层级分类,这部分XAML代码值得细品:

xml 复制代码
<TreeView ItemsSource="{Binding ToolCategories}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Tools}">
            <TextBlock Text="{Binding CategoryName}"/>
            <HierarchicalDataTemplate.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Tag="{Binding Script}">
                        <Image Source="{Binding Icon}"/>
                        <TextBlock Text="{Binding ToolName}" Margin="5"/>
                    </StackPanel>
                </DataTemplate>
            </HierarchicalDataTemplate.ItemTemplate>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

绑定ViewModel里的ToolCategories集合时,注意每个算子都带有脚本属性和图标路径,这为后续的拖拽操作埋下伏笔。当用户把Blob分析工具拖到画布时,实际是复制了预置的HDevelop脚本模板。

核心的拖拽逻辑藏在PreviewMouseMove事件里。判断鼠标移动距离超过系统阈值后,启动拖拽操作:

csharp 复制代码
private void OnToolItemPreviewMouseMove(object sender, MouseEventArgs e)
{
    if (e.LeftButton == MouseButtonState.Pressed && 
        _startPoint.HasValue &&
        (e.GetPosition(null) - _startPoint.Value).Length > 2.0)
    {
        var frameworkElement = sender as FrameworkElement;
        var data = new DataObject("ToolTemplate", frameworkElement.Tag.ToString());
        DragDrop.DoDragDrop(frameworkElement, data, DragDropEffects.Copy);
    }
}

这里有个坑:直接从Halcon导出的hdev脚本在C#环境里跑不起来,得手动替换掉那些反人类的变量命名。比如把AreaCenter转成area_center,还要处理坐标系转换问题------工业相机拍出来的图Y轴是反的!

参数配置窗体用了动态生成控件的大招。读取算子脚本的输入输出参数后,自动渲染对应控件:

csharp 复制代码
foreach (var param in script.Parameters)
{
    switch (param.Type)
    {
        case "int":
            var numBox = new NumericUpDown { Value = param.Value };
            _paramControls.Add(param.Name, numBox);
            break;
        case "string":
            var txtBox = new TextBox { Text = param.Value.ToString() };
            _paramControls.Add(param.Name, txtBox);
            break;
        // 其他类型处理...
    }
}

调试时发现Halcon的阈值参数用double类型传参会精度丢失,后来改成字符串传递再在脚本里转换才解决。这种坑文档里可不会写,都是项目现场踩出来的经验。

Halcon联合C#开发最新版实用框架 实际项目应用验证过的版本,源码,修改了大量Bug以适合实际项目应用 采用仿Visionpro拖拉流程形式,很适合学习使用,可修改参考用于项目。 注:软件能够正常编译运行,使用中遇到Bug自行摸索解决,主要是源码学习参考为主。

流程引擎最核心的部分是算子执行队列。用BackgroundWorker跑异步任务时,切记要加try-catch把Halcon异常转成C#异常:

csharp 复制代码
private void RunProcess(object sender, DoWorkEventArgs e)
{
    var process = e.Argument as Process;
    try
    {
        foreach (var tool in process.Tools)
        {
            _halconEngine.ExecuteScript(tool.Script);
            // 更新进度条需要回UI线程
            (sender as BackgroundWorker).ReportProgress(0, tool.ToolName);
        }
        e.Result = true;
    }
    catch (HOperatorException ex)
    {
        // 这里要解析Halcon错误代码
        e.Result = new ProcessError(ex.Message, ex.ErrorCode);
    }
}

重点注意HOperatorException的ErrorCode需要查Halcon文档,特别是2000系列错误基本都是图像没载入或区域为空这种低级错误。

图像显示控件继承自HalconDotNet.HWindowControl,但原始版本在多线程下会花屏。改进方案是加双缓冲:

csharp 复制代码
public class HSmartWindow : HWindowControl
{
    protected override void OnPaint(PaintEventArgs e)
    {
        if (_backBuffer != null)
        {
            lock (_backBuffer)
            {
                e.Graphics.DrawImageUnscaled(_backBuffer, 0, 0);
            }
        }
    }
    
    public void UpdateImage(HImage image)
    {
        using (var g = Graphics.FromImage(_backBuffer))
        {
            // 这里调用Halcon的dump_window方法生成Bitmap
            var bitmap = image.DumpWindow(this.HalconWindow);
            g.DrawImage(bitmap, 0, 0);
        }
        Invoke(new Action(Refresh));
    }
}

实测这个改写版本在i7处理器上能稳定跑60fps的1280x1024图像,比原生控件节省30%的CPU占用率。注意一定要加lock,否则多线程渲染时会内存溢出。

项目里还藏了些黑科技:比如用Roslyn动态编译用户自定义脚本,支持在界面里写C#代码直接操作Halcon对象;再比如用EF Core记录每次检测的算法参数和结果,方便后续追溯质量问题。

源码里最值得参考的是异常处理机制------毕竟工业现场的环境千奇百怪。我们给每个算子都加了try-catch包装,发生错误时自动保存现场图像和参数到错误目录,这对后期调试帮助巨大。

最后友情提示:别在UI线程里调用任何Halcon的耗时操作,否则拖动滚动条时画面会卡成PPT。正确做法是用Task.Run把图像处理丢到线程池,然后用Dispatcher.BeginInvoke更新界面。不过要注意Halcon对象不是线程安全的,跨线程使用记得加锁或者克隆对象。

相关推荐
a31582380615 天前
Android 大图显示策略优化显示(二)
android·java·开发语言·javascript·kotlin·glide·图片加载
青春勿语1 个月前
Lumen:重新定义 Android 图片加载体验
android·glide
灵感菇_1 个月前
Android图片加载框架 Glide全面解析
android·缓存·glide
Lei活在当下1 个月前
【项目踩坑实录】并发环境下,Glide缓存引起的图片加载异常
android·debug·glide
某空m1 个月前
【Android】Glide的缓存机制
android·缓存·glide
某空m1 个月前
【Android】Glide的使用
android·glide
胖虎15 个月前
Android入门到实战(六):Android主流图片加载框架
android·glide·android图片加载
webbin5 个月前
Glide GifDrawable加载流程
android·glide
安卓开发者5 个月前
Android Glide最佳实践:高效图片加载完全指南
android·glide