• C+ Halcon 打造你的可视化机器视觉流程编辑器
  • 尊龙凯时黑不黑钱
新闻动态
热点资讯
推荐资讯

C+ Halcon 打造你的可视化机器视觉流程编辑器

发布日期:2026-02-06 11:55 点击次数:161

在工业视觉检测系统中,流程的灵活性和可配置性至关重要。传统硬编码方式难以应对多变的产线需求,而通过图形化流程编排,用户可以像搭积木一样组合图像处理步骤,极大提升了开发效率与系统适应性。

本文介绍一个基于 C# 与 MVTec HALCON 开发的轻量级可视化流程编辑器,它支持拖拽式节点构建、节点间连线逻辑定义,并集成了 HALCON 的核心图像处理能力,如模板创建、匹配、ROI 绘制等。

项目介绍

项目是一个面向机器视觉应用的流程编排工具,采用 WinForms 开发界面,底层调用 HALCON .NET 接口(HalconDotNet)实现图像算法功能。

通过主界面左侧的工具栏选择不同功能模块(如"加载图像"、"绘制 ROI"、"创建模板"、"模板匹配"等),将其拖入中央的流程编辑区域,形成节点;再通过"连线"功能建立节点间的执行顺序与数据流向,最终实现一键运行整个视觉流程。

项目功能

1、模块化工具面板

提供图像加载、ROI 绘制、模板创建、模板匹配等常用视觉操作入口。

2、拖拽式节点生成

用户可将工具项拖入编辑区,自动生成带名称的流程节点(FlowNode)。

3、节点自由移动

支持在编辑区域内拖动节点调整布局,边界限制防止移出可视区域。

4、可视化连线机制

通过"连线"模式点击两个节点,自动绘制带箭头的连接线,表示数据流向。

5、流程执行引擎

点击"单次执行"即可按连线顺序依次调用各节点的处理逻辑。

6、HALCON 深度集成

每个节点对应具体的 HALCON 操作,如读图、绘制矩形、创建形状模型、执行匹配等。

7、结果可视化

匹配结果以红色轮廓叠加显示,并标注坐标与十字准星,便于调试。

项目特点

低耦合设计:流程节点(FlowNode)与具体算法逻辑解耦,便于扩展新功能模块。

所见即所得:流程结构与执行逻辑一致,用户能直观理解数据流动路径。

交互友好:拖拽、点击、连线等操作符合常规图形编辑习惯,学习成本低。

轻量高效:未依赖复杂框架,基于原生 WinForms 和 GDI+ 绘制连线,运行流畅。

面向实际场景:覆盖从图像输入、预处理、模板训练到匹配输出的完整闭环。

项目技术

HalconDotNet:调用 HALCON 的 .NET 接口,实现图像读取、ROI 操作、形状模型创建与匹配等高级视觉算法。

GDI+ 绘图:使用Graphics.DrawLines绘制带圆角和箭头的连接线,通过重写Paint事件确保连线随窗口刷新。

事件委托封装:通过MouseEventHelper.RegistryMouseEvent统一注册节点的鼠标事件,提升代码复用性。

状态管理:引入DrawState枚举区分"普通"与"连线"模式,控制用户交互行为。

异步执行:流程运行置于Task.Run中,避免 UI 线程阻塞。

项目源码

主窗体核心逻辑如下(已省略部分辅助方法):

using System.Drawing.Drawing2D;

using Vision.Flow.Proj.VControl;

using Vision.Flow.Proj.VHelper;

namespaceVision.Flow.Proj

{

publicpartialclassForm1 : Form

{

private Label lbl;

privatebool isMoving;

private Point startPoint;

private DrawState drawState = DrawState.Noramal;

private FlowNode node1;

privateint nodeNo = 0;

private FlowNode node2;

// ... 初始化及菜单控制代码 ...

private void Pl_FlowProcess_DragDrop(object sender, DragEventArgs e)

{

var container = sender as Control;

var flowNode = new FlowNode;

MouseEventHelper.RegistryMouseEvent(flowNode, NodeMouseDown, MouseEventName.MouseDown);

MouseEventHelper.RegistryMouseEvent(flowNode, NodeMouseMove, MouseEventName.MouseMove);

MouseEventHelper.RegistryMouseEvent(flowNode, NodeMouseUP, MouseEventName.MouseUp);

MouseEventHelper.RegistryMouseEvent(flowNode, NodeClick, MouseEventName.MouseDown);

flowNode.NodeName = lbl.Text;

flowNode.Location = container.PointToClient(new Point(e.X, e.Y));

container.Controls.Add(flowNode);

}

private void NodeClick(object sender, MouseEventArgs e)

{

if (e.Button == MouseButtons.Left && drawState == DrawState.DrawLine)

{

var control = sender as Control;

if (nodeNo == 0)

{

node1 = (FlowNode)control.Parent;

nodeNo = 1;

}

elseif (nodeNo == 1)

{

node2 = (FlowNode)control.Parent;

if (!node1.Equals(node2))

{

node1.NextNode = node2.NodeID;

node2.PreNode = node1.NodeID;

nodeNo = 0;

DrawPointToPointLine(node1, node2);

drawState = DrawState.Noramal;

}

}

}

}

private void DrawJoinLine(Point p1, Point p2, LineForward forward)

{

Graphics g = Pl_FlowProcess.CreateGraphics;

g.SmoothingMode = SmoothingMode.HighQuality;

Pen p = new Pen(Color.DarkRed, 5) { DashStyle = DashStyle.Solid, StartCap = LineCap.Round, EndCap = LineCap.ArrowAnchor };

Point inflectPoint1, inflectPoint2;

if (forward == LineForward.L_R

------

QQ咨询

QQ: