使用C#自行研发的基于Halcon的可视化抓边、抓圆控件(卡尺工具),注意是拖拽式控件,在Halcon控件上绘制的,可用于测量,使用起来简单、方便

在机器视觉项目中,抓边、抓圆是基础但非常重要的功能。传统Halcon开发需要反复编写测量代码,最近我们自己搓了个拖拽式卡尺控件,直接把算法工程师从重复劳动中解放出来——鼠标拖出个框就完成测量,还能实时看到算法效果。

这玩意儿最骚的操作是:按住Ctrl+鼠标左键在Halcon窗口画个矩形区域,松开鼠标瞬间自动完成边缘坐标提取。就像这样:

// 继承自Control的自定义控件核心事件
protected override void OnMouseDown(MouseEventArgs e)
{
    if ((Control.ModifierKeys & Keys.Control) != 0)
    {
        _isDrawing = true;
        _startPoint = ConvertToImageCoord(e.Location); // 转换到图像坐标系
    }
}

protected override void OnMouseMove(MouseEventArgs e)
{
    if (_isDrawing)
    {
        // 实时绘制红色半透明测量区域
        HOperatorSet.SetColor(_halconWindow, "red");
        HOperatorSet.SetDraw(_halconWindow, "margin");
        _currentRect = GetCurrentRect(e.Location);
        DisplayMeasurementArea(_currentRect); // 动态绘制边框
    }
}

这段代码实现了按住Ctrl键时触发绘制状态,实时转换坐标到Halcon图像坐标系。特别要注意的是鼠标位置到图像坐标的转换,很多测量误差都是这里没处理好。我们用了仿射变换矩阵来应对图像缩放的情况,避免控件坐标和实际像素坐标错位。

完成区域绘制后,自动触发测量逻辑。核心算法部分封装在独立类里,方便复用:

public class EdgeDetector
{
    public List<double> MeasureEdge(HImage image, HRectangle2 rect)
    {
        // 生成测量区域卡尺
        HMeasure measure = new HMeasure(rect.Height, rect.Width, 
            rect.Angle, rect.Row, rect.Column, 
            _measureWidth, _measureThreshold, "all", "all");
        
        // 执行抓边算法
        measure.MeasurePairs(image, 1, _smoothFactor, _edgeSelect, 
            out HTuple rowEdge, out HTuple columnEdge);
            
        // 坐标转换与筛选
        return FilterValidEdges(rowEdge, columnEdge);
    }
    
    // 过滤噪点的私有方法
    private List<double> FilterValidEdges(HTuple rows, HTuple cols)
    {
        // 实现边缘强度阈值筛选...
    }
}

这个类把Halcon的measure算子封装成了带默认参数的简洁方法,_measureWidth这些参数可以直接在控件属性面板里可视化调整。实测发现当测量宽度设为15像素、平滑系数0.8时,对金属反光件的边缘检测效果最佳。

控件还支持动态参数调试——改个阈值立刻看到新结果。比如要抓橡胶边缘,把极性从"positive"改成"negative",马上就能在界面看到边缘点的变化:

// 属性变更时自动刷新
public double Threshold
{
    get { return _threshold; }
    set { 
        _threshold = value;
        RefreshMeasurement(); // 触发重绘
    }
}

private void RefreshMeasurement()
{
    _currentEdges = _detector.MeasureEdge(_currentImage, _currentRect);
    DisplayEdges(_currentEdges); // 绿色高亮显示有效边缘点
}

实际使用中发现几个坑:Halcon的坐标系原点在左上角,而C#控件原点在左下角,坐标转换时要特别注意Y轴取反;测量区域旋转角度超过45度时,需要动态调整卡尺方向避免漏检。

最终效果是工程师在UI上点点拖拖就能完成测量方案配置,生成的参数配置文件可以直接给C++算法模块调用。这个月用这套工具完成了三个项目的视觉方案开发,效率比之前手写代码提升了至少三倍。下次可以聊聊怎么在这个基础上实现自动路径规划,让控件智能推荐测量区域位置。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