跳到主要内容

Vision Studio 完全教程

本教程采用实例驱动的方式,每一步都配有参数说明、代码示例、运行结果示意图和常见错误分析。适合从零开始学习机器视觉的工程师,也适合有经验者快速查阅。


第一章:视觉系统入门

1.1 什么是机器视觉?

机器视觉 (Machine Vision) 是让工业相机"看懂"生产场景的技术。与人类视觉相比:

对比项人类视觉机器视觉
速度约 200ms 反应时间微秒到毫秒级
精度约 0.1mm (人眼分辨率)亚微米级 (< 0.001mm)
疲劳会疲劳,注意力下降7×24 小时稳定
量化定性判断(好/坏)定量测量(精确到 0.01mm)
重复性不同人不同结果同一程序结果一致
适应环境适应光照变化需稳定光照

1.2 工业视觉典型应用场景

场景一:外观缺陷检测
┌─────────────────────────────────────────────┐
│ 传送带 → 产品到位传感器 → 相机拍照 │
│ → 深度学习模型检测缺陷 │
│ → 有缺陷 → 剔除器动作 │
│ → 无缺陷 → 流入下一工序 │
└─────────────────────────────────────────────┘

场景二:定位引导机器人抓取
┌─────────────────────────────────────────────┐
│ 料盘 → 相机拍照 │
│ → 模板匹配定位工件 │
│ → 计算 X/Y/角度偏移 │
│ → 发送坐标给机器人 │
│ → 机器人准确抓取 │
└─────────────────────────────────────────────┘

场景三:条码/二维码读取
┌─────────────────────────────────────────────┐
│ 包裹 → 触发相机 │
│ → 图像增强 → 解码条码/二维码 │
│ → 查询数据库 → 决定分拣通道 │
│ → 分拣机构动作 │
└─────────────────────────────────────────────┘

场景四:尺寸测量分选
┌─────────────────────────────────────────────┐
│ 零件 → 背光照明 → 相机拍照 │
│ → 边缘检测 → 拟合圆和直线 │
│ → 计算孔径/间距/角度 │
│ → 判断是否在公差范围内 │
│ → OK/NG 分选 │
└─────────────────────────────────────────────┘

1.3 Vision Studio 架构概览

Vision Studio 是 Darra RT IDE 内置的机器视觉开发环境,采用四层架构:

┌──────────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ 外观缺陷检测 │ │ 定位引导抓取 │ │ 条码识别 / OCR │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
├─────────┴────────────────┴────────────────────┴─────────────┤
│ 推理层 (Inference) │
│ ┌──────────────────────────┐ ┌──────────────────────────┐ │
│ │ ONNX Runtime (GPU/CUDA) │ │ OpenCV DNN (CPU 回退) │ │
│ │ • YOLOv8/v9/v10/v11 │ │ • 轻量模型 │ │
│ │ • ResNet/EfficientNet │ │ • 开发调试阶段 │ │
│ │ • 自定义 ONNX 模型 │ │ • 低算力边缘设备 │ │
│ └──────────────────────────┘ └──────────────────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ 采集层 (Acquisition) │
│ ┌────────────┐ ┌────────────┐ ┌────────────────────────┐ │
│ │ USB3 Vision│ │ GigE Vision│ │ GenTL (Camera Link/ │ │
│ │ (UVC) │ │ (1000BaseT)│ │ CoaXPress) │ │
│ └────────────┘ └────────────┘ └────────────────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ 硬件层 (Hardware) │
│ USB 3.0 / GigE / Camera Link / CoaXPress │
└──────────────────────────────────────────────────────────────┘

各层职责

职责典型组件
硬件层物理连接与数据传输相机、镜头、光源、线缆、采集卡
采集层相机驱动与图像获取USB 驱动、GigE Vision 协议、GenTL Producer
推理层模型推理与图像处理ONNX Runtime、OpenCV DNN
应用层业务逻辑与 PLC 集成卡片图流程、Vision SCL 程序、PLC 变量映射

1.4 硬件要求

相机选型指南

应用场景推荐相机类型分辨率帧率传感器
外观缺陷检测面阵相机500万~2000万像素30~75 fpsCMOS 全局快门
定位引导面阵相机130万~500万像素30~60 fpsCMOS 全局快门
条码读取线阵或面阵200万~500万像素60~200 fpsCMOS 滚动/全局
尺寸测量面阵相机 + 远心镜头500万~1200万像素15~30 fpsCCD/CMOS 全局
高速检测高速相机130万~400万像素200~1000 fpsCMOS 全局
OCR 字符识别高分辨率面阵1200万像素以上15~30 fpsCMOS 全局

镜头选型指南

镜头类型特点适用场景
定焦镜头焦距固定,成像质量好通用场景
变焦镜头焦距可调,灵活性高多工位切换
远心镜头无透视误差,测量精度高尺寸测量
微距镜头高放大倍率小零件检测
线扫镜头适配线阵相机卷材检测

镜头焦距计算公式

焦距 f = (工作距离 × 传感器宽度) / 视野宽度

