机器视觉完整指南

前言

机器视觉(Machine Vision)是人工智能领域的重要分支,让机器能够”看懂”世界。从工厂流水线的缺陷检测到自动驾驶的环境感知,机器视觉技术正在深刻改变各行各业。本文将系统讲解机器视觉的核心概念、关键技术栈和实战应用。

1. 机器视觉 vs 计算机视觉

很多人容易混淆这两个概念:

对比维度 计算机视觉(CV) 机器视觉(MV)
目标 让机器理解图像/视频的语义内容 解决具体的工业检测与控制问题
应用场景 互联网内容理解、自动驾驶、医疗影像 工业质检、自动化分拣、精密装配
侧重点 通用算法、深度学习模型 硬件集成、光学系统、实时性要求
系统构成 纯软件算法为主 相机+镜头+光源+算法软件一体化
标准规范 无统一标准 遵循 GigE Vision、USB3 Vision 等工业标准

简单理解:机器视觉是计算机视觉在工业领域的具体落地,强调的是可靠性和实时性。

2. 机器视觉系统组成

一个完整的机器视觉系统包括:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────────────────────────────────────────────────────┐
│ 机器视觉系统架构 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 光源 │ → │ 镜头 │ → │ 相机 │ → 图像采集 │
│ │ Lighting│ │ Lens │ │ Camera │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ ↓ │
│ ┌─────────────┐ │
│ │ 图像处理 │ │
│ │ 单元 │ │
│ └─────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 核心算法层 │ │
│ │ 图像预处理 → 特征提取 → 目标检测/分割 → 后处理 │ │
│ └─────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────┐ │
│ │ 结果输出 │ │
│ │ 控制指令 │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────┘

2.1 硬件选型

工业相机类型:

类型 分辨率 速度 成本 适用场景
面阵相机 尺寸测量、缺陷检测
线阵相机 极高 极快 连续材料检测(PCB、薄膜)
3D相机 体积测量、机器人引导

镜头选型关键参数:

  • 焦距:决定视野范围和工作距离
  • 光圈:影响景深和进光量
  • 靶面尺寸:需与传感器尺寸匹配
  • 接口类型:C口、CS口、F口等

光源类型:

光源 色温/颜色 特点 典型应用
环形光源 白色 均匀照明,减少阴影 电子元件检测
同轴光源 白色 消除反光 镜面物体检测
背光源 白色/红色 轮廓清晰 尺寸测量
条形光源 可调 灵活角度 曲面检测

2.2 软件算法栈

传统图像处理算法:

1
图像预处理 → 图像增强 → 特征提取 → 模板匹配/边缘检测 → 形态学操作 → 测量输出

核心算法包括:

  • 滤波去噪:高斯滤波、中值滤波、双边滤波
  • 边缘检测:Canny、Sobel、Laplacian
  • 形态学:腐蚀、膨胀、开运算、闭运算
  • 特征描述:SIFT、SURF、ORB、Harris角点
  • 模板匹配:基于灰度、基于形状

深度学习算法:

任务类型 经典模型 适用场景
图像分类 ResNet、EfficientNet、VGG 产品分类、质量分级
目标检测 YOLO、Faster R-CNN、SSD 缺陷定位、多目标计数
语义分割 U-Net、Mask R-CNN、DeepLab 像素级缺陷分割
实例分割 YOLACT、BlendMask 粘连物体分离
目标跟踪 ByteTrack、DeepSORT 流水线动态检测

3. 核心算法详解

3.1 图像预处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np

def preprocess_image(image):
"""机器视觉常用预处理流程"""
# 1. 去噪 - 双边滤波保留边缘去噪声
denoised = cv2.bilateralFilter(image, 9, 75, 75)

# 2. 灰度转换
gray = cv2.cvtColor(denoised, cv2.COLOR_BGR2GRAY)

# 3. 对比度增强 - CLAHE
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
enhanced = clahe.apply(gray)

