当前位置: 首页 > news >正文

WPF 工业视觉检测系统:双工位(面阵 + 线扫)独立运行架构

前言

智能制造与工业自动化的浪潮下,机器视觉已成为产线质量控制的核心技术。然而,许多中小型视觉系统仍面临架构混乱、扩展困难、维护成本高等问题——相机、PLC、算法逻辑耦合严重,UI 卡顿频发,日志难以追踪,权限管理缺失。

本文推荐一个基于 WPF + MVVM 架构,结合 海康 VisionMaster 视觉引擎 与 度申工业相机 SDK,设计并实现了一套高内聚、低耦合的工业视觉检测系统。

项目介绍

系统不仅支持 面阵与线扫双工位独立运行,还实现了 模块化硬件抽象、三级权限控制、智能图像存储、跨模块事件通信 等关键能力。更重要的是,我们在真实产线环境中验证了其稳定性与可维护性,并总结了多个典型开发陷阱与解决方案。

项目技术

  • 语言:C#

  • 框架:.NET Framework 4.8

  • UI 框架:WPF(MVVM 架构)

  • 视觉引擎:海康 VisionMaster

  • 相机 SDK:度申 SDK

  • PLC 通讯协议:欧姆龙 FINS/TCP

开发环境

  • IDE:Visual Studio 2019 / 2022

  • .NET 版本:.NET Framework 4.8

  • 视觉 SDK:海康 VisionMaster SDK 4.x

  • 相机 SDK:度申相机 SDK

项目功能

双工位独立运行:工位1(面阵相机) + 工位2(线扫相机)

图案匹配检测:识别产品图案,输出旋转角度

PLC 集成:通过欧姆龙 FINS/TCP 输出角度与 OK/NG 结果

三级权限管理:操作员 / 工程师 / 管理员

独立数据统计:各工位 OK/NG 计数,支持 CSV 导出

智能图片存储:最近 N 张循环缓存,NG 图像永久保存

模块化日志:按Camera/PLC/Vision等模块分文件记录

项目架构

VisionOTA/ ├── src/ │ ├── VisionOTA.Main/ # WPF 主程序 │ │ ├── Views/ # 视图层 │ │ ├── ViewModels/ # 视图模型层 │ │ ├── Controls/ # 自定义控件 │ │ ├── Converters/ # 值转换器 │ │ └── Themes/ # 主题样式 │ │ │ ├── VisionOTA.Core/ # 核心业务逻辑层 │ │ ├── Interfaces/ # 服务接口 │ │ ├── Models/ # 业务模型 │ │ └── Services/ # 业务服务实现 │ │ │ ├── VisionOTA.Hardware/ # 硬件通讯抽象层 │ │ ├── Camera/ # 相机控制模块 │ │ ├── Plc/ # PLC 通讯模块 │ │ └── Vision/ # 视觉处理模块 │ │ │ ├── VisionOTA.Infrastructure/ # 基础设施层 │ │ ├── Config/ # 配置管理 │ │ ├── Logging/ # 日志系统 │ │ ├── Permission/ # 权限管理 │ │ └── Storage/ # 存储服务 │ │ │ └── VisionOTA.Common/ # 公共组件库 │ ├── Constants/ # 常量定义 │ ├── Events/ # 事件聚合器 │ ├── Extensions/ # 扩展方法 │ └── Mvvm/ # MVVM 基础类 │ └── Config/ # 配置文件目录

核心文件说明

1、VisionOTA.Main(主程序)

Views(视图)

文件

说明

MainWindow.xaml

主界面,包含双工位显示、统计面板、状态栏

CameraSettingsWindow.xaml

相机设置窗口,支持双工位配置与实时预览

PlcSettingsWindow.xaml

PLC 设置窗口,支持地址配置与连接测试

VisionMasterSettingsWindow.xaml

算法设置窗口,用于加载/调试 VisionMaster 方案

LogWindow.xaml

日志查看窗口,支持按模块筛选

LoginWindow.xaml

用户登录界面

UserManagementWindow.xaml

用户管理界面

ViewModels(视图模型)

文件

说明

MainViewModel.cs

主界面逻辑,协调工位状态与检测流程

StationViewModel.cs

工位通用 ViewModel,封装相机控制与统计逻辑

CameraSettingsViewModel.cs

相机设置业务逻辑

PlcSettingsViewModel.cs

PLC 设置逻辑

PlcAddressViewModel.cs

