前言
工业视觉领域,开发一套稳定、灵活且易于维护的平台从来不是一件容易的事。不同品牌的相机、多样的图像算法库、复杂的场景配置逻辑,常常让开发者陷入"适配地狱"。而更头疼的是,每次更换硬件或算法框架,几乎都要重写大半代码。有没有一种方式,能把这些差异封装起来,让上层逻辑专注业务本身?
本文推荐一个用插件化架构和清晰的抽象接口,为工业视觉应用提供一个真正可扩展的基础平台。
项目介绍
一个基于 .NET 和 WPF 开发的工业视觉开发平台,核心目标是解耦相机驱动与视觉算法框架。通过定义统一的 ICamera 和 IVisionFrame 接口,平台支持动态加载不同厂商的 SDK(如 uEye、Hik、Pylon 等)以及主流视觉库(如 HALCON、VisionPro)。主窗口(MainWindow)作为调度中心,负责管理场景、切换环境、调用执行流程,而所有具体实现则通过反射从独立 DLL 中加载,真正做到"即插即用"。
项目功能
1、多相机支持
自动扫描指定目录下的相机 SDK 插件,支持物理相机与虚拟图像文件夹(用于测试)。
2、多视觉框架切换
可在 HALCON、VisionPro 等之间动态切换,无需重启应用。
3、场景管理
每个检测任务封装为一个"Scene",包含相机绑定、算法流程、参数配置,支持创建、修改、删除和恢复。
4、标定与相机配置
提供独立窗口进行相机参数调整(曝光、增益、触发模式)和手眼标定操作。
5、运行与调试
选中场景后一键执行,结果实时反馈,错误信息弹窗提示,便于现场调试。
项目特点
最突出的特点是"插件化"和"解耦"。相机和视觉算法不再是硬编码依赖,而是通过工厂类(CameraFactory、VisionFrameFactory)在运行时动态加载。
这意味着,当需要接入一个新的相机品牌,只需按约定编写一个实现 ICamera 的 DLL 放入对应目录,平台就能自动识别。同样,算法模块也可独立升级,不影响主程序。
另外,虚拟相机功能极大提升了开发效率——即使没有真实设备,也能用本地图片模拟采集流程。
项目技术
平台采用 C# + WPF UI,利用 MVVM 模式分离界面与逻辑。
核心技术点包括:
反射与插件机制:通过 Assembly.LoadFrom 动态加载 DLL,按类型名实例化对象。
接口抽象:ICamera 定义了 Connect、Grab、StopGrab 等通用方法,屏蔽底层 SDK 差异。
单例场景管理:SceneManager 以字典形式维护所有 Scene 实例,支持持久化恢复。
资源安全释放:在窗口关闭时主动 StopGrab、DisConnect 并 Dispose 相机对象,防止内存泄漏。
配置文件管理:相机参数和标定数据以 JSON 形式存储,便于版本控制和迁移。
项目代码
相机工厂静态类
/// <summary>
/// 获取所有的相机
/// </summary>
/// <returns>相机信息列表</returns>
public static List<DeviceInfo> GetAllCameras()
{
if (!CameraAssemblys.ContainsKey(DefaultCameraSdkType))
{
thrownew ArgumentException("ECameraSdkType invalid");
}
return CreateInstance(DefaultCameraSdkType).GetDeviceList();
}
/// <summary>
/// 添加相机
/// </summary>
/// <param name="cameraSerial">相机序列号</param>
/// <exception cref="InvalidOperationException">
/// 打开相机失败
/// </exception>
public static void AddCamera(string cameraSerial)
{
if (!CameraAssemblys.ContainsKey(DefaultCameraSdkType))
{
thrownew ArgumentException("ECameraSdkType invalid");
}
if (string.IsNullOrEmpty(cameraSerial))
{
thrownew ArgumentException("cameraSerial cannot be null");
}
if (Cameras.ContainsKey(cameraSerial))
{
return;
}
ICamera camera = CreateInstance(DefaultCameraSdkType);
if (camera.Connect(cameraSerial))
{
Cameras.Add(cameraSerial, camera);
SetToDefaultConfiguration(camera);
return;
}
else
{
thrownew InvalidOperationException($"open camera[{cameraSerial}] err!");
}
}
/// <summary>
/// 添加所有的相机
/// </summary>
/// <returns>执行结果</returns>
public static void AddAllCamera()
{
if (!CameraAssemblys.ContainsKey(DefaultCameraSdkType))
{
thrownew ArgumentException("ECameraSdkType invalid");
}
try
{
var devices = GetAllCameras();
foreach (var item in devices)
{
AddCamera(item.SerialNumber);
}
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 移除相机
/// </summary>
/// <param name="cameraSerial">相机序列号</param>
public static void RemoveCamera(string cameraSerial)
{
if (Cameras.ContainsKey(cameraSerial))
{
Cameras[cameraSerial].StopGrab();
Cameras[cameraSerial].DisConnect();
Cameras[cameraSerial].Dispose();
Cameras.Remove(cameraSerial);
}
}
/// <summary>
/// 移除所有的相机
/// </summary>
public static void RemoveAllCameras()
{
foreach (var item in Cameras.Values)
{
item.StopGrab();
item.DisConnect();
item.Dispose();
}
Cameras.Clear();
}
项目效果
可通过下拉框快速切换相机类型和视觉框架。系统会自动加载预设的测试图像目录(如刹车片、眼镜等),直接用于算法验证。创建新场景后,可配置图像源、绑定算法步骤、设置触发逻辑,保存后即可在列表中看到。
系统主页

相机窗口

标定窗口

场景配置

项目源码
项目结构清晰,所有相机 SDK 封装为独立类库,命名规范严格,二次开发极为方便,不管是新增设备支持,还是替换算法引擎,都无需改动主程序。
为了防止丢失,可以在评论区留言关键字「工业相机」,即可获取完整源码地址。
总结
项目没有炫酷的界面或复杂的 AI 功能,而是回归工程本质:解决兼容性问题、提升开发效率、保障系统稳定性。它像一个"视觉中间件",把碎片化的工业硬件和软件整合成统一的服务。对于需要长期维护、频繁迭代的视觉项目来说,这种架构带来的灵活性和可维护性,远比短期开发速度更重要。如果大家正被多品牌设备困扰,不妨看看这个平台的设计思路,或许能为大家打开一扇新的门作为参考。
关键词
#工业视觉、#插件化架构、#WPF、C#、#相机抽象、#HALCON、#VisionPro、#动态加载、#场景管理、#MVVM、#标定、#工业相机、#算法库
作者:小码编匠
.NET 网络协议组件,支持 Web 服务、RTSP 流媒体与 IoT 设备通信
WPF 轻量级工业边缘网关:支持 PLC 数据采集、条件触发与 HTTP 上报
工业软件也能颜值在线?这个 WPF + DevExpress 工控框架太实用了
.NET 8 + Avalonia 实现跨平台的视频会议(Windows、Linux、信创)
觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力