# 4. 边缘增强
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpened = cv2.filter2D(enhanced, -1, kernel)

return sharpened

3.2 缺陷检测实战 - 基于面积和圆形度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def detect_defects(image):
"""
工业零件缺陷检测:检测气泡、划痕、缺损
"""
# 预处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)

# 二值化 - Otsu自动阈值
_, binary = cv2.threshold(blurred, 0, 255,
cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 形态学操作去噪
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
cleaned = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)

# 连通域分析
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(cleaned)

defects = []
for i in range(1, num_labels): # 跳过背景
area = stats[i, cv2.CC_STAT_AREA]

# 过滤太小或太大的区域(非缺陷)
if area < 50 or area > 5000:
continue

# 计算圆形度:4π×面积 / 周长²
# 圆形度接近1表示接近圆形,缺陷通常不规则
contours, _ = cv2.findContours(cleaned, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
perimeter = cv2.arcLength(cnt, True)
if perimeter > 0:
circularity = 4 * np.pi * area / (perimeter ** 2)
if circularity < 0.5: # 非圆形,可能是缺陷
x, y, w, h = cv2.boundingRect(cnt)
defects.append({
'bbox': (x, y, w, h),
'area': area,
'circularity': circularity
})

return defects

3.3 深度学习目标检测 - YOLOv8实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from ultralytics import YOLO

def detect_products(image_path, model_path='yolov8n.pt'):
"""YOLOv8工业零件检测"""
model = YOLO(model_path)

# 推理
results = model.predict(
source=image_path,
conf=0.5, # 置信度阈值
iou=0.45, # NMS交并比阈值
max_det=100, # 最大检测数
device='cuda' # GPU加速
)

# 解析结果
detections = []
for result in results:
boxes = result.boxes
for box in boxes:
x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()
conf = box.conf[0].cpu().numpy()
cls_id = int(box.cls[0])
cls_name = model.names[cls_id]

detections.append({
'class': cls_name,
'confidence': float(conf),
'bbox': [int(x1), int(y1), int(x2), int(y2)]
})

return detections

4. 实战项目:PCB板缺陷检测

4.1 项目需求

检测PCB板上的常见缺陷:

  • 缺胶:焊点处胶水不足
  • 气泡:胶水中的气泡
  • 溢胶:胶水溢出指定区域
  • 偏移:元器件位置偏移

4.2 数据集构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import os
from pathlib import Path

def build_dataset():
"""
构建PCB缺陷数据集
目录结构:
dataset/
├── images/
│ ├── train/
│ └── val/
└── labels/
├── train/
└── val/
"""
base_dir = Path('dataset')

# 缺陷类别映射
class_mapping = {
0: 'missing_glue', # 缺胶
1: 'bubble', # 气泡
2: 'overflow', # 溢胶
3: 'shift' # 偏移
}

return base_dir, class_mapping

4.3 模型训练配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# pcb_defect_detection.yaml
model: yolov8m.pt
data: pcb_defect.yaml
epochs: 100
imgsz: 640
batch: 16
device: 0

# 数据增强
augmentation:
hsv_h: 0.015 # 色调变化
hsv_s: 0.7 # 饱和度变化
hsv_v: 0.4 # 亮度变化
degrees: 5 # 旋转角度
translate: 0.1 # 平移
scale: 0.5 # 缩放
flipud: 0.0 # 上下翻转
fliplr: 0.5 # 左右翻转
mosaic: 1.0 # 马赛克增强

# 优化器配置
optimizer: AdamW
lr0: 0.001
lrf: 0.01
momentum: 0.937
weight_decay: 0.0005

4.4 完整训练流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from ultralytics import YOLO
import torch

def train_pcb_detector():
"""PCB缺陷检测模型训练"""
# 加载预训练模型
model = YOLO('yolov8m.pt')

# 设置设备
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"使用设备: {device}")