示例:工作距离 300mm,传感器宽 6.4mm(1/2"),视野宽 100mm
f = (300 × 6.4) / 100 = 19.2mm → 选用 20mm 定焦镜头

光源选型指南

光源类型特点适用场景
环形光源均匀环形照明,消除阴影字符识别、通用检测
背光源从背面照明,轮廓清晰尺寸测量、边缘检测
同轴光源垂直照明,消除反光镜面表面检测
条形光源角度可调,突出缺陷划痕检测、表面纹理
穹顶光源漫射均匀照明球形/反光表面
暗场光源低角度照明,突出凹凸划痕、压印检测

工控机推荐配置

配置等级CPU内存GPU存储适用场景
入门级i5-1250016GB无(CPU 推理)256GB SSD单相机简单检测
标准级i7-1270032GBRTX 3060 12GB512GB SSD双相机标准检测
高性能i9-1390064GBRTX 4090 24GB1TB NVMe四相机深度学习
边缘级NUC 13 Pro16GBIntel Iris Xe256GB SSD边缘设备部署

1.5 软件流程概述

一个完整的视觉项目通常经历以下阶段:

阶段一:环境搭建
├─ 安装 Darra RT IDE
├─ 连接相机硬件
├─ 安装相机驱动(GenICam / USB)
└─ 配置 RuntimeResourcePolicy

阶段二:视觉编程
├─ 添加相机并配置参数
├─ 创建视觉程序(卡片图或 Vision SCL)
├─ 配置图像预处理流程
├─ 导入并配置模型
├─ 配置结果输出与 PLC 变量映射
└─ 配置触发条件与事件处理

阶段三:调试与验证
├─ 单步运行验证每个环节
├─ 调整参数优化效果
├─ 批量测试验证稳定性
└─ 模型验证与版本管理

阶段四:部署运行
├─ 部署模型到运行时
├─ 配置 RuntimeResourcePolicy
├─ 启动视觉服务
└─ 监控运行状态

1.6 常见误区

误区正确理解
分辨率越高越好分辨率越高,数据量越大,推理越慢。够用就好
深度学习万能简单场景用传统方法(Blob/模板匹配)更快更稳
相机随便装安装位置、角度、高度直接影响检测效果
光源随便选光源是视觉系统最重要的部分,占项目成败的 70%
参数一次调好参数需要根据实际产线环境反复调试

第二章:相机配置

2.1 相机类型

Vision Studio 支持三种相机接口:

USB3 Vision (UVC)

即插即用,适合开发调试和小型系统。

特点

  • 带宽:USB 3.0 约 350 MB/s,USB 2.0 约 40 MB/s
  • 线缆长度:最长 5 米(USB 3.0),可加延长器到 20 米
  • 成本:低
  • 适用:单相机、近距离、开发调试

支持设备

  • UVC 兼容相机(大多数 USB 工业相机)
  • 海康机器人 USB 系列
  • 大恒图像 USB 系列
  • 普通 USB 摄像头(开发调试用)

GigE Vision

工业标准,适合远距离、多相机系统。

特点

  • 带宽:1000BASE-T 约 125 MB/s
  • 线缆长度:最长 100 米(CAT6)
  • 成本:中等
  • 适用:多相机、远距离、产线部署

支持设备

  • Basler GigE 系列
  • 海康机器人 GigE 系列
  • 大恒图像 GigE 系列
  • 符合 GenICam 标准的 GigE 相机

GenTL 采集卡

高性能,适合高速/高分辨率相机。

特点

  • 带宽:Camera Link 约 850 MB/s,CoaXPress 约 1.25 GB/s
  • 线缆长度:Camera Link 最长 10 米,CoaXPress 最长 40 米
  • 成本:高
  • 适用:高速检测、高分辨率、工业相机

支持设备

  • Matrox 采集卡
  • Euresys 采集卡
  • Silicon Software 采集卡
  • 厂商 GenTL Producer 兼容

2.2 添加相机

操作步骤

  1. 在 IDE 左侧面板中选择 视觉系统 标签页
  2. 点击 添加相机 按钮
  3. 系统自动扫描可用相机
┌───────────────────────────────────────────────┐
│ 添加相机 │
│ │
│ ● 扫描到 3 个设备 │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ ☑ USB 相机 #1 (USB 3.0) │ │
│ │ Hikvision MV-CA013-UC │ │
│ │ 1280×1024 30fps │ │
│ ├─────────────────────────────────────────┤ │
│ │ ☐ GigE 相机 #1 (192.168.1.100) │ │
│ │ Basler acA2440-75um │ │
│ │ 2448×2048 75fps │ │
│ ├─────────────────────────────────────────┤ │
│ │ ☐ GenTL 采集卡 #1 │ │
│ │ Matrox Radient eV-CL │ │
│ │ 4096×3072 60fps │ │
│ └─────────────────────────────────────────┘ │
│ │
│ [ 添加选中设备 ] [ 刷新扫描 ] │
└───────────────────────────────────────────────┘
  1. 勾选要添加的相机,点击 添加选中设备
  2. 相机出现在视觉系统面板中,可开始配置参数

2.3 相机参数详解

曝光 (Exposure)

曝光时间决定了相机传感器收集光线的时间长度。

曝光时间 = 传感器收集光线的总时间

┌──────────────┐
│ │ 曝光时间短 → 图像暗,但运动模糊少
│ 电荷积累 │ 曝光时间长 → 图像亮,但运动模糊多
│ │
└──────────────┘
←── 曝光时间 ──→
参数说明取值范围典型值
ExposureAuto自动曝光TRUE/FALSETRUE(开发时)
ExposureTime手动曝光时间 (µs)10~10000003000~5000 µs
ExposureMode曝光模式Timed/TriggerWidthTimed

选择曝光时间的经验法则

  • 静态物体:曝光时间 = 2000~5000 µs
  • 运动物体:曝光时间 < 运动速度的倒数(如 2m/s → < 500 µs)
  • 暗光环境:曝光时间适当增加,但注意运动模糊

曝光与帧率的关系

最大帧率 ≈ 1 / (曝光时间 + 读出时间)

示例:曝光 5000 µs,读出时间 10000 µs
最大帧率 ≈ 1 / (0.005 + 0.010) = 66.7 fps

增益 (Gain)

增益放大图像信号,但也会放大噪声。

原始信号 ──→ [增益放大器] ──→ 放大后的信号(含噪声)
参数说明取值范围典型值
GainAuto自动增益TRUE/FALSEFALSE(手动控制)
Gain手动增益 (dB)0~240~6 dB

最佳实践

  • 优先调曝光时间,增益尽量小(< 6 dB)
  • 增益 > 12 dB 时噪声明显增加
  • 自动增益只适用于光照变化大的场景

触发模式 (Trigger Mode)

模式说明适用场景
Software软件触发开发调试、手动触发
Hardware硬件 Line 触发产线同步采集
FreeRun自由运行连续采集监控

硬件触发接线

相机 Line0 ──── PLC DO 输出 ──── 产品到位传感器

├── 上升沿触发采集
└── 下降沿触发结束曝光

像素格式 (Pixel Format)

格式每像素位数说明适用场景
Mono88 bit灰度,数据量小条码、尺寸测量
Mono1010 bit灰度,高动态范围缺陷检测
Mono1212 bit灰度,更高动态范围高精度检测
BayerRG88 bitRAW 数据,需去马赛克彩色相机原始数据
RGB824 bit彩色颜色识别、通用
YUV42216 bit彩色,压缩格式视频流

2.4 多相机管理

Vision Studio 支持同时管理多个相机,每个相机独立配置。

添加多个相机

视觉系统面板
┌──────────────────────────────────────────┐
│ 视觉系统 │
│ ┌──────────────────────────────────────┐│
│ │ 相机列表 ││
│ │ ├─ ● USB_CAM_1 [运行中] ││
│ │ │ 1280×1024 30fps 曝光 5000µs ││
│ │ ├─ ● GIGE_CAM_1 [运行中] ││
│ │ │ 2448×2048 75fps 曝光 3000µs ││
│ │ └─ ○ GENTL_CAM_1 [停止] ││
│ │ 4096×3072 60fps 曝光 2000µs ││
│ └──────────────────────────────────────┘│
│ │
│ [添加相机] [启动全部] [停止全部] │
└──────────────────────────────────────────┘

常见错误

错误原因解决方法
相机扫描不到驱动未安装 / 线缆松动检查设备管理器,安装 GenICam 驱动
相机报错 Timeout带宽不足 / 触发信号丢失降低分辨率或帧率,检查触发线
多相机帧率下降USB 带宽共享使用独立 USB 控制器,或换 GigE
图像花屏线缆质量问题 / 干扰更换屏蔽线缆,检查接地

2.5 相机校准

相机校准的目的是确定相机的内参(焦距、畸变系数)和外参(位置、姿态)。

内参标定

为什么要标定

  • 消除镜头畸变(桶形/枕形畸变)
  • 确定像素当量(mm/pixel)
  • 校正透视误差

标定步骤

  1. 准备标定板(棋盘格或圆点阵列)
┌────────────────────────────────┐
│ ██░░██░░██░░██░░██░░██░░██ │
│ ░░██░░██░░██░░██░░██░░██░░ │
│ ██░░██░░██░░██░░██░░██░░██ │
│ ░░██░░██░░██░░██░░██░░██░░ │
│ ██░░██░░██░░██░░██░░██░░██ │
│ ░░██░░██░░██░░██░░██░░██░░ │
│ ██░░██░░██░░██░░██░░██░░██ │
│ ░░██░░██░░██░░██░░██░░██░░ │
│ │
│ 棋盘格标定板 (7×7 内角点) │
│ 方格边长: 10mm │
└────────────────────────────────┘
  1. 从不同角度拍摄 10~20 张标定板图像
拍摄角度要求:
┌────────────────────────────────────────────┐
│ │
│ [正对] [左偏] [右偏] [上偏] [下偏] │
│ [倾斜] [旋转] [远距] [近距] [四角] │
│ │
│ 要求:覆盖整个视野、角度丰富 │
│ 标定板占视野 1/4~1/2 │
└────────────────────────────────────────────┘
  1. 在 Vision Studio 中打开标定工具,导入图像
  2. 系统自动检测角点并计算内参

标定结果示例

相机标定报告
─────────────────────────────────────────────
相机: USB_CAM_1 (Hikvision MV-CA013-UC)
标定日期: 2026-07-20 14:30:00
标定板: 棋盘格 7×7, 方格 10mm

内参矩阵:
fx = 2456.78 fy = 2455.23
cx = 643.12 cy = 511.45

畸变系数:
k1 = -0.0452 k2 = 0.0123
p1 = 0.0005 p2 = -0.0003
k3 = -0.0012

标定误差: 0.08 像素 ✅

像素当量 (工作距离 300mm): 0.052 mm/pixel
─────────────────────────────────────────────

畸变矫正

标定完成后,可在预处理流程中插入畸变矫正:

[相机采集] ──→ [畸变矫正] ──→ [后续处理]

参数

参数说明默认值
CameraName使用哪个相机的标定参数当前相机
Scale缩放因子1.0
Interpolation插值方式Linear

畸变矫正前后对比

矫正前:             矫正后:
┌──────────────┐ ┌──────────────┐
│ ┌──┐ │ │ ┌──┐ │
│ │ │ 弯曲 │ │ │ │ 直线 │
│ └──┘ │ │ └──┘ │
│ ┌──┐ │ │ ┌──┐ │
│ │ │ │ │ │ │ │
│ └──┘ │ │ └──┘ │
└──────────────┘ └──────────────┘
桶形畸变 矫正后(直线)

2.6 常见错误

错误现象可能原因解决方法
"设备未找到"相机驱动未安装安装 GenICam 驱动或 UVC 驱动
"采集超时"触发信号未到检查触发模式,软触发直接点采集
"图像全黑"曝光时间过短/光圈关闭增加曝光时间,打开镜头光圈
"图像全白"曝光时间过长/光照过强减少曝光时间,降低增益
"图像闪烁"光源频闪(50Hz 日光灯)曝光时间设为 20ms 整数倍
"帧率低"带宽不足降低分辨率,使用更小编码

第三章:图像采集

3.1 采集模式

Vision Studio 支持三种采集模式:

单帧采集 (Snap)

采集一帧图像后停止,适合触发式应用。

触发信号 ──→ 相机采集一帧 ──→ 输出图像 ──→ 等待下次触发

参数配置

参数说明默认值推荐值
Timeout采集超时 (ms)50003000~5000
ExposureMode曝光模式TimedTimed
TriggerMode触发模式Software根据场景

卡片图配置

[触发信号] ──→ [相机采集 (Snap)] ──→ [后续处理]
参数: Timeout=5000

连续采集 (Grab)

连续采集图像流,适合视频监控类应用。

相机 ──→ 连续采集 ──→ 帧 1 → 帧 2 → 帧 3 → ... → 帧 N

参数配置

参数说明默认值推荐值
FrameRate目标帧率 (fps)3015~30
BufferCount缓存帧数44~8
DropMode丢帧策略OldestOldest

卡片图配置

[相机采集 (Grab)] ──→ [帧处理循环]
参数: FrameRate=30

软触发 (Software Trigger)

通过软件指令触发采集,适合开发调试。

PLC 逻辑 ──→ VIS_JOB_START = TRUE ──→ 软件触发 ──→ 采集

触发流程

1. PLC 设置 VIS_JOB_START = TRUE
2. Vision Studio 检测到上升沿
3. 调用 CAM_Capture() 采集一帧
4. 执行后续处理
5. 完成后设置 VIS_JOB_DONE = TRUE

硬触发 (Hardware Trigger)

通过相机硬件 Line 信号触发,适合产线同步。

传感器 ──→ 信号 ──→ 相机 Line0 ──→ 触发采集 ──→ 图像输出

接线方式

PLC 输出 DO  ────┐
├──── 相机 Line0 (触发输入)
传感器输出 ────┘

触发时序

传感器信号  ┌────┐              ┌────┐
│ │ │ │
└────┴──────────────┴────┴────────
│ │
触发信号 ┌────┐ ┌────┐
│ │ │ │
└────┴────────┴────┴────────
│ │
曝光时间 ←─── 曝光 ──→ ←─── 曝光 ──→
│ │
图像读出 │←── 读出 ──→│

编码器触发 (Encoder Trigger)

通过编码器信号触发,适合传送带同步。

编码器 ──→ A/B 相脉冲 ──→ 相机 ──→ 等距触发采集

参数配置

参数说明默认值推荐值
EncoderMode编码器模式ABPhaseABPhase
PulsesPerTrigger每触发脉冲数1000根据分辨率
Direction方向ForwardForward
Divider分频系数11

3.2 图像格式与缓存

像素格式选择

格式每像素一帧 1280×1024适用场景
Mono81 byte1.25 MB条码、尺寸测量
Mono121.5 byte1.88 MB高精度检测
RGB83 byte3.75 MB颜色识别
BayerRG81 byte1.25 MB需去马赛克

选择建议

  • 不需要颜色 → Mono8(数据量最小,处理最快)
  • 需要颜色 → RGB8(直接可用,无需转换)
  • 高精度灰度 → Mono12(动态范围更高)

缓存管理

图像缓存管理策略:

参数说明默认值推荐值
MaxImageMemory图像缓存上限 (MB)512256~1024
BufferCount采集缓存帧数44~8
SwapToDisk超出缓存时写磁盘falsefalse
CleanupInterval清理间隔 (s)6060~300

缓存溢出处理

缓存使用率 > 80% ──→ 清理最早图像
缓存使用率 > 95% ──→ 停止新采集,抛出警告
缓存使用率 = 100% ──→ 返回错误,等待清理

3.3 常见错误

错误原因解决方法
采集超时触发信号未到检查触发源,或临时切到软触发
图像撕裂缓存不足增加 BufferCount
丢帧处理速度跟不上采集降低帧率,优化处理流程
内存溢出图像缓存未及时释放检查循环中是否有 IMG_Release

第四章:图像预处理

预处理是视觉系统的"第一道工序",预处理质量直接影响后续检测和测量的效果。

4.1 滤波 (Filtering)

滤波的目的是去除图像噪声,同时尽量保留边缘和细节。

高斯滤波

高斯滤波使用高斯核对图像进行卷积,平滑去噪。

原理:以每个像素为中心,用高斯核计算加权平均

┌─────────────┐
│ 1 4 7 4 1│
│ 4 16 26 16 4│
│ 7 26 41 26 7│ ← 5×5 高斯核 (σ=1.0)
│ 4 16 26 16 4│
│ 1 4 7 4 1│
└─────────────┘
÷ 273 (归一化)

参数

参数类型必填默认值说明
KernelSizeDWORD5核大小(奇数:3/5/7/9/11)
SigmaXREAL1.5X 方向标准差
SigmaYREALAutoY 方向标准差(=SigmaX)

KernelSize 选择

核大小 3 → 轻度去噪,保留细节
核大小 5 → 中等去噪,平衡效果
核大小 7 → 强力去噪,可能丢失小边缘
核大小 9 → 强去噪,仅适合大目标

示例

输入:                    输出(高斯滤波 5×5):
┌──────────────┐ ┌──────────────┐
│ │ │ │
│ ●●●●● │ │ ───── │
│ ● ● │ → │ │ │ │
│ ● ● │ │ │ │ │
│ ●●●●● │ │ ───── │
│ │ │ │
└──────────────┘ └──────────────┘
带噪声的矩形 去噪后边缘模糊

中值滤波

中值滤波用邻域像素的中值代替当前像素,对椒盐噪声特别有效。

原理:对邻域像素排序,取中值

原始像素值: 排序后: 中值:
[ 10, 255, 12 ] [ 10, 12, 15 ] 12
[ 8, 5, 14 ] [ 8, 5, 14 ]
[ 15, 255, 11 ] [ 11, 15, 255] ← 椒盐噪声 (255) 被排除了

参数

参数类型必填默认值说明
KernelSizeDWORD5核大小(奇数:3/5/7)

应用场景

  • 去除椒盐噪声(传感器坏点)
  • 保留边缘(比高斯滤波好)
  • 不适合高斯噪声

双边滤波

双边滤波同时考虑空间距离和像素值差异,实现"保边去噪"。

原理:权重 = 空间权重 × 像素值权重

空间权重(高斯分布): 像素值权重(高斯分布):
┌───┐ ╱───╲
│ ● │ │ ← │ ← 边缘处权重小
└───┘ └───┘
中心权重最大 值差异大 → 权重小

参数

参数类型必填默认值说明
DiameterDWORD9邻域直径
SigmaColorREAL75颜色空间标准差
SigmaSpaceREAL75坐标空间标准差

示例

输入:                    输出(双边滤波):
┌──────────────┐ ┌──────────────┐
│ │ │ │
│ ┌──────┐ │ │ ┌──────┐ │
│ │ 噪声 │ │ → │ │ 平滑 │ │
│ │ 区域 │ │ │ │ (边缘保留)│
│ └──────┘ │ │ └──────┘ │
│ 边缘 │ │ 边缘清晰 │
└──────────────┘ └──────────────┘

滤波方法对比

方法去噪效果边缘保留速度适用场景
高斯滤波通用去噪
中值滤波好(椒盐噪声)传感器坏点修复
双边滤波保边去噪
均值滤波最快快速预览

4.2 形态学 (Morphology)

形态学操作基于图像形状进行处理,通常用在二值图像上。

腐蚀 (Erode)

腐蚀操作"收缩"前景区域,去除小的白色噪点。

原理:核范围内全为前景 → 保留,否则变背景

输入: 输出(腐蚀 3×3):
┌──────────────┐ ┌──────────────┐
│ │ │ │
│ ●●●●● │ │ ●●● │
│ ● ● │ → │ │ │ ← 边缘被腐蚀
│ ● ● │ │ │ │
│ ●●●●● │ │ ●●● │
│ │ │ │
└──────────────┘ └──────────────┘

膨胀 (Dilate)

膨胀操作"扩张"前景区域,填充小的空洞。

原理:核范围内有前景 → 变前景

输入: 输出(膨胀 3×3):
┌──────────────┐ ┌──────────────┐
│ │ │ │
│ ●●● │ │ ●●●●● │
│ ● │ → │ ●●●●● │ ← 边缘膨胀
│ ●●● │ │ ●●●●● │
│ │ │ │
└──────────────┘ └──────────────┘

开运算 (Open)

先腐蚀后膨胀,去除小噪点,分离相连物体。

应用:去除噪点、断开粘连

输入: 腐蚀后: 开运算结果:
┌──────┐ ┌──────┐ ┌──────┐
│ ●●○ │ │ ●● │ │ ●● │
│ ○●● │ → 腐蚀 │ ●● │ → 膨胀 │ ●● │
│ ●○● │ │ │ │ │ ← 小点被清除
└──────┘ └──────┘ └──────┘
● 前景 ○ 噪点

闭运算 (Close)

先膨胀后腐蚀,填充小空洞,连接断开的物体。

应用:填充空洞、连接断线

输入: 膨胀后: 闭运算结果:
┌──────┐ ┌──────┐ ┌──────┐
│ ● ○ │ │ ●●● │ │ ●●● │
│ │ → 膨胀 │ ●●● │ → 腐蚀 │ ●●● │ ← 空洞被填充
│ ● ○ │ │ ●●● │ │ ●●● │
└──────┘ └──────┘ └──────┘
● 前景 ○ 空洞

形态学参数

参数类型必填默认值说明
OperationENUMErode/Dilate/Open/Close/Gradient/TopHat/BlackHat
KernelShapeENUMRectRect/Cross/Ellipse
KernelSizeDWORD3核大小 (3/5/7/...)
IterationsDWORD1迭代次数

KernelShape 选择

Rect (矩形)     Cross (十字)     Ellipse (椭圆)
███ █ ███
███ ███ █████
███ █ ███

通用形状 保留矩形角 圆形物体

4.3 阈值分割 (Thresholding)

阈值分割将灰度图像转换为二值图像,分离前景和背景。

全局阈值

像素值 > 阈值 → 白色 (255)
像素值 ≤ 阈值 → 黑色 (0)

输入灰度图: 阈值 128 后:
┌────────────────┐ ┌────────────────┐
│ 200 150 100 50 │ │ 255 255 0 0│
│ 180 120 80 40 │ │ 255 0 0 0│
│ 160 100 60 30 │ │ 255 0 0 0│
│ 140 90 50 20 │ │ 255 0 0 0│
└────────────────┘ └────────────────┘

自适应阈值

根据局部区域自动计算阈值,适合光照不均匀的图像。

原理:每个像素的阈值 = 该像素邻域均值 - C

┌──────────────┐
│ 局部区域计算 │
│ 阈值 = 均值 - C│
└──────────────┘


输入(光照不均)→ 自适应阈值 → 均匀的二值图

Otsu 自动阈值

Otsu 算法自动寻找最佳阈值,使前景和背景的类间方差最大。

Otsu 算法原理:
1. 计算直方图
2. 遍历所有可能的阈值 (0~255)
3. 计算每个阈值的类间方差
4. 选择类间方差最大的阈值

直方图:

│ ████
│ ████████
│ ████████████
│ ████████████████
│████████████████████
└─────────────────────▶
0 128 255

最佳阈值 (Otsu)

阈值参数

参数类型必填默认值说明
ThresholdREAL128手动阈值
MaxValueREAL255最大值
TypeENUMBinary二值化类型
UseOtsuBOOLFALSE使用 Otsu
AdaptiveMethodENUMNone自适应方法
BlockSizeDWORD11自适应块大小

二值化类型详解

Binary:        BinaryInv:       Trunc:
255 ──── 255 ──── 255 ────
│ │ │
│ │ │───
0 ──────── 0 ──── 0 ────────
thresh 255 thresh 255 thresh 255

ToZero: ToZeroInv:
255 ──── 255 ────
│ │───
│ │
0 ──── 0 ────────
thresh 255 thresh 255

4.4 色彩空间转换

BGR ↔ Gray

BGR → Gray: Gray = 0.299 × R + 0.587 × G + 0.114 × B

彩色图: 灰度图:
┌────────────────┐ ┌────────────────┐
│ ████ ████ │ │ ▓▓▓▓ ▓▓▓▓ │
│ ██ ████ ██ │ → │ ▓▓ ▓▓▓▓ ▓▓ │
│ ████████████ │ │ ▓▓▓▓▓▓▓▓▓▓▓ │
│ ██ ████ ██ │ │ ▓▓ ▓▓▓▓ ▓▓ │
└────────────────┘ └────────────────┘
3 通道 (BGR) 1 通道 (Gray)

BGR ↔ HSV

HSV 色相更接近人类视觉感知,适合颜色识别。

H (Hue):        色相 0°~180° (OpenCV 范围)
S (Saturation): 饱和度 0~255
V (Value): 明度 0~255

HSV 色环:
0° (红)
330° 30°
\ /
300° ○ 60°
/ \
270° 90°
240° 120°
210° 150°
180° (青)

颜色提取示例

要提取红色物体:
1. 转 HSV: IMG_CvtColor(img, BGR2HSV)
2. 红色范围: H=0~10 或 160~180, S>50, V>50
3. 阈值: IMG_Threshold(hsv, ...)

结果:
原始图 → HSV 空间 → 红色阈值 → 红色区域二值图

4.5 几何变换

旋转

参数: Angle = 45°, Center = (640, 512), Scale = 1.0

旋转前: 旋转 45° 后:
┌────────────────┐ ┌────────────────┐
│ │ │ ┌─────┐ │
│ ┌──────────┐ │ │ / /│ │
│ │ │ │ → │ ┌─────┐ │ │
│ │ │ │ │ │ │/ │
│ └──────────┘ │ │ └─────┘ │
│ │ │ │
└────────────────┘ └────────────────┘

缩放

参数: Width=640, Height=480, Interpolation=Linear

原图 1280×1024: 缩放至 640×480:
┌────────────────┐ ┌────────────────┐
│ │ │ │
│ │ → │ │
│ │ │ │
│ │ │ │
└────────────────┘ └────────────────┘

插值方式选择

插值方式质量速度适用场景
Nearest最快快速预览
Linear通用缩放
Cubic高质量缩放
Lanczos4最好精确测量

仿射变换

仿射变换保持平行线,适合纠正倾斜。

变换矩阵:[[a, b, tx],
[c, d, ty]]

输入: 输出(纠正倾斜):
┌────────────────┐ ┌────────────────┐
│ ┌──────────┐ │ │ ┌──────────┐ │
│ \ \ │ → │ │ │ │
│ \────────\ │ │ │ │ │
│ │ │ └──────────┘ │
└────────────────┘ └────────────────┘
倾斜的物体 纠正后的物体

透视变换

透视变换将任意四边形映射为矩形,适合纠正透视畸变。

输入四个点:                   输出矩形:
(x1,y1) ─── (x2,y2) (0,0) ─── (w,0)
│ │ → │ │
│ │ │ │
(x3,y3) ─── (x4,y4) (0,h) ─── (w,h)

4.6 图像增强

直方图均衡

增强图像对比度,使直方图均匀分布。

暗图:                    直方图均衡后:
┌────────────────┐ ┌────────────────┐
│ │ │ ▓▓▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓▓▓▓▓ │ → │ ▓▓▓▓▓▓▓▓▓▓▓▓ │
│ │ │ ▓▓▓▓▓▓▓▓▓▓▓▓ │
│ │ │ │
└────────────────┘ └────────────────┘
细节不明显 细节清晰可见

直方图对比:
均衡前: 均衡后:
▲ ▲
│ ████ │ ████████████████
│ ████████████ │ ██████████████████
│ ██████████████ │ ████████████████████
└───────────▶ └───────────▶
0 255 0 255
集中在暗部 均匀分布

CLAHE (限制对比度自适应直方图均衡)

CLAHE 是直方图均衡的改进版,避免过度放大噪声。

原理:将图像分块 → 每块做直方图均衡 → 限制对比度 → 拼接

参数:
ClipLimit: 2.0 (对比度限制,越大增强越强)
TileGridSize: 8 (分块大小,越小局部增强越强)

ClipLimit=0 (标准均衡): ClipLimit=2.0 (CLAHE):
┌────────────────┐ ┌────────────────┐
│ ▓▓▓▓▓▓▓▓▓▓ │ │ ▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓▓▓▓▓▓▓▓▓ │ → │ ▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓▓▓▓▓▓▓▓▓ │ │ ▓▓▓▓▓▓▓▓▓▓ │
│ 噪声被放大 │ │ 噪声抑制 │
└────────────────┘ └────────────────┘

4.7 ROI 提取

ROI (Region of Interest) 提取感兴趣区域,减少处理数据量。

完整图像 1280×1024:          ROI 区域 400×400:
┌────────────────────┐ ┌────────────────┐
│ │ │ │
│ ┌──────────┐ │ │ │
│ │ ROI 区域 │ │ → │ │
│ │ 400×400 │ │ │ (只处理这个 │
│ └──────────┘ │ │ 区域) │
│ │ │ │
└────────────────────┘ └────────────────┘
处理量: 1.3 MB 处理量: 0.16 MB (节省 88%)

ROI 参数

参数类型必填默认值说明
XDWORD左上角 X
YDWORD左上角 Y
WidthDWORD区域宽度
HeightDWORD区域高度
RelativeBOOLFALSE相对坐标 (0.0~1.0)

Relative 模式

Relative=FALSE: X=100, Y=100, W=400, H=400
绝对像素坐标,从 (100,100) 到 (500,500)

Relative=TRUE: X=0.1, Y=0.1, W=0.5, H=0.5
相对坐标,从图像 10% 位置开始,取 50% 宽高

4.8 常见错误

错误原因解决方法
图像模糊滤波核太大减小 KernelSize
边缘丢失滤波过度换双边滤波,或减小 Sigma
阈值效果差光照不均匀用自适应阈值或 CLAHE
形态学过度迭代次数太多减少 Iterations
ROI 越界区域超出图像检查 ROI 范围,或加边界检查
色彩转换错误输入格式不匹配检查输入图像通道数

第五章:目标检测 (Object Detection)

5.1 深度学习检测器

Vision Studio 使用 ONNX Runtime 进行深度学习推理,支持 YOLOv8/v9/v10/v11 等主流模型。

ONNX 模型推理

参数表

参数类型必填默认值说明
ModelPathSTRINGONNX 模型文件路径
InputWidthDWORD640模型输入宽度
InputHeightDWORD640模型输入高度
ConfidenceREAL0.5置信度阈值
NMSThresholdREAL0.45NMS 阈值
MaxDetectionsDWORD256最大检测目标数
LabelsPathSTRING标签文件路径
ExecutionProviderENUMAuto推理后端

ExecutionProvider 选项

说明要求
Auto自动选择(优先 GPU)
CPUCPU 推理
CUDANVIDIA GPU 推理CUDA 11.8+
OpenCLIntel GPU 推理OpenCL 2.0+
TensorRTNVIDIA TensorRTTensorRT 8.6+

推理流程

输入图像 1280×1024 → 预处理 → 模型推理 → 后处理 → 检测结果
│ │ │ │
▼ ▼ ▼ ▼
原始图像 缩放至 ONNX NMS 过滤
640×640 推理 + 缩放回原图坐标

YOLOv8 输出解析

模型输出: [1, 84, 8400]

84 = 4 (边界框: cx,cy,w,h) + 80 (COCO 类别概率)

8400 = 3 个尺度的检测结果总和
- 80×80 网格 (小物体)
- 40×40 网格 (中物体)
- 20×20 网格 (大物体)

后处理步骤:
1. 解析 8400 个候选框
2. 过滤置信度 < 阈值的候选框
3. 对每个类别做 NMS
4. 缩放回原始图像尺寸

卡片图配置

[相机采集] ──→ [缩放 640×640] ──→ [目标检测] ──→ [结果输出]
│ │
│ ModelPath: model.onnx
│ Confidence: 0.5
│ NMS: 0.45

│ (预处理)
│ Interpolation: Linear
│ KeepAspectRatio: TRUE
│ PadColor: Black

运行结果示例

┌──────────────────────────────────────────────┐
│ 检测结果:3 个目标 │
│ │
│ ┌──────────┬────────┬────────┬────────────┐ │
│ │ 类别 │ 置信度 │ 位置 (x,y) │ 尺寸 (w,h)│ │
│ ├──────────┼────────┼────────┼────────────┤ │
│ │ bottle │ 0.92 │ (320,240) │ (80, 120) │ │
│ │ cap_top │ 0.88 │ (640,200) │ (60, 40) │ │
│ │ lid │ 0.76 │ (800,500) │ (100, 60) │ │
│ └──────────┴────────┴────────┴────────────┘ │
│ │
│ 推理耗时: 8 ms (GPU) │
└──────────────────────────────────────────────┘

模型导出到 ONNX

YOLOv8 导出示例 (Python):

from ultralytics import YOLO

# 加载训练好的模型
model = YOLO("runs/detect/train/weights/best.pt")

# 导出为 ONNX
model.export(format="onnx", imgsz=640, opset=19)
# 输出: best.onnx

导出参数说明

参数说明推荐值
format导出格式"onnx"
imgsz输入尺寸640(与训练时一致)
opsetONNX opset 版本19(与 Vision Studio 相容)
simplify简化模型True
dynamic动态 batchFalse(固定尺寸推理更快)

5.2 传统检测器

Blob 分析

Blob 分析对二值图像中的连通域进行检测和分析。

参数

参数类型必填默认值说明
MinAreaREAL100最小面积 (像素)
MaxAreaREAL100000最大面积 (像素)
MinCircularityREAL0.0最小圆形度 (0~1)
MinConvexityREAL0.0最小凸度 (0~1)
MinInertiaRatioREAL0.0最小惯性比
FilterByColorBOOLFALSE按颜色过滤
BlobColorDWORD255目标颜色 (0=黑, 255=白)

Blob 分析流程

二值化图像 → 连通域标记 → 过滤 → 分析 → 输出

┌──────────────┐
│ ██████ │
│ ██░░██ ██ │
│ ██████ │
│ ██████│
└──────────────┘

连通域标记后:
┌──────────────┐
│ 111111 │
│ 11○○11 22 │
│ 111111 │
│ 333333│
└──────────────┘

过滤后(去掉面积 < 100 的 Blob #2):
Blob #1: 面积=200, 圆形度=0.85, 质心=(50,50)
Blob #3: 面积=300, 圆形度=0.40, 质心=(180,80)

Blob 输出属性

属性说明示例
area面积 (像素)200
centroid_x质心 X50.0
centroid_y质心 Y50.0
bounding_box外接矩形(40,40,80,60)
circularity圆形度 (4πA/P²)0.85
convexity凸度 (面积/凸包面积)0.95
elongation伸长率1.2
orientation方向角度45.0°

连通域分析

连通域分析 (Connected Component Analysis) 标记图像中所有连通区域。

4-连通:                8-连通:
↑ ↖↑↗
← ○ → ←○→
↓ ↙↓↘

4-连通更严格,8-连通更容易连接

参数

参数类型必填默认值说明
ConnectivityDWORD8连通性 (4 或 8)
MinAreaREAL0最小面积过滤
MaxAreaREAL0最大面积 (0=不限)

5.3 模板匹配 (Template Matching)

模板匹配在图像中搜索与模板图像最相似的位置。

归一化互相关匹配

原理:在图像上滑动模板,计算每个位置的相似度
相似度范围:-1~1(1 表示完全匹配)

输入图像: 模板: 匹配结果:
┌──────────────┐ ┌────────┐ ┌──────────────┐
│ │ │ ████ │ │ │
│ ○○ ████ │ │ ████ │ → │ ●● ████ │
│ ○○ │ │ ████ │ │ ●● │
│ ██ │ └────────┘ │ ██ │
└──────────────┘ └──────────────┘
模板是 4×4 方块 匹配评分: 0.95

参数

参数类型必填默认值说明
TemplatePathSTRING模板图像路径
MethodENUMNormed匹配方法
MinScoreREAL0.7最低匹配评分
MaxMatchesDWORD1最大匹配数
SearchRoiRECT全图搜索区域

匹配方法

方法说明对光照敏感度速度
Normed归一化互相关不敏感
NormedSqDiff归一化平方差(越小越匹配)敏感
CCoeffNormed归一化相关系数不敏感

形状匹配

基于轮廓的形状匹配,不受光照变化影响。

参数:
ContourTemplate: 形状模板文件
MinScore: 0.6
ScaleMin: 0.8
ScaleMax: 1.2
AngleRange: 360°

形状匹配结果:
┌──────────────────────────────────────┐
│ │
│ 匹配位置 1: (320, 240) 评分: 0.92 │
│ 缩放: 0.95 角度: 15.3° │
│ │
│ 匹配位置 2: (800, 600) 评分: 0.85 │
│ 缩放: 1.02 角度: -5.7° │
│ │
└──────────────────────────────────────┘

5.4 边缘检测 (Edge Detection)

Canny 边缘检测

Canny 边缘检测是最常用的边缘检测算法,具有低错误率、精确定位和单边缘响应等优点。

Canny 算法流程:
原始图像 → 高斯滤波 → 梯度计算 → 非极大值抑制 → 双阈值检测 → 边缘图像

双阈值:
高阈值: 150 → 强边缘(必定保留)
低阈值: 50 → 弱边缘(仅连接强边缘时保留)

梯度方向:
← 水平边缘 (垂直梯度最大)
↑ 垂直边缘 (水平梯度最大)
↗ 对角边缘 (两个方向梯度都大)

参数

参数类型必填默认值说明
LowThresholdREAL50低阈值
HighThresholdREAL150高阈值
ApertureSizeDWORD3Sobel 算子大小 (3/5/7)

阈值选择指南

高阈值/低阈值 ≈ 2:1 ~ 3:1

场景 低阈值 高阈值
清晰边缘 50 150
弱边缘(如划痕) 30 90
噪声较大 80 240

Sobel 边缘检测

Sobel 算子计算图像梯度,对噪声敏感。

Sobel X 核:          Sobel Y 核:
[-1 0 1] [-1 -2 -1]
[-2 0 2] [ 0 0 0]
[-1 0 1] [ 1 2 1]

Sobel X 结果: Sobel Y 结果:
检测垂直边缘 检测水平边缘
┌───┐ ┌───┐
│ │ │ │───│
│ │ │ │───│
│ │ │ └───┘
└───┘

参数

参数类型必填默认值说明
DxDWORD1X 方向阶数
DyDWORD0Y 方向阶数
ApertureSizeDWORD3核大小

Laplacian 边缘检测

Laplacian 算子检测二阶导数,对噪声非常敏感。

Laplacian 核:
[0 1 0]
[1 -4 1]
[0 1 0]

特点:对边缘位置敏感,但会放大噪声

5.5 特征匹配 (SIFT/SURF/ORB)

特征匹配在不同图像间寻找对应的特征点,适合拼接、定位等场景。

参数

参数类型必填默认值说明
MethodENUM特征检测方法
MaxFeaturesDWORD1000最大特征点数
MatchRatioREAL0.75Lowe 匹配比率
MinMatchesDWORD10最少匹配点数

特征匹配方法对比

方法旋转不变缩放不变光照不变速度适用场景
SIFT精确匹配
SURF通用匹配
ORB部分实时应用

5.6 常见错误

错误原因解决方法
检测不到目标置信度阈值太高降低 Confidence 到 0.3~0.4
检测框太多NMS 阈值太低提高 NMSThreshold 到 0.5~0.6
推理速度慢使用 CPU 推理切换到 GPU,或换小模型
模型加载失败ONNX 版本不兼容检查 opset 版本,重新导出
标签显示错误标签文件顺序不对检查 labels.txt 是否与训练时一致
模板匹配失败光照变化用形状匹配代替
Canny 边缘不连续阈值设置不当降低 LowThreshold 或增加 HighThreshold

第六章:图像测量 (Measurement)

6.1 边缘定位

边缘定位是测量的基础,Vision Studio 提供亚像素级别的边缘定位。

直线拟合

从图像中提取直线边缘,输出直线参数。

参数:
Roi: (100, 100, 500, 50) ← 矩形 ROI
EdgeThreshold: 50
MinLength: 100
MaxGap: 10

ROI 区域: 边缘检测结果: 直线拟合:
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ │ │ │ │ │
│ ───────────── │ │ ·········· │ │ ────────────── │
│ │ │ │ │ │
│ │ │ │ │ │
└────────────────────┘ └────────────────────┘ └────────────────────┘
搜索区域 亚像素边缘点 拟合的直线

输出Line

字段类型说明
x1REAL起点 X
y1REAL起点 Y
x2REAL终点 X
y2REAL终点 Y
angleREAL角度 (度)
scoreREAL拟合评分

圆拟合

从图像中提取圆形边缘,输出圆心和半径。

参数:
Roi: (100, 100, 300, 300)
EdgeThreshold: 50
MinRadius: 50
MaxRadius: 500

ROI 区域: 边缘点: 拟合圆:
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ │ │ ······ │ │ ╭──────╮ │
│ ○○○○○○ │ │ ·· ·· │ │ ╱ ╲ │
│ ○○ ○○ │ → │ · · │ → │ │ ● │ │
│ ○○ ○○ │ │ · · │ │ ╲ ╱ │
│ ○○○○○○ │ │ ·· ·· │ │ ╰──────╯ │
│ │ │ ······ │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
搜索区域 亚像素边缘点 拟合圆 (圆心+半径)

输出Circle

字段类型说明
center_xREAL圆心 X
center_yREAL圆心 Y
radiusREAL半径 (像素)
scoreREAL拟合评分

6.2 点测量

两点距离

参数:
Point1: (320, 240)
Point2: (800, 600)

计算:距离 = sqrt((800-320)² + (600-240)²)
= sqrt(580² + 360²) = sqrt(336400 + 129600) = sqrt(466000)
= 682.6 像素

标定后:682.6 × 0.05 mm/pixel = 34.13 mm

点到线距离

参数:
Point: (500, 300)
Line: (100, 200, 900, 200)

计算:点到水平线的距离 = |300 - 200| = 100 像素
标定后:100 × 0.05 = 5 mm

6.3 角度测量

两线夹角

线 1: (100, 200, 500, 200)  ← 水平线
线 2: (300, 100, 300, 500) ← 垂直线

夹角 = 90°

输出:
┌──────────────────────────────────────┐
│ │
│ 线 2 │
│ │ 线 1 │
│ │──────────────────── │
│ │ │
│ │ 角度 = 90° │
│ │ │
└──────────────────────────────────────┘

6.4 圆拟合

最小二乘法

最小二乘法拟合圆:
给定 N 个边缘点,最小化 ∑(距离_圆心 - 半径)²

优点:计算快
缺点:对离群点敏感

RANSAC 拟合

RANSAC 拟合圆:
1. 随机选 3 个点拟合圆
2. 计算所有点到圆的距离
3. 统计内点数量
4. 重复 1-3 步 N 次
5. 选择内点最多的圆

优点:对离群点鲁棒
缺点:计算慢

参数

参数类型必填默认值说明
MethodENUMLeastSquaresLeastSquares / RANSAC
RansacThresholdREAL2.0RANSAC 内点阈值 (像素)
RansacMaxIterDWORD1000RANSAC 最大迭代次数

6.5 卡尺工具 (Caliper)

卡尺工具是工业视觉中最常用的测量工具,用于测量边缘间距。

卡尺工具的工作原理:

┌──────────────────────────────────────────────┐
│ │
│ ┌─ 卡尺矩形 ROI ───────────────┐ │
│ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │
│ │ │H1│ │H2│ │H3│ │H4│ │ │
│ │ └──┘ └──┘ └──┘ └──┘ │ │
│ │ 测量范围: 从 H1 到 H4 │ │
│ │ 宽度 = H4 - H1 = 200 像素 │ │
│ └──────────────────────────────┘ │
│ │
└──────────────────────────────────────────────┘

参数

参数类型必填默认值说明
RoiXDWORD卡尺 ROI X
RoiYDWORD卡尺 ROI Y
RoiWidthDWORD卡尺宽度
RoiHeightDWORD卡尺高度
EdgeSelectorENUMBest边缘选择策略
EdgePolarityENUMAny边缘极性
MinEdgeStrengthREAL30最小边缘强度
NumEdgesDWORD2边缘数量

EdgeSelector

说明示意图
Best最强边缘选择梯度最大的边
First第一个边缘从扫描方向第一个
Last最后一个边缘从扫描方向最后一个
All全部边缘返回所有检测到的边

EdgePolarity

Any:      ← 黑→白 或 白→黑 都检测
Positive: 只检测 ────────→ 白→黑 边缘
Negative: 只检测 ────────→ 黑→白 边缘

6.6 几何测量综合示例

测量零件孔径和位置度

卡片图流程:
[相机采集] ──→ [畸变矫正] ──→ [边缘检测] ──→ [圆拟合] ──→ [测量] ──→ [结果输出]

关键参数:
畸变矫正: 使用标定参数
Canny: Low=50, High=150
圆拟合: Method=RANSAC, MinRadius=50

测量结果:
┌──────────────────────────────────────────────┐
│ 零件: 支架-A292 │
│ │
│ ┌──────────┬──────┬──────┬──────┬────────┐ │
│ │ 测量项 │ 标称值 │ 实测值 │ 公差 │ 结果 │ │
│ ├──────────┼──────┼──────┼──────┼────────┤ │
│ │ 孔径 #1 │ 20.0 │ 20.02│ ±0.1 │ OK │ │
│ │ 孔径 #2 │ 12.0 │ 12.03│ ±0.1 │ OK │ │
│ │ 孔径 #3 │ 8.0 │ 8.01 │ ±0.05│ OK │ │
│ │ 间距 #1 │ 50.0 │ 49.98│ ±0.2 │ OK │ │
│ │ 间距 #2 │ 30.0 │ 30.05│ ±0.2 │ OK │ │
│ │ 角度 │ 90.0 │ 89.8 │ ±1.0 │ OK │ │
│ └──────────┴──────┴──────┴──────┴────────┘ │
│ │
│ 总体判定: OK │
└──────────────────────────────────────────────┘

6.7 常见错误

错误原因解决方法
边缘检测不到边缘强度不够降低 EdgeThreshold,改善照明
拟合圆不准确边缘点太少扩大 ROI,增加边缘检测范围
测量结果跳变边缘不稳定使用 RANSAC,增加 AvgNum 做平均
单位错误标定系数不对确认像素当量 mm/pixel
角度跳变 180°角度取模问题使用有向角度

第七章:识别 (Recognition)

7.1 条码读取 (1D Barcode)

Vision Studio 支持常见的一维条码类型。

支持的条码类型

条码类型说明字符集长度
Code128高密度字母数字ASCII 128可变
Code39字母数字 + 符号43 字符可变
EAN1313 位商品码数字13 位
EAN88 位商品码数字8 位
UPC-A12 位商品码数字12 位
UPC-E6 位压缩码数字6 位
ITF交错 2/5 码数字可变
Codabar条形码数字+6 字符可变
Code93高密度安全码ASCII 93可变
PDF417堆叠式条码ASCII 全部可变
DataBar复合条码数字可变

参数配置

参数类型必填默认值说明
RoiX/Y/Width/HeightDWORD全图搜索区域
SymbologyENUMAuto码类型(Auto=自动检测)
TimeoutDWORD2000识别超时 (ms)
TryHarderBOOLFALSE增强识别(降低速度)

TryHarder 说明

TryHarder=FALSE: 快速识别,适合清晰条码(1-5ms)
TryHarder=TRUE: 增强识别,适合模糊/损坏条码(50-200ms)

卡片图配置

[相机采集] ──→ [图像增强] ──→ [条码识别] ──→ [结果输出]
│ │
│ Symbology: Auto
│ Timeout: 2000
│ TryHarder: FALSE

CLAHE: ClipLimit=2.0

结果处理示例

// 条码识别结果处理
IF decode_result.content <> "" THEN
// 根据条码内容分拣
CASE decode_result.format OF
FORMAT_CODE128:
// Code128 条码
IF LEFT(decode_result.content, 3) = "ORD" THEN
channel := 1; // 订单
ELSIF LEFT(decode_result.content, 3) = "RET" THEN
channel := 2; // 退货
ELSE
channel := 3; // 其他
END_IF;

FORMAT_EAN13:
// EAN13 商品码
channel := 1;
END_CASE;

// 输出
VIS_WriteVariable("SORT_CHANNEL", INT_TO_REAL(channel));
END_IF;

7.2 二维码读取 (2D Code)

支持的二维码类型

码类型说明容量特点
QR Code矩阵二维码最多 7K 数字广泛使用
Micro QR小型 QR 码最多 35 字符小空间
DataMatrix工业矩阵码最多 2K 字符容错高
Aztec金字塔码最多 3K 字符无需空白区
PDF417堆叠式条码最多 1K 字符大容量

参数配置

QR 码参数

参数类型必填默认值说明
RoiX/Y/Width/HeightDWORD全图搜索区域
TimeoutDWORD2000识别超时 (ms)
MicroQRBOOLFALSE支持 Micro QR

DataMatrix 参数

参数类型必填默认值说明
RoiX/Y/Width/HeightDWORD全图搜索区域
TimeoutDWORD2000识别超时
RectOnlyBOOLFALSE仅矩形 DM 码

7.3 字符识别 (OCR)

Vision Studio OCR 基于 Tesseract 引擎,支持数字、字母和完整文本识别。

参数配置

参数类型必填默认值说明
RoiX/Y/Width/HeightDWORD全图搜索区域
LanguageSTRING"eng"识别语言
CharWhitelistSTRING""白名单字符
PsmModeENUMAuto页面分割模式
TimeoutDWORD3000识别超时 (ms)

Language 选项

语言字符串说明
"eng"英文
"eng+chi_sim"英文+简体中文
"eng+chi_tra"英文+繁体中文
"jpn"日文
"kor"韩文
"deu"德文

CharWhitelist 示例

白名单说明识别内容
"0123456789"仅数字1234567890
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-"大写字母+数字+连字符SN-20260720-01
".0123456789"数字+小数点12.34

PsmMode (页面分割模式)

模式说明适用场景
Auto自动检测通用
SingleBlock单块文本段落文字
SingleLine单行文本序列号、条码下方文字
SingleWord单单词短标签
SingleChar单字符独立字符
RawLine原始行精确行定位

OCR 预处理最佳实践

OCR 推荐预处理流程:
原始图像 → 灰度 → 二值化 → 形态学 → 倾斜校正 → OCR

每一步的作用:
1. 灰度:减少颜色干扰
2. 二值化:突出字符与背景的对比
3. 形态学闭运算:连接字符断裂部分
4. 倾斜校正:纠正拍摄角度偏差

预处理效果对比:
不处理: 处理后:
┌──────────────────────┐ ┌──────────────────────┐
│ SN-2026-07-20 │ │ SN-2026-07-20 │
│ ────────── │ → │ ────────── │
│ 字符模糊 │ │ 字符清晰 │
│ 背景不均匀 │ │ 背景均匀 │
│ 倾斜 2° │ │ 已校正 │
└──────────────────────┘ └──────────────────────┘

7.4 颜色识别

颜色识别在 HSV 空间中进行,适合区分不同颜色的物体。

颜色范围参考

颜色H 范围S 范围V 范围
红色010 或 16018050~25550~255
橙色11~2550~25550~255
黄色26~3550~25550~255
绿色36~8550~25550~255
蓝色86~12550~25550~255
紫色126~15550~25550~255
黑色0~1800~2550~50
白色0~1800~30200~255

颜色识别流程

1. 转 HSV: IMG_CvtColor(img, BGR2HSV)
2. 按颜色范围阈值
3. 计算区域面积
4. 判断颜色

示例:识别红色零件
blue_mask := IMG_Threshold(hsv, LOWER:=(100,50,50), UPPER:=(130,255,255));
red_mask := IMG_Threshold(hsv, LOWER:=(0,50,50), UPPER:=(10,255,255));
red_mask := red_mask OR IMG_Threshold(hsv, LOWER:=(160,50,50), UPPER:=(180,255,255));

7.5 缺陷检测 (Anomaly Detection)

异常检测基于深度学习模型,检测图像中的异常区域。

参数

参数类型必填默认值说明
ModelPathSTRING异常检测 ONNX 模型
ThresholdREAL0.5异常阈值
OutputHeatmapBOOLTRUE输出热力图
ExecutionProviderENUMAuto推理后端

异常检测输出

AnomalyResult:
anomaly_score: 0.87 (0~1, 越大越异常)
is_anomaly: TRUE (score > threshold)
heatmap: Image (异常区域热力图)

正常产品: 异常产品:
┌────────────────────┐ ┌────────────────────┐
│ │ │ │
│ │ │ ▓▓▓▓ │
│ (均匀) │ │ ▓▓▓▓▓▓▓▓ │
│ │ │ ▓▓▓▓▓▓▓▓ │
│ │ │ ▓▓▓▓ │
└────────────────────┘ └────────────────────┘
anomaly_score: 0.12 anomaly_score: 0.87
is_anomaly: FALSE is_anomaly: TRUE

7.6 常见错误

错误原因解决方法
条码读不到条码模糊或损坏启用 TryHarder,改善照明
条码读错对比度太低增加 CLAHE 预处理
QR 码读不到码太小或畸变靠近拍摄,或降低分辨率
OCR 识别率低字符切割不好调整二值化阈值,用白名单
颜色识别不准光照变化在 HSV 空间调大范围
异常检测误报阈值太低提高 Threshold

第八章:视觉流程编程

8.1 卡片图编辑器

卡片图编辑器是视觉流程的可视化编排工具,通过拖拽卡片构建处理管道。

编辑器界面

┌──────────────────────────────────────────────────────────────┐
│ 工具箱 (Toolbox) │ 编辑区 (Canvas) │
│ ┌────────────────────┐ │ ┌──────────────────────────┐ │
│ │ 采集 │ │ │ │ │
│ │ ├ 相机采集 │ │ │ [相机采集]──[预处理] │ │
│ │ ├ 图像加载 │ │ │ │ │ │ │
│ │ │ │ │ ▼ ▼ │ │
│ │ 预处理 │ │ │ [目标检测]──[结果输出] │ │
│ │ ├ 滤波 │ │ │ │ │
│ │ ├ 尺寸调整 │ │ └──────────────────────────┘ │
│ │ ├ 色彩转换 │ │ │
│ │ │ │ ┌──────────────────────────┐ │
│ │ 检测 │ │ │ 属性面板 (Properties) │ │
│ │ ├ 目标检测 │ │ │ ┌──────────────────────┐│ │
│ │ ├ 模板匹配 │ │ │ │ 卡片: 目标检测 ││ │
│ │ │ │ │ │ 模型: model.onnx ││ │
│ │ 测量 │ │ │ │ 阈值: 0.5 ││ │
│ │ ├ 圆/弧测量 │ │ │ │ NMS: 0.45 ││ │
│ │ ├ 直线测量 │ │ │ └──────────────────────┘│ │
│ │ ├ 点间距 │ │ └──────────────────────────┘ │
│ │ │ │ │
│ │ 识别 │ │ [状态栏: 就绪 | 卡片数: 4] │
│ │ ├ 条码识别 │ │ │
│ │ └─── │ │ │
│ └────────────────────┘ │ │
└──────────────────────────────────────────────────────────────┘

连接规则

1. 单向连接:数据从上游流向下游
[相机] ──→ [预处理] ✓
[预处理] ←── [相机] ✗

2. 一进多出:一个输出可连多个输入
[目标检测] ──→ [结果输出]

└──→ [图像保存] ✓

3. 类型匹配:输出类型必须兼容输入类型
[相机](Image) ──→ [目标检测](Image) ✓
[相机](Image) ──→ [条码识别](Image) ✓
[目标检测](DetectionResult) ──→ [结果输出](DetectionResult) ✓
[目标检测](DetectionResult) ──→ [滤波](Image) ✗

4. 不支持多输入合并(用 Vision SCL 实现)

卡片图示例

示例 1:产品外观检测

[相机采集] ──→ [灰度转换] ──→ [高斯滤波] ──→ [目标检测] ──→ [结果输出]
GigE GRAY8 5×5 model.onnx PLC 变量
2448×2048 阈值 0.5

示例 2:定位引导

[相机采集] ──→ [畸变矫正] ──→ [模板匹配] ──→ [坐标转换] ──→ [结果输出]
USB 3.0 标定参数 参考图像 像素→mm 机器人坐标
1280×1024 评分 > 0.7

示例 3:条码识别

[编码器触发] ──→ [相机采集] ──→ [CLAHE] ──→ [条码识别] ──→ [分拣输出]
传送带同步 线阵扫描 增强对比度 Code128 通道号

8.2 Vision SCL 编程

Vision SCL 是视觉专用编程语言,扩展了视觉数据类型和处理函数。

程序结构

PROGRAM ProgramName
VAR_INPUT
// 输入参数(从 PLC 传入)
trigger : BOOL;
part_id : INT;
END_VAR
VAR_OUTPUT
// 输出参数(结果回写 PLC)
result_count : INT;
is_ok : BOOL;
END_VAR
VAR
// 局部变量
cam : Camera;
img : Image;
result : DetectionResult;
i : INT;
END_VAR

// 主程序逻辑
// ...

END_PROGRAM

事件处理

Vision SCL 支持事件驱动模型:

事件触发时机典型用途
OnTrigger收到触发信号时重置计数器、记录起始时间
OnFrame采集到一帧时检查图像质量、动态调曝光
OnInferenceCompleted推理完成时条件分支、二次确认
OnFault发生故障时切换备用相机、报警
OnTimeout超时时输出默认值

事件绑定示例

PROGRAM VisionWithEvents
VAR
cam : Camera;
img : Image;
result : DetectionResult;
END_VAR

// 注册事件处理器
EVENT_BIND(EVENT_ON_TRIGGER, "OnTriggerHandler");
EVENT_BIND(EVENT_ON_FRAME, "OnFrameHandler");
EVENT_BIND(EVENT_ON_INFERENCE_COMPLETED, "OnInferenceHandler");
EVENT_BIND(EVENT_ON_FAULT, "OnFaultHandler");
EVENT_BIND(EVENT_ON_TIMEOUT, "OnTimeoutHandler");

// 主流程
cam := CAM_Open("USB_CAM_1");
img := CAM_Capture(cam, TIMEOUT := 5000);
result := OBJ_Detect(img, MODEL := "model.onnx");

EVENT_WAIT_ALL(TIMEOUT := 1000);
END_PROGRAM

// 推理完成事件处理
ACTION OnInferenceHandler
VAR
i : INT;
END_VAR
VIS_Log(LOG_INFO, "检测到 " + INT_TO_STRING(result.object_count) + " 个目标");

FOR i := 0 TO result.object_count - 1 DO
VIS_WriteVariable("VIS_OBJ_" + INT_TO_STRING(i) + "_CLASS",
STRING_TO_REAL(result.objects[i].class_name));
END_FOR;
END_ACTION

// 故障处理
ACTION OnFaultHandler
VIS_Log(LOG_ERROR, "视觉故障: " + error_message);

IF error_code = ERR_CAMERA_DISCONNECTED THEN
// 切换备用相机
alt_cam := CAM_Open("USB_CAM_2");
IF alt_cam <> INVALID_CAMERA THEN
VIS_WriteVariable("VIS_CAM_SWITCHED", 1.0);
END_IF;
END_IF;
END_ACTION

// 超时处理
ACTION OnTimeoutHandler
VIS_Log(LOG_WARN, "超时: " + stage + " 已耗时 " +
INT_TO_STRING(elapsed_ms) + "ms");
VIS_WriteVariable("VIS_RESULT_COUNT", 0.0);
END_ACTION

异步执行模型

视觉程序以 Job 形式异步执行,不阻塞 PLC 扫描周期。

PLC 扫描周期:         视觉 Job 执行:
┌───┐ ┌───┐ ┌───┐ ┌──────────────────┐
│ │ │ │ │ │ │ Job #1287 │
│ ① │ ② │ ③ │ │ ├──────────────────┤
│ │ │ │ │ │ │ 采集 → 推理 → 输出│
└───┘ └───┘ └───┘ └──────────────────┘
│ │ │ │
│ │ └── VIS_JOB_DONE 读到结果
│ │
│ └── VIS_JOB_START 触发 Job

└── PLC 正常逻辑不受影响

Job 状态机

         ┌──────────┐
│ IDLE │ ←── PLC 就绪
└────┬─────┘
│ 触发 (VIS_JOB_START ↑)

┌──────────┐
│ QUEUED │ ←── 排队等待资源
└────┬─────┘
│ 资源就绪

┌──────────┐
│ RUNNING │ ←── 执行中
└────┬─────┘

┌────────┼────────┐
▼ ▼ ▼
┌────────┐┌────────┐┌──────────┐
│DONE ││FAULT ││TIMEOUT │
│(成功) ││(故障) ││(超时) │
└────────┘└────────┘└──────────┘

8.3 结果回写 PLC 变量

视觉 Job 执行完成后,结果自动写入 PLC 变量区。

系统变量(所有视觉 Job 共享):

变量名类型说明
VIS_JOB_BUSYBOOL有 Job 正在执行
VIS_JOB_DONEBOOL最近一次 Job 完成
VIS_JOB_ERRORBOOL最近一次 Job 异常
VIS_JOB_ERROR_IDDWORD错误码
VIS_JOB_IDDWORD当前 Job 序号
VIS_JOB_ELAPSEDREAL执行耗时 (ms)

结果变量(按 Job 配置):

变量名类型说明
VIS_RESULT_COUNTINT检测目标数
VIS_RESULT_01_CLASSSTRING[32]目标 1 类别
VIS_RESULT_01_CONFREAL目标 1 置信度
VIS_RESULT_01_XREAL目标 1 X 坐标
VIS_RESULT_01_YREAL目标 1 Y 坐标
VIS_RESULT_01_WREAL目标 1 宽度
VIS_RESULT_01_HREAL目标 1 高度
VIS_RESULT_01_ANGLEREAL目标 1 角度
VIS_RESULT_02_*...目标 2(最多 256 个)

PLC 侧触发和读取示例

PROGRAM VisionIntegration
VAR
trigger_pulse : BOOL;
trigger_prev : BOOL;
result_count : INT;
i : INT;
END_VAR

// 上升沿触发
trigger_pulse := trigger_signal AND NOT trigger_prev;
trigger_prev := trigger_signal;

IF trigger_pulse THEN
VIS_JOB_START := TRUE;
ELSE
VIS_JOB_START := FALSE;
END_IF;

// 读取结果
IF VIS_JOB_DONE AND NOT VIS_JOB_BUSY THEN
IF VIS_JOB_ERROR THEN
// 错误处理
system_state := STATE_VISION_FAULT;
ELSE
result_count := VIS_RESULT_COUNT;
// 处理结果
END_IF;

// 清除完成标志
VIS_JOB_DONE := FALSE;
END_IF;

// 超时保护
IF VIS_JOB_BUSY AND (TIME_SINCE_TRIGGER > T#30S) THEN
VIS_JOB_ABORT := TRUE;
END_IF;
END_PROGRAM

8.4 常见错误

错误原因解决方法
卡片连接报错类型不匹配检查连接线的数据类型
视觉程序编译失败语法错误检查输出面板中的错误信息
Job 排队超时并发数过多增加 max_concurrent_jobs
结果不更新未清除 VIS_JOB_DONEPLC 中加清零逻辑
事件处理器不执行事件未绑定检查 EVENT_BIND 是否注册

第九章:模型管理

9.1 导入 ONNX 模型

模型管理器在 IDE 左侧 视觉系统模型管理 标签页中。

界面

┌──────────────────────────────────────────────────────────────┐
│ 模型管理 [+ 导入] │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 本地模型 │ │ 项目模型 │ │ 部署模型 │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ┌───────────────┬──────┬──────┬──────┬────────────────────┐│
│ │ 模型名称 │ 版本 │ 大小 │ 状态 │ 上次验证 ││
│ ├───────────────┼──────┼──────┼──────┼────────────────────┤│
│ │ surface_defect│ v3 │ 24MB │ ● 已部署 │ 2026-07-20 ││
│ │ position_det │ v2 │ 12MB │ ● 已验证 │ 2026-07-19 ││
│ │ barcode_reader│ v1 │ 8MB │ ○ 未验证 │ 2026-07-15 ││
│ └───────────────┴──────┴──────┴──────┴────────────────────┘│
│ │
│ [详情] [验证] [部署] [删除] [导出] │
└──────────────────────────────────────────────────────────────┘

导入步骤

  1. 点击 导入 按钮
  2. 选择 ONNX 模型文件
  3. 系统自动解析模型元数据
导入模型
────────────────────────────────────────────────
文件: surface_defect_v3.onnx
大小: 24.3 MB
算子集: opset 19

┌─ 输入 ──────────────────────────────────────┐
│ images: float32[1,3,640,640] │
└──────────────────────────────────────────────┘
┌─ 输出 ──────────────────────────────────────┐
│ output0: float32[1,84,8400] │
└──────────────────────────────────────────────┘

模型名称: surface_defect
版本号: v3

[确定] [取消]
  1. 确认名称和版本后,模型复制到项目目录 Vision/Models/

9.2 模型版本管理

版本命名规则v + 正整数,如 v1v2v3

版本操作

操作说明
新建版本导入新 ONNX 文件,版本号自动递增
回滚版本切换到历史版本,模型文件保留
对比版本对比两个版本的输入/输出/大小/性能
删除版本删除不需要的版本(部署中的不可删除)
设置默认指定默认使用的版本

版本对比

surface_defect v2 ↔ v3 对比
────────────────────────────────────────────────
属性 │ v2 │ v3
──────────────┼───────────────┼─────────────────
文件大小 │ 18.2 MB │ 24.3 MB
输入尺寸 │ 640×640 │ 640×640
算子集 │ opset 17 │ opset 19
mAP@0.5 │ 0.892 │ 0.935 ▲
推理延迟(CPU) │ 45 ms │ 38 ms ▲
推理延迟(GPU) │ 12 ms │ 8 ms ▲
模型架构 │ YOLOv8s │ YOLOv8m
训练数据集 │ 5000 张 │ 12000 张
训练日期 │ 2026-06-01 │ 2026-07-10

9.3 模型验证与测试

验证流程

  1. 选择模型 → 点击 验证
  2. 选择验证数据集
  3. 系统逐张推理并生成报告

验证报告

模型验证报告
────────────────────────────────────────────────
模型: surface_defect v3
验证集: 100 张图像
日期: 2026-07-20 14:30:00

┌─ 性能指标 ───────────────────────────────────┐
│ 平均推理延迟: 38 ms (CPU) / 8 ms (GPU) │
│ 平均帧率: 26 FPS (CPU) / 125 FPS (GPU) │
│ 最大内存占用: 156 MB │
└───────────────────────────────────────────────┘
┌─ 检测指标 ───────────────────────────────────┐
│ 准确率: 97.2% │ 误检率: 1.8% │
│ 召回率: 96.5% │ 漏检率: 3.5% │
│ mAP@0.5: 0.935 │ mAP@0.5:0.95: 0.712 │
└───────────────────────────────────────────────┘
┌─ 失败案例 ───────────────────────────────────┐
│ #1 缺陷: 划痕 │
│ 图像: test_023.jpg │
│ 实际: 有划痕 预测: 无缺陷 │
│ 置信度: 0.32 (低于阈值 0.5) │
│ #2 缺陷: 凹陷 │
│ 图像: test_047.jpg │
│ 实际: 有凹陷 预测: 无缺陷 │
│ 置信度: 0.41 (低于阈值 0.5) │
└───────────────────────────────────────────────┘

验证结论: 通过
建议: 失败案例均为低置信度漏检,可考虑降低
置信度阈值至 0.3 或补充训练数据

9.4 部署模型

部署流程

  1. 选择已验证的模型版本
  2. 点击 部署 按钮
  3. 选择部署目标
部署模型
────────────────────────────────────────────────
模型: surface_defect v3

部署目标:
● 当前项目 (本地)
○ 远程运行时 (192.168.3.197)

部署配置:
推理后端: GPU (CUDA)
超时时间: 5000 ms
最大并发: 2

[部署] [取消]

部署步骤

步骤说明状态
1. 模型压缩ONNX 优化 (图优化、常量折叠)完成
2. 格式转换转换为运行时格式完成
3. 资源分配分配 GPU 显存 / CPU 内存完成
4. 部署验证加载模型并运行 3 次验证推理完成
5. 注册完成创建模型 Session,准备就绪完成

9.5 蓝绿部署与回滚

蓝绿部署支持零停机切换模型版本。

蓝绿部署策略:

当前版本 (v3): 新版本 (v4):
┌──────────────┐ ┌──────────────┐
│ 蓝色 (活跃) │ │ 绿色 (预备) │
│ surface_def │ │ surface_def │
│ ect v3 │ │ ect v4 │
│ GPU 显存已分配│ │ GPU 显存已分配│
│ Session 就绪 │ │ Session 就绪 │
└──────────────┘ └──────────────┘
│ │
└──────────┬───────────┘


切换命令: 蓝色→绿色
新推理请求走绿色
蓝色保持 5 分钟回滚窗口

回滚:
5 分钟内检测到问题
→ 切回蓝色
→ 绿色卸载

模型文件结构

<项目根目录>/
└── Vision/
└── Models/
├── surface_defect/
│ ├── v1/
│ │ ├── model.onnx
│ │ ├── labels.txt
│ │ ├── metadata.json
│ │ └── validation.json
│ ├── v2/
│ └── v3/ ← 当前部署版本
├── position_detect/
└── models.index.json

9.6 常见错误

错误原因解决方法
模型导入失败ONNX 版本不兼容检查 opset 是否在 11~21 范围
模型验证失败验证数据集格式不对确保图像格式与模型输入一致
部署失败GPU 显存不足切换 CPU 推理,或减少 batch size
推理结果异常输入尺寸与模型不匹配检查 Resize 参数是否与模型一致
版本无法删除该版本正在使用先切换到其他版本

第十章:与 PLC 集成

10.1 触发信号

PLC 触发相机采集

触发方式对比

方式延迟精度接线适用场景
软件触发 (PLC 变量)10~50 ms中等非实时触发
硬件触发 (PLC DO)< 1 µs需要高速产线同步
编码器触发编码器脉冲精确位置需要传送带等距采集

PLC 变量触发配置

触发条件配置
────────────────────────────────────────────────
触发方式: ● PLC 变量触发

触发变量: VIS_TRIGGER_01
触发沿: ● 上升沿 ○ 下降沿
触发后去抖: 50 ms
超时时间: 5000 ms
超时动作: 输出默认值

[确定] [取消]

PLC 侧代码

// 产品到位时触发视觉
IF part_present AND NOT part_prev THEN
VIS_JOB_START := TRUE;
trigger_time := NOW();
END_IF;
part_prev := part_present;

10.2 结果回写

视觉 Job 完成后,结果自动写入 PLC 变量区。

回写流程

1. PLC 设置 VIS_JOB_START = TRUE
2. 运行时检测上升沿,创建 Job
3. Job 开始,VIS_JOB_BUSY = TRUE
4. 采集 → 预处理 → 推理 → 后处理
5. 结果写入 VIS_RESULT_* 变量
6. VIS_JOB_DONE = TRUE, VIS_JOB_BUSY = FALSE
7. PLC 下一个扫描周期读到完成
8. PLC 读取结果变量
9. PLC 将 VIS_JOB_DONE 清零

PLC 读取结果完整示例

PROGRAM VisionReader
VAR
trigger_pulse : BOOL;
trigger_prev : BOOL;
has_result : BOOL;
result_count : INT;
i : INT;
all_ok : BOOL;
END_VAR

// 触发
trigger_pulse := trigger_signal AND NOT trigger_prev;
trigger_prev := trigger_signal;

IF trigger_pulse THEN
VIS_JOB_START := TRUE;
ELSE
VIS_JOB_START := FALSE;
END_IF;

// 读取结果
IF VIS_JOB_DONE AND NOT VIS_JOB_BUSY THEN
IF VIS_JOB_ERROR THEN
// 错误处理
system_state := STATE_VISION_FAULT;
ELSE
result_count := VIS_RESULT_COUNT;

// 判断是否合格
IF result_count = 0 THEN
// 无缺陷,合格
all_ok := TRUE;
ELSE
// 有缺陷,不合格
all_ok := FALSE;
END_IF;

// 输出
product_ok := all_ok;
product_count := product_count + 1;
IF NOT all_ok THEN
defect_count := defect_count + 1;
END_IF;
END_IF;

// 清除完成标志
VIS_JOB_DONE := FALSE;
END_IF;

// 超时保护
IF VIS_JOB_BUSY AND (TIME() - trigger_time > T#30S) THEN
VIS_JOB_ABORT := TRUE;
system_state := STATE_VISION_TIMEOUT;
END_IF;
END_PROGRAM

10.3 视觉状态监控

运行时指标

指标说明单位读取方式
GPU 利用率GPU 计算核心占用率%系统变量
GPU 显存使用显存已用量MB系统变量
CPU 使用率视觉进程 CPU 占用%系统变量
推理延迟平均推理时间msVIS_JOB_ELAPSED
Job 排队长度当前等待队列长度个数系统变量
Job 吞吐量每分钟完成数个/min系统变量
成功率最近 100 次成功率%计算

状态监控示例

HMI 状态面板:
┌──────────────────────────────────────────────┐
│ 视觉系统状态 │
│ │
│ ● 运行中 帧率: 30 fps │
│ 推理延迟: 8 ms 排队: 0 │
│ GPU 显存: 512/1024 MB 成功率: 99.5% │
│ │
│ ┌─ 最近 100 次 Job ────────────────────────┐│
│ │ ████████████████████████████████████████ ││
│ │ ████ ││
│ │ 成功: 96 失败: 3 超时: 1 ││
│ └───────────────────────────────────────────┘│
└──────────────────────────────────────────────┘

10.4 故障处理与超时

故障分类

故障类型错误码可恢复处理方式
相机断开0x1001自动重连,最多 3 次
模型加载失败0x2001回退到上一个版本
推理异常0x3001记录日志,报错到 PLC
显存不足0x4001自动回退到 CPU
内存不足0x4002清理缓存后重试
超时0x5001输出默认值,下次重试
许可限制0x6001提示用户升级许可

自动恢复流程

检测到故障 ──→ 判断可恢复性
│ │
│ 可恢复 │ 不可恢复
▼ ▼
重试计数 记录日志
│ 通知 PLC
▼ 通知操作员
重试操作 │
│ ▼
├── 成功 → 恢复正常 禁用视觉功能

└── 失败 → 判断是否达到最大重试次数

┌────────┼────────┐
▼ ▼ ▼
相机故障 模型故障 其他故障
重连相机 回退版本 禁用功能

10.5 端到端示例:视觉引导定位抓取

场景:机器人从传送带上抓取无序来料的工件。

硬件配置

  • 相机:俯视安装,固定于支架 (Eye-to-Hand)
  • 机器人:6 轴工业机器人
  • PLC:Darra RT PLC 控制传送带和机器人

视觉流程

[编码器触发] ──→ [相机采集] ──→ [畸变矫正] ──→ [模板匹配]


[坐标转换]


[结果输出]
(机器人坐标)

PLC 逻辑

PROGRAM PickAndPlace
VAR
// 输入
part_detected : BOOL; // 来料检测传感器
robot_ready : BOOL; // 机器人就绪

// 视觉相关
trigger_pulse : BOOL;
trigger_prev : BOOL;
vision_ok : BOOL;

// 输出
grab_x, grab_y, grab_angle : REAL;
grab_request : BOOL;
cycle_count : INT;
END_VAR

// 触发视觉
trigger_pulse := part_detected AND NOT trigger_prev;
trigger_prev := part_detected;

IF trigger_pulse AND robot_ready THEN
VIS_JOB_START := TRUE;
END_IF;

// 读取视觉结果
IF VIS_JOB_DONE THEN
VIS_JOB_DONE := FALSE;

IF NOT VIS_JOB_ERROR AND VIS_RESULT_COUNT > 0 THEN
// 读取第一个工件的坐标
grab_x := VIS_RESULT_01_X;
grab_y := VIS_RESULT_01_Y;
grab_angle := VIS_RESULT_01_ANGLE;
grab_request := TRUE;
vision_ok := TRUE;
ELSE
// 视觉失败
vision_ok := FALSE;
grab_request := FALSE;
LOG_ERROR("视觉定位失败");
END_IF;
END_IF;

// 机器人抓取完成
IF grab_request AND robot_grab_done THEN
grab_request := FALSE;
cycle_count := cycle_count + 1;
END_IF;
END_PROGRAM

性能指标

指标
定位精度±0.3 mm
角度精度±0.5°
单次定位时间150 ms
抓取成功率99.5%
节拍3 秒/件

第十一章:实际应用示例

11.1 产品外观缺陷检测

场景:注塑件表面缺陷检测(划痕、凹陷、缺料、飞边)。

视觉流程

[相机采集] ──→ [预处理] ──→ [缺陷检测] ──→ [结果输出]
GigE 灰度+滤波 ONNX 模型 分拣信号
2448×2048 5×5 高斯 阈值 0.5 + 图像保存

关键配置

参数说明
相机Basler acA2440-75umGigE, 75fps
触发硬件触发 (PLC DO)产品到位时
曝光3000 µs适应白色注塑件
预处理灰度 + 高斯滤波 5×5去噪
模型surface_defect.onnxYOLOv8m
置信度阈值0.5过滤低质量
检测类别划痕, 凹陷, 缺料, 飞边4 类
结果输出分拣 DO + 数据通信分拣 + MES 上报

PLC 逻辑

FUNCTION_BLOCK FB_SurfaceInspection
VAR_INPUT
part_present : BOOL;
ejector_ready : BOOL;
END_VAR
VAR_OUTPUT
ejector : BOOL;
pass_count : INT;
fail_count : INT;
END_VAR
VAR
trigger_prev : BOOL;
END_VAR

trigger_pulse := part_present AND NOT trigger_prev;
trigger_prev := part_present;

IF trigger_pulse AND ejector_ready THEN
VIS_JOB_START := TRUE;
END_IF;

IF VIS_JOB_DONE THEN
VIS_JOB_DONE := FALSE;

IF NOT VIS_JOB_ERROR THEN
IF VIS_RESULT_COUNT > 0 THEN
// 有缺陷,不合格
ejector := TRUE;
fail_count := fail_count + 1;
ELSE
// 合格
ejector := FALSE;
pass_count := pass_count + 1;
END_IF;
ELSE
ejector := TRUE;
END_IF;
END_IF;

IF ejector AND NOT part_present THEN
ejector := FALSE;
END_IF;
END_FUNCTION_BLOCK

性能指标

指标
检测节拍800 ms/件
检测精度99.2%
误检率0.5%
漏检率0.3%
最大吞吐量75 件/分钟

11.2 定位引导机器人抓取

场景:无序来料,视觉系统定位工件,引导机器人抓取。

视觉流程

[相机采集] ──→ [模板匹配] ──→ [坐标转换] ──→ [结果输出]
俯视安装 形状匹配 像素→mm 机器人坐标
1280×1024 评分 > 0.7 手眼标定 X/Y/角度

手眼标定

标定板 → 机器人移动到 9 个位置 → 视觉记录像素坐标 → 计算变换矩阵

标定矩阵示例:
[ 0.052, 0.001, -10.5 ]
[ -0.001, 0.052, 8.2 ]
[ 0, 0, 1 ]

每个像素 = 0.052 mm

性能指标

指标
定位精度±0.3 mm
角度精度±0.5°
单次定位150 ms
抓取成功率99.5%

11.3 条码/二维码读取

场景:物流分拣线,读取包裹条码,按目的地分拣。

视觉流程

[编码器触发] ──→ [线阵扫描] ──→ [图像增强] ──→ [条码识别]

├──→ [分拣输出]
│ └→ 通道号 DO

└──→ [数据库写入]
└→ 追溯记录

关键配置

参数说明
相机线阵相机 4096 像素高速传送带
触发编码器触发与传送带同步
图像增强CLAHE改善条码对比度
条码类型Code128, QR, DataMatrix自适应
识别超时1000 ms快速识别

性能指标

指标
识别率99.7%
识别速度< 100 ms/次
传送带速度2 m/s

11.4 尺寸测量与分选

场景:机加工零件尺寸测量,判断是否在公差范围内。

视觉流程

[相机采集] ──→ [边缘检测] ──→ [几何测量] ──→ [结果判断]
背光照明 Canny 亚像素 圆/直线拟合 公差范围
500 万像素 50/150 最小二乘 OK/NG

测量项目:孔径 3 处、间距 2 处、角度 1 处

性能指标

指标
测量精度±0.01 mm
重复精度±0.005 mm
单次测量500 ms
误判率< 0.1%

11.5 OCR 字符识别

场景:读取产品表面激光刻印的序列号,用于追溯。

关键配置

参数说明
相机12MP 高分辨率1200 万像素
镜头50mm 微距高放大倍率
照明环形暗场突出刻印字符
预处理二值化 + 形态学闭运算字符增强
OCR 引擎Tesseract工业级 OCR
白名单A-Z, 0-9, -限制字符集
最低置信度0.8视为识别失败

性能指标

指标
识别率99.3%
误识率0.02%
识别速度< 300 ms/次
最小字符高度15 像素

11.6 综合示例:完整视觉工作站

场景:一个完整的视觉工作站,包含产品检测、定位、条码识别和尺寸测量。

工作站布局:
┌──────────────────────────────────────────────────┐
│ │
│ 工位 1 工位 2 工位 3 │
│ 外观检测 定位抓取 条码读取 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 相机 1 │ │ 相机 2 │ │ 相机 3 │ │
│ │ GigE │ │ USB 3.0 │ │ 线阵 │ │
│ │ 缺陷检测 │ │ 模板匹配 │ │ 条码识别 │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ┌────┴────┐ │
│ │ PLC │ │
│ │ 汇总判断 │ │
│ │ 分拣输出 │ │
│ └─────────┘ │
│ │
└──────────────────────────────────────────────────┘

PLC 汇总逻辑

// 三个工位视觉结果汇总
IF vis1_done AND vis2_done AND vis3_done THEN
// 全部合格
IF vis1_ok AND vis2_ok AND vis3_ok THEN
product_result := RESULT_OK;
ok_count := ok_count + 1;
ELSE
// 有不合格项
product_result := RESULT_NG;
ng_count := ng_count + 1;

// 记录不合格原因
IF NOT vis1_ok THEN
fault_reason := "外观缺陷";
ELSIF NOT vis2_ok THEN
fault_reason := "定位异常";
ELSE
fault_reason := "条码读取失败";
END_IF;
END_IF;

// 重置
vis1_done := FALSE;
vis2_done := FALSE;
vis3_done := FALSE;
END_IF;

第十二章:性能优化与排错

12.1 帧率优化

瓶颈分析

视觉流程各阶段耗时分布(典型值):

总耗时 = 采集 + 预处理 + 推理 + 后处理

采集: 4 ms (8%)
预处理: 3 ms (6%)
推理: 38 ms (76%) ← 通常是最慢的环节
后处理: 5 ms (10%)
──────────────────
总计: 50 ms (20 fps)

优化策略

策略效果说明
降低分辨率显著1280×1024 → 640×480,推理速度提升 2~4 倍
切换推理后端显著CPU → GPU,速度提升 5~10 倍
使用小模型显著YOLOv8m → YOLOv8n,速度提升 2 倍
模型量化显著FP32 → INT8,速度提升 2 倍,精度损失 < 1%
减少预处理中等只做必要的预处理
限制 ROI中等只处理感兴趣区域
批量推理中等同时处理多帧
调整帧率轻微降低目标帧率减少处理压力

GPU 加速配置

RuntimeResourcePolicy 配置
────────────────────────────────────────────────
GPU:
enabled: true
device_id: 0
memory_limit_mb: 1024
fallback_to_cpu: true

CPU:
max_cores: 2
affinity: [4, 5]
priority: below_normal

Concurrency:
max_concurrent_jobs: 2
queue_size: 10
job_timeout_ms: 30000

12.2 模型推理加速

模型选择指南

需求推荐模型推理延迟 (GPU)mAP
最快速度YOLOv8n2 ms0.872
平衡YOLOv8s4 ms0.895
高精度YOLOv8m8 ms0.912
最高精度YOLOv8l12 ms0.928

模型量化

FP32 模型 (24 MB) → INT8 量化 (12 MB)

量化方法:
后训练量化 (PTQ): 无需训练数据,简单
量化感知训练 (QAT): 需要训练数据,精度更好

量化效果:
FP32 → INT8: 速度提升 2 倍
精度损失: < 1%
内存减少: 50%

ONNX 优化

ONNX Runtime 自动优化:
1. 图优化:合并节点、消除冗余
2. 常量折叠:预计算常量表达式
3. 算子融合:减少 kernel launch 开销
4. 内存优化:复用 intermediate tensor

优化效果:推理速度提升 10~30%

12.3 常见故障与解决方法

相机相关

故障原因解决方法
相机扫描不到驱动未安装安装 GenICam 或 UVC 驱动
采集超时触发信号未到检查触发模式,临时切软触发
图像全黑曝光太短/光圈关闭增加曝光时间,开光圈
图像全白曝光太长/光照太强减少曝光,降增益
图像闪烁光源频闪 (50Hz)曝光时间设为 20ms 整数倍
帧率达不到带宽不足降低分辨率,减帧率

模型相关

故障原因解决方法
模型加载失败ONNX 版本不兼容检查 opset 版本
推理结果为空置信度阈值太高降到 0.3 试试
推理速度慢CPU 推理切 GPU 或换小模型
显存不足模型太大切 CPU 推理
检测框歪输入尺寸不匹配检查 Resize 参数

测量相关

故障原因解决方法
边缘检测不到边缘强度弱降低 EdgeThreshold
测量结果跳变边缘不稳定增加测量次数取平均
单位错误标定系数不对确认像素当量
圆拟合不准边缘点太少扩大 ROI

集成相关

故障原因解决方法
PLC 收不到结果VIS_JOB_DONE 未清零PLC 中加清零逻辑
Job 排队超时并发数设置太小增加 max_concurrent_jobs
视觉程序不触发触发变量未配置检查触发方式
结果变量不更新变量名不匹配检查命名

12.4 日志分析

日志位置%AppData%/DarraPLC/logs/vision_*.log

正常日志示例

[2026-07-20 14:30:00.123] [INFO] [VisionJob] Job #1287 开始执行 (程序: surface_inspect)
[2026-07-20 14:30:00.124] [INFO] [Acquisition] 相机 USB_CAM_1 采集开始, 曝光 5000µs
[2026-07-20 14:30:00.128] [INFO] [Acquisition] 采集完成, 1280×1024, 耗时 4ms
[2026-07-20 14:30:00.129] [INFO] [Preprocessing] 预处理开始
[2026-07-20 14:30:00.132] [INFO] [Preprocessing] 预处理完成, 耗时 3ms
[2026-07-20 14:30:00.133] [INFO] [Inference] 推理开始 (模型: surface_defect v3, GPU)
[2026-07-20 14:30:00.141] [INFO] [Inference] 推理完成, 耗时 8ms, 检测到 2 个目标
[2026-07-20 14:30:00.142] [INFO] [Postprocessing] 后处理完成, 耗时 1ms
[2026-07-20 14:30:00.143] [INFO] [ResultWrite] 结果写入 PLC 变量, 2 个目标
[2026-07-20 14:30:00.143] [INFO] [VisionJob] Job #1287 完成, 总耗时 20ms

故障日志示例

[2026-07-20 14:31:00.000] [ERROR] [VisionJob] Job #1288 失败
[2026-07-20 14:31:00.000] [ERROR] [Acquisition] 采集超时: 5000ms, 相机 USB_CAM_1
[2026-07-20 14:31:00.001] [WARN] [FaultHandler] 自动重试 #1, 等待 1000ms
[2026-07-20 14:31:01.002] [ERROR] [Acquisition] 采集超时: 5000ms, 相机 USB_CAM_1
[2026-07-20 14:31:01.002] [WARN] [FaultHandler] 自动重试 #2, 等待 2000ms
[2026-07-20 14:31:03.003] [ERROR] [Acquisition] 采集超时: 5000ms, 相机 USB_CAM_1
[2026-07-20 14:31:03.003] [WARN] [FaultHandler] 自动重试 #3, 等待 4000ms
[2026-07-20 14:31:07.004] [ERROR] [Acquisition] 采集超时: 5000ms, 相机 USB_CAM_1
[2026-07-20 14:31:07.004] [ERROR] [FaultHandler] 达到最大重试次数, 上报故障
[2026-07-20 14:31:07.005] [ERROR] [ResultWrite] 写入 PLC 故障码: 0x1001

常用 grep 分析命令

# 查看所有错误
grep "ERROR" vision_*.log

# 查看某个 Job 的完整执行链
grep "Job #1287" vision_*.log

# 统计各类错误次数
grep -o "error_code: 0x[0-9A-F]*" vision_*.log | sort | uniq -c

# 查看推理延迟
grep "推理完成" vision_*.log

# 查看最近 100 条记录
tail -n 100 vision_*.log

12.5 诊断工具

IDE 诊断面板

诊断面板
────────────────────────────────────────────────
┌─ 系统信息 ───────────────────────────────────┐
│ Vision Studio 版本: 1.0.0 │
│ ONNX Runtime 版本: 1.17.0 │
│ OpenCV 版本: 4.9.0 │
│ CUDA 版本: 11.8 │
│ 可用 GPU: NVIDIA RTX 3060 (12GB) │
└───────────────────────────────────────────────┘
┌─ 相机诊断 ───────────────────────────────────┐
│ USB_CAM_1: ● 连接正常 1280×1024 30fps │
│ GIGE_CAM_1: ● 连接正常 2448×2048 75fps │
│ 带宽使用: 245 MB/s / 350 MB/s (70%) │
└───────────────────────────────────────────────┘
┌─ 模型诊断 ───────────────────────────────────┐
│ surface_defect v3: ● 已部署 GPU 8ms │
│ position_detect v2: ● 已部署 CPU 25ms │
│ 显存使用: 512 MB / 12288 MB (4%) │
└───────────────────────────────────────────────┘
┌─ 性能基准 ───────────────────────────────────┐
│ 当前推理延迟: 8 ms (历史平均: 7.5 ms) │
│ 当前帧率: 30 fps (目标: 30 fps) │
│ Job 成功率: 99.5% (最近 1000 次) │
└───────────────────────────────────────────────┘

性能基准测试

# 运行性能基准测试
工具 → 性能基准 → 视觉推理基准

基准测试结果:
────────────────────────────────────────────────
模型: surface_defect v3
输入尺寸: 640×640
迭代次数: 1000

GPU (CUDA):
平均: 7.8 ms (128 fps)
最小: 7.2 ms (139 fps)
最大: 12.4 ms (80 fps)
P99: 9.5 ms

CPU (OpenCV DNN):
平均: 38.2 ms (26 fps)
最小: 35.1 ms (28 fps)
最大: 45.8 ms (21 fps)
P99: 42.3 ms

12.6 常见错误总结

快速排查表

现象优先级检查项
相机无图像最高驱动、线缆、触发模式、曝光
模型不推理ONNX 版本、输入尺寸、显存
检测不到目标置信度阈值、模型质量
测量不准标定系数、边缘参数、ROI 位置
性能慢推理后端、分辨率、模型大小
PLC 不通信变量名、触发信号、超时设置
结果跳变光源稳定性、边缘强度、滤波
偶发超时并发数、资源分配、系统负载

本教程所有示例均可在 Darra RT IDE 中直接运行。

更多信息请参考: