PCB 视觉检测上位机 · 界面设计与调试记录

鹿人检测
Visual Inspection Host v1.0.0

面向 PCB 缺陷检测场景的 C# / WPF 桌面上位机(.NET 8):左侧工具栏、中央检测画布、右侧参数面板、底部运行条。 本文所有截图摄于 2026 年 9 月 10 日真机运行,检测对象为 DeepPCB 公开数据集测试图;所用检测模型来自我自行训练的 PCB 缺陷检测成果,训练过程与评估结果见质检报告。

职责界面设计 / 调试验证
技术栈C# · WPF · .NET 8
检测类别6 类(DeepPCB)
运行环境Windows · 2880×1704
01

主界面

暗色界面服务于车间与实验室的长时间注视场景:画布区域占比最大,检测状态(NG 徽标、帧率、计数)集中在底部运行条,参数面板常驻右侧,不打断检测主流程。

主界面 · 连续运行
图 1 连续运行状态,9 个缺陷框保持锁定,底部运行条显示 21 FPS · 47.0 ms21:55:39
02

检测流程

从加载图像到导出报告共四步,均可在主窗口内完成。

加载图像
图 2 加载 DeepPCB 测试图,判定栏处于等待状态21:51:53
单帧检测
图 3 单帧推理完成:9 个 NG 框附中文类别与置信度21:52:00
检出类别数量置信度区间
针孔 pin-hole30.827 – 0.927
铜面缺陷 copper20.855 – 0.894
断路 open / 短路 short / 鼠咬 mousebite / 毛刺 spur各 10.815 – 0.923

检出阈值 conf 0.30 / IoU 0.45;全部框高于界面 NG 判定线 0.5,与判定结果一致。数据来自隐藏 CLI --detect 直出坐标,与 Python onnxruntime 基准逐框一致。

03

连续运行稳定性

调试期间出现过两类症状:背景图轮播切换、检测框聚在原点乱跳。修复后取相隔约 14 秒的两帧对照——检测框坐标逐像素一致,帧率稳定在 21–24 FPS。

帧累计 130
图 4 帧累计 130 · 21 FPS · 47.0 ms21:55:39
帧累计 305
图 5 帧累计 305 · 24 FPS · 42.0 ms21:55:48

两帧之间 9 个检测框坐标零漂移,背景图保持静止,NG 计数无跳变。运行日志中每帧坐标记录完全一致(针孔@425,19 · 断路@539,193 · 鼠咬@465,331 …),耗时区间 41–48 ms。

依据:logs/20260910.log 逐帧记录 · 图 4 / 图 5 底部状态栏
04

报告输出

工具栏 ⇩ 一键导出:CSV 坐标表与 640×480 标注合成图。合成图由离线渲染管线生成,不依赖界面可视化树,因此也是验证检测框对位的最可靠依据。

报告标注合成图
图 6 report_20260910_215203.jpg · 原图叠加检测框与中文标签640×480
05

本轮问题与修复

上述画面能够稳定呈现,前置条件是三个缺陷的定位与修复(2026-09-09 闭环)。

检测框 X 坐标压缩根因级 · 推理链路
灰度图被 WPF 解码为 Gray8(1 字节/像素),预处理按 BGR32(4 字节)读取,stride 相差四倍,图像横向压扁后进入输入张量,模型输出的 X 坐标缩至约 1/5。修复:缩放后经 FormatConvertedBitmap 强制转为 Bgra32 再 CopyPixels。修复后与 Python 基准 9 框逐一对齐。
检测框堆叠于原点WPF 布局
Canvas.Left / Top 附加属性设置在 DataTemplate 内的 Border 上,无法生效——Canvas 的直接子元素是自动生成的 ContentPresenter。修复:改由 ItemContainerStyle 对 ContentPresenter 设置附加属性。
NG 框不变红样式优先级
Border 本地属性 BorderBrush 优先级高于 Style 触发器,触发器永不生效。修复:移除本地属性,仅保留样式触发器。