# 开始训练
results = model.train(
data='pcb_defect.yaml',
epochs=100,
imgsz=640,
batch=16,
device=device,
project='runs/pcb_detection',
name='exp',
exist_ok=True,
save=True,
save_period=10,

# 早停
patience=20,

# 学习率策略
lr0=0.001,
lrf=0.01,

# 数据增强
augmentation=True,
mosaic=1.0,
mixup=0.1,
)

# 验证集评估
metrics = model.val(data='pcb_defect.yaml')
print(f"mAP50: {metrics.box.map50:.4f}")
print(f"mAP50-95: {metrics.box.map:.4f}")

# 导出模型
model.export(format='onnx', opset=12)

return model

4.5 部署推理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import cv2
from ultralytics import YOLO
import numpy as np

class PCBDefectDetector:
"""PCB缺陷检测推理类"""

def __init__(self, model_path='best.pt'):
self.model = YOLO(model_path)
self.class_names = ['missing_glue', 'bubble', 'overflow', 'shift']

def detect(self, image_path):
"""执行缺陷检测"""
results = self.model.predict(
source=image_path,
conf=0.5,
iou=0.45,
verbose=False
)

defects = []
for result in results:
boxes = result.boxes
for box in boxes:
x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()
conf = float(box.conf[0])
cls_id = int(box.cls[0])

defects.append({
'type': self.class_names[cls_id],
'confidence': conf,
'bbox': [int(x1), int(y1), int(x2), int(y2)],
'severity': 'high' if conf > 0.8 else 'medium'
})

return defects

def visualize(self, image_path, defects, output_path='result.jpg'):
"""可视化检测结果"""
img = cv2.imread(image_path)

color_map = {
'missing_glue': (0, 0, 255), # 红色
'bubble': (0, 255, 0), # 绿色
'overflow': (255, 0, 0), # 蓝色
'shift': (0, 255, 255) # 黄色
}

for defect in defects:
x1, y1, x2, y2 = defect['bbox']
color = color_map[defect['type']]

# 画框
cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)

# 画标签
label = f"{defect['type']}: {defect['confidence']:.2f}"
cv2.putText(img, label, (x1, y1-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)

cv2.imwrite(output_path, img)
return img

# 使用示例
detector = PCBDefectDetector('runs/pcb_detection/exp/weights/best.pt')
defects = detector.detect('test_images/pcb_001.jpg')
detector.visualize('test_images/pcb_001.jpg', defects)
print(f"检测到 {len(defects)} 个缺陷")

5. 常见问题与解决方案

问题 原因 解决方案
检测精度低 数据集不足/质量差 扩充数据集,增加难例样本
误检率高 背景干扰/光照变化 固定光源,增加数据增强
速度慢 模型过大/分辨率过高 模型量化,剪枝,降低输入分辨率
重复检测 NMS阈值过低 适当提高NMS的IoU阈值
漏检 缺陷对比度低/过小 图像增强,突出缺陷特征

6. 工具与框架推荐

工业视觉软件平台:

  • Halcon:工业级视觉算法库,功能强大
  • VisionPro (Cognex):工业视觉软件龙头
  • LabVIEW Vision:图形化视觉开发
  • OpenVINO:Intel的深度学习推理优化工具

开源框架:

  • OpenCV:基础图像处理
  • OpenMMLab:目标检测、分割等SOTA算法集合
  • Ultralytics YOLO:YOLO系列模型快速训练部署
  • LibreElectronics/OpenMV:嵌入式机器视觉

数据集:

7. 总结与展望

机器视觉技术正在从传统的规则-based方法向深度学习方法快速演进:

  • 现状:深度学习在目标检测、语义分割等任务上已超越传统方法
  • 趋势:小样本学习、自监督学习、3D视觉成为研究热点
  • 挑战:数据标注成本、实时性要求、跨场景泛化能力

随着制造升级的加速,机器视觉在质量检测、自动化控制领域的应用将越来越广泛。掌握机器视觉技术,将成为工程师的重要竞争力。


延伸阅读: