跳到主要内容

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 (归一化)

参数:

参数类型必填默认值说明
KernelSizeDWORD否5核大小(奇数:3/5/7/9/11)
SigmaXREAL否1.5X 方向标准差
SigmaYREAL否AutoY 方向标准差(=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) 被排除了

参数:

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

应用场景:

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

双边滤波​

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

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

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

参数:

参数类型必填默认值说明
DiameterDWORD否9邻域直径
SigmaColorREAL否75颜色空间标准差
SigmaSpaceREAL否75坐标空间标准差

示例:

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

滤波方法对比​

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

4.2 形态学 (Morphology)​

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

腐蚀 (Erode)​

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

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

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

膨胀 (Dilate)​

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

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

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

开运算 (Open)​

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

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

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

闭运算 (Close)​

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

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

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

形态学参数​

参数类型必填默认值说明
OperationENUM是—Erode/Dilate/Open/Close/Gradient/TopHat/BlackHat
KernelShapeENUM否RectRect/Cross/Ellipse
KernelSizeDWORD否3核大小 (3/5/7/...)
IterationsDWORD否1迭代次数

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)

阈值参数:

参数类型必填默认值说明
ThresholdREAL否128手动阈值
MaxValueREAL否255最大值
TypeENUM否Binary二值化类型
UseOtsuBOOL否FALSE使用 Otsu
AdaptiveMethodENUM否None自适应方法
BlockSizeDWORD否11自适应块大小

二值化类型详解:

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是—区域高度
RelativeBOOL否FALSE相对坐标 (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 模型推理​

参数表:

参数类型必填默认值说明
ModelPathSTRING是—ONNX 模型文件路径
InputWidthDWORD否640模型输入宽度
InputHeightDWORD否640模型输入高度
ConfidenceREAL否0.5置信度阈值
NMSThresholdREAL否0.45NMS 阈值
MaxDetectionsDWORD否256最大检测目标数
LabelsPathSTRING否—标签文件路径
ExecutionProviderENUM否Auto推理后端

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 分析对二值图像中的连通域进行检测和分析。

参数:

参数类型必填默认值说明
MinAreaREAL否100最小面积 (像素)
MaxAreaREAL否100000最大面积 (像素)
MinCircularityREAL否0.0最小圆形度 (0~1)
MinConvexityREAL否0.0最小凸度 (0~1)
MinInertiaRatioREAL否0.0最小惯性比
FilterByColorBOOL否FALSE按颜色过滤
BlobColorDWORD否255目标颜色 (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-连通更容易连接

参数:

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

5.3 模板匹配 (Template Matching)​

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

归一化互相关匹配​

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

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

参数:

参数类型必填默认值说明
TemplatePathSTRING是—模板图像路径
MethodENUM否Normed匹配方法
MinScoreREAL否0.7最低匹配评分
MaxMatchesDWORD否1最大匹配数
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 → 弱边缘(仅连接强边缘时保留)

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

参数:

参数类型必填默认值说明
LowThresholdREAL否50低阈值
HighThresholdREAL否150高阈值
ApertureSizeDWORD否3Sobel 算子大小 (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 结果:
检测垂直边缘 检测水平边缘
┌───┐ ┌───┐
│ │ │ │───│
│ │ │ │───│
│ │ │ └───┘
└───┘

参数:

参数类型必填默认值说明
DxDWORD是1X 方向阶数
DyDWORD是0Y 方向阶数
ApertureSizeDWORD否3核大小

Laplacian 边缘检测​

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

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

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

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

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

参数:

参数类型必填默认值说明
MethodENUM是—特征检测方法
MaxFeaturesDWORD否1000最大特征点数
MatchRatioREAL否0.75Lowe 匹配比率
MinMatchesDWORD否10最少匹配点数

特征匹配方法对比:

方法旋转不变缩放不变光照不变速度适用场景
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. 选择内点最多的圆

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

参数:

参数类型必填默认值说明
MethodENUM否LeastSquaresLeastSquares / RANSAC
RansacThresholdREAL否2.0RANSAC 内点阈值 (像素)
RansacMaxIterDWORD否1000RANSAC 最大迭代次数

6.5 卡尺工具 (Caliper)​

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

卡尺工具的工作原理:

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

参数:

参数类型必填默认值说明
RoiXDWORD是—卡尺 ROI X
RoiYDWORD是—卡尺 ROI Y
RoiWidthDWORD是—卡尺宽度
RoiHeightDWORD是—卡尺高度
EdgeSelectorENUM否Best边缘选择策略
EdgePolarityENUM否Any边缘极性
MinEdgeStrengthREAL否30最小边缘强度
NumEdgesDWORD否2边缘数量

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否全图搜索区域
SymbologyENUM否Auto码类型(Auto=自动检测)
TimeoutDWORD否2000识别超时 (ms)
TryHarderBOOL否FALSE增强识别(降低速度)

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否全图搜索区域
TimeoutDWORD否2000识别超时 (ms)
MicroQRBOOL否FALSE支持 Micro QR

DataMatrix 参数:

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

7.3 字符识别 (OCR)​

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

参数配置​

参数类型必填默认值说明
RoiX/Y/Width/HeightDWORD否全图搜索区域
LanguageSTRING否"eng"识别语言
CharWhitelistSTRING否""白名单字符
PsmModeENUM否Auto页面分割模式
TimeoutDWORD否3000识别超时 (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 模型
ThresholdREAL否0.5异常阈值
OutputHeatmapBOOL否TRUE输出热力图
ExecutionProviderENUM否Auto推理后端

异常检测输出:

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 + 正整数,如 v1、v2、v3

版本操作:

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

版本对比:

surface_defect v2 ↔ v3 对比
────────────────────────────────────────────────
属性 │ v2 │ v3
──────────────┼───────────────┼─────────────────
文件大小 │ 18.2 MB │ 24.3 MB
输入尺寸 │ 640×640 │ 640×640
算子集 │ opset 17 │ opset 19
[email protected] │ 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% │
│ [email protected]: 0.935 │ [email protected]: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 中直接运行。

更多信息请参考: