基于 YOLOv12 的洗衣机外桶装配全自动视觉检测系统:从模型训练到产线落地
一、痛点:人工目检为什么扛不住了
洗衣机外桶装配线涉及三大核心工艺:部件装配(减震器、密封圈、排水阀等 6-12 个组件)、螺钉紧固(8-15 颗自攻螺钉,扭矩精度 ±0.3N·m)、导线整理(电源线、信号线、地线共 4-8 束,走线路径固定)。
传统人工目检的问题:
我们团队为某知名白电企业部署的 YOLOv12 视觉检测系统,上线后过程不良率从 2.8% 降至 0.4%,单工位节拍从 45 秒压缩至 18 秒,以下为完整技术实现路径。
二、技术架构总览
┌─────────────────────────────────────────────────────────────┐
│ 产线边缘计算节点 │
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 工业相机 │→│ 图像采集卡 │→│ YOLOv12 │→│ 判定引擎 │ │
│ │ Hikrobot │ │ PCIe x4 │ │ ONNX FP16 │ │ C++ │ │
│ │ 500万像素 │ │ │ │ TensorRT │ │ │ │
│ └──────────┘ └──────────┘ └───────────┘ └───────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ 合格 → 放行 │ │
│ │ 不合格 → 报警 │ │
│ │ + 自动拍照存档│ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ MES / 数据库 │ │ 看板大屏 / 追溯 │
│ PostgreSQL │ │ Grafana │
│ 时序 + 关系型 │ │ 实时缺陷热力图 │
└─────────────────┘ └──────────────────┘
三、检测任务定义:五个模型,各司其职
外桶装配不是一个模型打天下,我们拆解为 5 个独立检测模型 + 1 个型号匹配模块:
型号匹配模块:通过扫描内桶上的激光打码/二维码,从工艺参数数据库中调取当前型号的标准走线路径、螺钉数量和位置定义,自动切换检测逻辑,支持 12 种内桶型号混线生产。
四、数据集构建:最容易被低估的环节
4.1 图像采集
4.2 标注规范
使用 LabelStudio(v1.13)进行标注,关键规则:
# 螺钉标注
类别名: screw_present / screw_missing / screw_float
标注框: 螺钉头部外接矩形 + 5px 外扩
十字槽关键点: 槽中心 1 点 + 槽两端各 1 点(共 3 点)
# 导线标注
类别名: wire_correct / wire_deviated / wire_pinched
标注方式: 多边形分段标注,线宽 3-5px
# 部件标注
类别名: {component_name}_present / {component_name}_missing
标注框: 部件外轮廓,容忍 ±3px
4.3 数据增强策略
YOLOv12 训练管线中,线下增强 + 在线增强双管齐下:
# 线下增强(Albumentations,生成 10x 变体)
import albumentations as A
pipeline = A.Compose([
A.RandomBrightnessContrast(brightness_limit=0.15, contrast_limit=0.15, p=0.7),
A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=20, p=0.5),
A.GaussNoise(var_limit=(5.0, 25.0), p=0.4),
A.MotionBlur(blur_limit=5, p=0.2), # 模拟产线振动
A.CLAHE(clip_limit=2.0, p=0.3),
A.ShiftScaleRotate(shift_limit=0.02, scale_limit=0.05, rotate_limit=3, p=0.5),
], bbox_params=A.BboxParams(format='yolo', label_fields=['class_labels']))
# 在线增强(YOLOv12 data.yaml)
mosaic: 1.0 # 4 图拼接,提升小目标检测
mixup: 0.1 # 混合样本,防过拟合
copy_paste: 0.15 # 复制螺钉到随机位置,解决正负样本不均衡
hsv_h: 0.01 # 工业场景色调变化不宜过大
hsv_s: 0.3
hsv_v: 0.2
degrees: 2.0 # 螺钉方向关键,旋转角度限制在 ±2°
五、YOLOv12 模型训练:完整参数与调优路径
5.1 为什么选 YOLOv12
核心差异:YOLOv12 的 A2C2f(Area Attention C2f)模块,对空间位置固定的工业检测场景有天然优势——外桶每次在相同工位、相同角度拍照,螺钉和走线路径的空间分布是有规律的,区域注意力比全局 self-attention 更高效。
5.2 训练环境
硬件: NVIDIA RTX 4090 24GB × 1(训练)/ NVIDIA Jetson Orin AGX 64GB(部署)
框架: PyTorch 2.4.0 + CUDA 12.4 + cuDNN 9.1
工具链: ultralytics 8.3.x(原生支持 YOLOv12)
标注格式: YOLO 格式(class_id cx cy w h),归一化坐标
5.3 训练超参数
# 螺钉检测模型 M1 训练配置
model: yolov12n.pt # 从 nano 预训练权重开始,部署到 Jetson
epochs: 300 # 小目标检测需充分训练
batch: 32 # 4090 24G 上限
imgsz: 1280 # 高分辨率,螺钉仅 30-50px 需要大图
optimizer: AdamW # 比 SGD 在 YOLOv12 上收敛更快
lr0: 0.001 # 初始学习率
lrf: 0.01 # 最终学习率因子 = lr0 × lrf = 1e-5
momentum: 0.937
weight_decay: 0.0005
warmup_epochs: 3
warmup_momentum: 0.8
warmup_bias_lr: 0.1
# 损失函数权重
box: 7.5 # 边界框回归损失(螺钉定位要求高)
cls: 0.5 # 分类损失(类别少,权重降低)
dfl: 1.5 # 分布焦点损失
pose: 12.0 # 关键点损失(仅 M2 螺钉方向模型)
# 关键
close_mosaic: 15 # 最后 15 个 epoch 关闭 mosaic 增强
scale: 0.5 # 缩放系数不宜过大,工业场景尺度变化小
5.4 训练过程与指标
数据集划分: 训练集 7,200 张 / 验证集 1,600 张 / 测试集 1,200 张(按日期分层)
总标注框: 螺钉类 58,000+ / 导线类 12,000+ / 部件类 35,000+
训练时长: 约 6.5 小时(4090, 300 epochs)
收敛曲线:
- mAP@0.5: 0.962(epoch 280 达到最优)
- mAP@0.5:0.95: 0.841
- Precision: 0.953
- Recall: 0.968
- F1-score: 0.960
六、模型部署:从 PyTorch 到产线边缘计算
6.1 模型导出链路
# Step 1: PyTorch → ONNX(FP32)
yolo export model=runs/train/screw_m1/weights/best.pt \
format=onnx imgsz=1280 opset=17 simplify dynamic
# Step 2: ONNX → TensorRT Engine(FP16)
trtexec --onnx=screw_m1.onnx \
--saveEngine=screw_m1_fp16.engine \
--fp16 \
--workspace=4096 \
--optShapes=images:1x3x1280x1280
# 推理速度验证
# PyTorch FP32: 8.7ms
# ONNX FP32: 6.3ms
# TensorRT FP16: 1.2ms ← 部署版本
6.2 C++ 推理引擎(核心代码片段)
// 推理管线:图像采集 → 预处理 → 推理 → 后处理 → 判定 → 存储
class ScrewDetector {
public:
ScrewDetector(const std::string& engine_path, const std::string& config_yaml) {
// 1. 加载 TensorRT Engine
runtime_ = nvinfer1::createInferRuntime(gLogger);
engine_ = runtime_->deserializeCudaEngine(engine_data, size);
context_ = engine_->createExecutionContext();
// 2. 加载当前型号的螺钉位置定义
loadModelConfig(config_yaml); // 不同内桶型号对应不同螺钉数量/位置
}
DetectionResult detect(const cv::Mat& frame, const std::string& model_id) {
// 3. 预处理:BGR→RGB, 归一化, resize 1280, GPU upload
preprocess(frame, input_buffer_);
// 4. TensorRT 推理
context_->executeV2(buffers_.data());
// 5. NMS 后处理,置信度阈值 0.35
auto detections = postprocess(output_buffer_, 0.35f, 0.45f);
// 6. 与当前型号标准比对(关键!不同内桶螺钉数不同)
auto result = matchWithStandard(detections, model_id);
// 7. 不合格:触发 PLC 报警 + 存档
if (!result.passed) {
triggerAlarm(result.defect_type, result.defect_location);
archiveImage(frame, result); // 保存到 NAS + 写入 PostgreSQL
}
return result;
}
private:
// ... TensorRT 上下文、CUDA 流、预处理/后处理、型号匹配逻辑
};
6.3 推理性能
七、数据存储与追溯系统
7.1 数据库设计
-- PostgreSQL 核心表结构
CREATE TABLE inspection_records (
id BIGSERIAL PRIMARY KEY,
serial_number VARCHAR(32) NOT NULL, -- 产品序列号
model_id VARCHAR(16) NOT NULL, -- 内桶型号
station_id SMALLINT NOT NULL, -- 工位编号
camera_id SMALLINT NOT NULL, -- 相机编号
timestamp TIMESTAMPTZ DEFAULT NOW(), -- 检测时间
result BOOLEAN NOT NULL, -- 合格/不合格
defect_type VARCHAR(64), -- 缺陷类型
defect_score REAL, -- 缺陷置信度
image_path VARCHAR(256), -- 存档图片路径(NAS)
inference_ms REAL, -- 推理耗时
model_version VARCHAR(32) -- 模型版本号
);
CREATE INDEX idx_serial ON inspection_records(serial_number);
CREATE INDEX idx_timestamp ON inspection_records(timestamp);
CREATE INDEX idx_defect ON inspection_records(defect_type) WHERE result = FALSE;
7.2 追溯看板
采用 Grafana + PostgreSQL 实时展示:
八、落地效果:数字说话
九、关键踩坑与经验
1. 螺钉反光是最大敌人
工业环境环形光源下,镀锌螺钉的镜面反光导致十字槽特征消失。解决方案:低角度条光 + 偏振片组合,采样时在 6 种光照强度下拍摄(模拟车间清晨到傍晚的光线变化),模型对光照鲁棒性从 0.72 提升至 0.94。
2. 型号匹配不能靠模型,要靠系统
早期尝试让 YOLOv12 同时检测螺钉并判断"这个型号应该有几颗"——准确率只有 76%。根本原因是:螺钉数量是工艺标准,不是视觉特征。正确做法:扫码 → 查数据库 → 拿来比对检测结果,不要试图让模型"猜"工艺规范。
3. 离线增强做不够,在线增强也要调
Mosaic 增强在大图 + 小目标场景会产生过多不完整零件,导致模型对"部件被遮挡"过度敏感。将 mosaic 从默认 1.0 降低至 0.6,并在最后 15 个 epoch 关闭(close_mosaic=15),mAP 提升了 2.1 个百分点。
4. Jetson Orin 上的 FP16 精度损失在可接受范围
TensorRT FP16 精度下 mAP@0.5 从 0.962 降至 0.957,仅损失 0.5%,但推理速度从 18.7ms 降至 6.8ms(提速 2.75×),完全值得。
十、结语
从选型到落地,这个项目的完整技术栈是:LabelStudio 标注 → Albumentations 增强 → PyTorch 训练 YOLOv12 → ONNX 导出 → TensorRT FP16 部署 → C++ 推理引擎 → PostgreSQL 存储 → Grafana 看板 → PLC 产线联动。
不是炫技——每一层工具的选型背后都是一个具体的产线约束:光照波动、型号混产、节拍要求、追溯合规。工业 AI 的核心不是模型多先进,而是有多少工程细节被考虑进去了。
本文由 青岛碳足迹智能科技有限公司 AI 视觉团队撰写。我们专注工业视觉检测与 AI 系统集成,为企业提供从数据标注、模型训练到产线部署的全链路解决方案。技术咨询与合作:www.668ai.cn