news 2026/5/13 16:08:11

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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

总结

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/13 16:07:11

HoRain云--Lua table核心机制与高效实践

🎬 HoRain云小助手:个人主页 🔥 个人专栏: 《Linux 系列教程》《c语言教程》 ⛺️生活的理想,就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!…

作者头像 李华
网站建设 2026/5/13 16:07:10

HoRain云--Lua元表:解锁高级编程技巧

🎬 HoRain云小助手:个人主页 🔥 个人专栏: 《Linux 系列教程》《c语言教程》 ⛺️生活的理想,就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!…

作者头像 李华
网站建设 2026/5/13 16:02:34

Taotoken的稳定性与低延迟在实时对话应用中的体感

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken的稳定性与低延迟在实时对话应用中的体感 1. 引言 对于开发实时AI对话应用的团队而言,服务的响应速度和连接稳…

作者头像 李华
网站建设 2026/5/13 16:01:07

资本意志下的工程师生存指南:从高通裁员看技术与商业的博弈

1. 从一封信到四千七百张解雇单:当资本意志敲响工程师的门在科技行业,尤其是半导体这个以创新为生命线的领域,我们常常沉浸于晶体管密度、架构革新和制程竞赛的技术叙事中。然而,2015年夏天,一封来自华尔街的公开信&am…

作者头像 李华
网站建设 2026/5/13 16:01:07

Android原生AI智能体平台Zero:Rust核心与多通道集成的工程实践

1. 项目概述:一个运行在Android上的原生AI智能体平台如果你和我一样,对手机上那些“大模型助手”感到有些审美疲劳——它们要么是套壳的Web应用,响应慢、功能受限,要么就是纯粹的聊天玩具,没法真正帮你处理点“脏活累累…

作者头像 李华