PLC 地址项 ViewModel,支持动态绑定

LogViewModel.cs

日志查看逻辑,支持模块筛选

LoginViewModel.cs

登录验证逻辑

Controls(自定义控件)

文件

说明

ZoomableImageControl.xaml

可缩放图像控件,支持:
• 鼠标滚轮缩放
• 拖拽平移
• 十字准线定位

2、VisionOTA.Core(核心业务)

文件

说明

InspectionService.cs

检测服务,协调相机 → 视觉 → PLC 完成完整检测流程

StatisticsService.cs

统计服务,独立维护各工位 OK/NG 计数

ImageStorageService.cs

图片存储服务,支持循环缓存 + NG 图像单独保存

3、VisionOTA.Hardware(硬件层)

Camera(相机)

文件

说明

ICamera.cs

相机统一接口

DushenCameraBase.cs

度申相机基类

DushenAreaCamera.cs

面阵相机实现(工位1)

DushenLineCamera.cs

线扫相机实现(工位2)

CameraFactory.cs

相机工厂,根据配置创建对应实例

Plc(PLC 通讯)

文件

说明

IPlcCommunication.cs

PLC 通讯接口

OmronFinsCommunication.cs

欧姆龙 FINS/TCP 协议实现

MockPlc.cs

模拟 PLC,支持离线调试

Vision(视觉处理)

文件

说明

IVisionProcessor.cs

视觉处理器接口

VisionMasterProcessor.cs

VisionMaster 实现,含方案管理器单例

MockVisionProcessor.cs

模拟视觉处理器,用于无设备测试

4、VisionOTA.Infrastructure(基础设施)

Config(配置)

文件

说明

ConfigManager.cs

统一配置加载/保存入口

CameraConfig.cs

相机参数模型(曝光、增益、触发模式等)

PlcConfig.cs

PLC 地址配置模型

VisionConfig.cs

视觉算法配置(方案路径、流程名)

Logging(日志)

文件

说明

FileLogger.cs

按模块分文件的日志写入器

LogExtensions.cs

日志快捷调用扩展

Permission(权限)

文件

说明

PermissionService.cs

三级权限控制(操作员/工程师/管理员)

PermissionLevel.cs

权限级别枚举

5、VisionOTA.Common(公共组件)

Mvvm

文件

说明

ViewModelBase.cs

实现INotifyPropertyChanged的基类

RelayCommand.cs

标准命令实现

CommandFactory.cs

简化命令创建

ObservableObject.cs

可观察对象基类

Events

文件

说明

EventAggregator.cs

跨模块事件通信中枢

配置文件

Config/ ├── CameraConfig.json # 相机参数(曝光、增益、触发模式) ├── PlcConfig.json # PLC 地址映射(支持界面编辑) ├── VisionConfig.json # VisionMaster 方案路径与流程配置 ├── SystemConfig.json # 系统级参数(如缓存数量、日志等级) └── Users.json # 用户账户信息(加密存储)

开发中遇到的问题及解决方案

1、VisionMaster 加载方案时 UI 卡住

问题:点击"加载方案"后界面冻结,状态栏持续显示"正在加载方案..."

原因

  • VmSolution.Load()是耗时操作,在 UI 线程执行

  • SetRotationAngleFromPlc()中使用.Result同步等待异步操作,阻塞 Dispatcher

解决方案

// 1. 后台线程加载方案 await Task.Run(() => { VmSolution.Load(solutionPath); }); // 2. 改为纯异步方法,避免 .Result private async Task SetRotationAngleFromPlcAsync() { await Task.Run(async () => { var connected = await plc.ConnectAsync(); varvalue = await plc.ReadFloatAsync(address); }); } // 3. 后台执行,不阻塞 UI _ = SetRotationAngleFromPlcAsync();

2、VisionMaster 状态灯不亮

问题:方案加载成功,但主界面算法状态灯未变绿

原因:未发布连接状态变更事件

解决方案

EventAggregator.Instance.Publish(new ConnectionChangedEvent { DeviceType = "Vision", DeviceName = "VisionMaster", IsConnected = true });

3、切换方案时卡住

问题:已加载方案后重新选择新方案,界面卡死

原因:使用局部变量_isSolutionLoaded判断状态,而非全局单例

解决方案

if (VmSolution.Instance != null) { VmSolution.Instance.CloseSolution(); }

4、相机设置界面按钮过多

问题:每个工位 7 个按钮,界面拥挤

