在很多工业视觉项目里,软件经常会遇到这样的问题:
客户现场突然说:

“这个检测逻辑要改一下。”

或者:

“这个产品换型号了。”

然后工程师打开代码:

if(productType == 1)
{
    DetectA();
}
else if(productType == 2)
{
    DetectB();
}
else if(productType == 3)
{
    DetectC();
}
过一段时间代码就变成这样:
if(productType == 1)
{
    DetectA();
}
else if(productType == 2)
{
    DetectB();
}
else if(productType == 3)
{
    DetectC();
}
else if(productType == 4)
{
    DetectD();
}
else if(productType == 5)
{
    DetectE();
}

最后整个系统变成:

一坨无法维护的代码。

很多工业视觉系统越做越乱,其实不是算法问题。
而是:
架构设计问题。
今天这篇文章讲一个非常关键的设计:

插件式算法架构(Plugin Architecture)

这是很多成熟视觉软件都会用的结构。

一、工业视觉系统最大的变化来源

工业视觉软件和普通软件最大的不同是:
算法经常变化。
变化来源通常有:

产品型号变化
检测规则变化
模型更新
算法升级
客户定制需求

如果每次变化都要:

修改代码
重新编译
重新部署

那么系统维护成本会越来越高。
所以一个成熟的视觉系统应该做到:

算法可以独立更新。

而不是写死在系统里。

二、什么是插件式算法架构

插件式架构的核心思想是:

系统只提供框架
算法作为插件加载

系统架构变成:

Vision System
      │
      ▼
Algorithm Manager
      │
 ┌────┼─────┐
 ▼    ▼     ▼
PluginA PluginB PluginC

这样做有几个好处:
1 算法独立开发
不同算法可以单独开发。
例如:

DefectDetector.dll
DimensionMeasure.dll
OCRReader.dll

2 算法可以热替换
只需要替换 DLL:

plugins/
   DefectDetector.dll
   OCRReader.dll

系统重启即可生效。

3 项目更容易扩展

新增算法只需要:

写插件
放到插件目录

不用修改主程序。
三、插件式架构整体结构
一个典型视觉系统插件架构如下:

Vision System

├─ Core
│   ├─ PluginManager
│   ├─ TaskScheduler
│
├─ Plugins
│   ├─ YoloDetector.dll
│   ├─ HalconMeasure.dll
│   └─ OCRPlugin.dll
│
├─ Device
│   ├─ CameraService
│   └─ PlcService
│
└─ UI

运行流程:

相机采图
   ↓
任务调度
   ↓
插件算法执行
   ↓
结果输出

四、插件式算法接口设计

插件架构的核心是:
统一接口。
例如:

public interface IAlgorithmPlugin
{
    string Name { get; }

    void Initialize();

    AlgorithmResult Run(ImageData image);

    void Dispose();
}

每个算法插件只需要实现这个接口。
例如:
YOLO检测插件

public class YoloDetector : IAlgorithmPlugin
{
    public string Name => "YOLO Detector";

    public void Initialize()
    {
        LoadModel();
    }

    public AlgorithmResult Run(ImageData image)
    {
        return Detect(image);
    }

    public void Dispose()
    {
    }
}

Halcon检测插件

public class HalconMeasure : IAlgorithmPlugin
{
    public string Name => "Halcon Measure";

    public void Initialize()
    {
    }

    public AlgorithmResult Run(ImageData image)
    {
        return Measure(image);
    }

    public void Dispose()
    {
    }
}

这样:
系统并不知道插件内部实现。
只知道:

Run()

五、插件加载机制

在 C# 中,插件通常通过 反射加载。
示例代码:

var dlls = Directory.GetFiles("plugins", "*.dll");

foreach (var dll in dlls)
{
    var assembly = Assembly.LoadFrom(dll);

    var types = assembly.GetTypes()
        .Where(t => typeof(IAlgorithmPlugin).IsAssignableFrom(t));

    foreach (var type in types)
    {
        var plugin = (IAlgorithmPlugin)Activator.CreateInstance(type);
        plugin.Initialize();
        plugins.Add(plugin);
    }

}
这样系统启动时会自动加载:

plugins 文件夹

中的算法插件。

六、YOLO + Halcon 插件组合

在工业视觉系统中常见的组合是:

YOLO检测
   ↓
ROI提取
   ↓
Halcon精测

插件流程:

Image
  ↓
YoloDetectorPlugin
  ↓
ROIExtractorPlugin
  ↓
HalconMeasurePlugin
  ↓
Result

这样:
AI 负责:

粗检测

传统算法负责:

精测量

这也是很多成熟系统采用的方案。

七、插件架构的最大优势

如果系统设计成插件结构,你会发现几个巨大变化:
新增算法非常容易
只需要:
新增DLL

不影响主系统

主系统完全不需要修改。

支持客户定制

不同客户可以使用不同插件组合。
例如:
客户A

YOLO + Halcon

客户B

YOLO + OCR

客户C

传统视觉

八、工业视觉软件的一个重要原则

很多刚做视觉软件的人喜欢把所有算法写在一个项目里。
但经验告诉我:

算法应该永远是可替换的。

因为:

算法会变
产品会变
需求会变

但:

系统架构不应该变

所以一个好的工业视觉系统应该做到:

系统稳定,算法可插拔。

工业视觉 AI 项目做久了你会发现:
真正决定系统寿命的不是模型。
而是:

架构设计

插件式算法架构可以让你的系统:

更灵活
更稳定
更易维护

如果你的视觉软件已经开始变得难以维护。
那么可能是时候重新思考:
你的系统架构是否支持插件化?

我正在整理一套《工业视觉AI实战工具包》,包括源码、案例、学习路线。 如果你想第一时间获取资料包,请关注公众号–视觉小码农(需要halcon工具的可以公众号私我)

在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