解决方案

  • 合并互斥操作:连接/断开 → 1 个切换按钮;采集/停止 → 1 个切换按钮

  • 动态按钮文本:

public string ConnectionButtonText => IsConnected ? "断开" : "连接";

分组布局:连接控制 | 采集控制 | 工具按钮

5、代码重复问题

问题:CameraSettingsViewModelMainViewModel中工位逻辑大量重复

解决方案

  • 提取StationViewModel封装通用工位逻辑(相机控制、统计)

  • 提取PlcAddressViewModel封装 PLC 地址项

  • 使用组合代替继承,减少重复代码约 50%

6、日志混乱

问题:所有模块日志混写入同一文件,难以排查

解决方案:按模块 + 日期分文件存储

logs/2024-01-15/ ├── All.log # 全量日志 ├── Camera.log # 相机模块 ├── PLC.log # PLC 模块 ├── Vision.log # 视觉模块
public void Log(LogLevel level, string message, string category) { var module = GetModuleFromCategory(category); WriteToFile($"logs/{date}/All.log", message); WriteToFile($"logs/{date}/{module}.log", message); }

项目源码

GitHub:https://github.com/userqz1/Vision_OTA

总结

系统设计原则:高内聚、低耦合、可测试、可维护。

目标:打造一套稳定、灵活、易扩展的工业视觉检测平台。

http://www.jsqmd.com/news/809738/

相关文章:

  • 2026年重磅解读:全面解析7大固德牌气动隔膜泵供应商选购攻略 预算规划 - 资讯焦点
  • 大语言模型在信息抽取任务中的评测与应用实践
  • 2026湖州婚纱礼服馆排行|热门门店全解析 - charlieruizvin
  • 2026年山东广告投流与全场景营销服务深度指南:企业精准获客的破局之道 - 年度推荐企业名录
  • 为什么92%的博士生用错Perplexity?——被忽略的学术可信度校验链与证据溯源四步法
  • 【Oracle数据库指南】第31篇:Oracle重做日志文件管理操作详解
  • 2026年玻璃棉卷毡优质厂家推荐指南 廊坊依索维尔保温材料有限公司优选 玻璃棉卷毡 玻璃棉 - 奔跑123
  • 3个场景告诉你:为什么Windows电脑需要APK安装器
  • 同星多工位自动化刷写台架,助力汽车电子高效量产与质量追溯
  • BG3ModManager终极配置指南:专业级模组管理与游戏兼容性解决方案
  • 桥梁动应变监测制造商怎么选?金诚测试仪器厂实测表现优异 - 品牌推荐大师1
  • 如何快速清理重复图片:AntiDupl.NET的完整使用指南
  • 5分钟免费掌握:通达信缠论可视化分析插件终极指南
  • 2026年论文AI率过高遭导师打回?高效方法帮你降AI率到10%以下! - 降AI实验室
  • QNAP NAS空间告急?试试这个开源神器fdupes,比官方工具更强大的重复文件清理方案
  • 京东商品库存监控终极指南:使用 jd-happy 实现24小时自动下单
  • 深度解析:libiec61850开源库如何解决电力系统通信的三大核心挑战
  • 28倍加速!北大新作Spark3R:无需训练,加速前馈3D重建模型,兼容VGGT、π3 、DepthAnythingV3!
  • 从“无法调用”到“秒级响应”:Gemini Android SDK级设置还原术(附ADB命令+截图验证流程)
  • 【Oracle数据库指南】第30篇:Oracle重做日志规划与配置详解
  • 界面原型设计工具--墨刀
  • 2026宜宾装修公司怎么选?本地人实测这几家,别墅大宅、全案整装都有谱 - 深度智识库
  • 广西江马新能源科技:南宁共享扫码代步车哪家好 - LYL仔仔
  • AI视频生产力革命(2024企业级集成实录):ChatGPT+Sora 2协同架构设计与低代码部署方案
  • 在Claude Code中配置Taotoken作为备用API解决封号与Token不足问题
  • 襄阳CMA甲醛检测治理公司及洁净室公共卫生检测报告排行榜(2026版) - 张诗林资源库
  • 三亚CMA甲醛检测治理及公共卫生检测报告排行榜(2026版) - 张诗林资源库
  • 从爱因斯坦求和到代码实践:解锁numpy.einsum()的高维张量运算
  • ClawSuite:模块化网络安全工具集的设计原理与实战应用
  • 软件开发创新第11周作业