从零实现电路板大元件缺失检测:小批量多品种场景下的深度学习与透视校正实战
一、引言
在电子产品生产线上,电路板元件的缺失检测是一个常见需求。然而,对于小批量、多品种的生产模式,传统方法面临诸多挑战:
没有CAD文件,无法获得元件精确坐标;
不同品种电路板布局差异大,难以用固定模板;
拍摄角度、光照、方向不一致,导致传统图像配准失败;
产线要求快速部署,无法为每个品种收集大量标注数据。
本文记录了我从零开始,结合YOLO目标检测、透视变换与GUI开发,最终实现了一套稳定的电路板大元件缺失检测系统。整个过程充满试错与优化,希望为遇到类似问题的读者提供参考。
二、问题定义与约束
检测目标:电路板上的指定大元件(插座、电感、大电容、屏蔽罩、支架IC等),只关心是否存在,不区分具体类型。
生产特点:小批量多品种,每个品种产量少,无法为每个品种单独训练模型。
图像采集:摄像头拍照,电路板摆放方向可能有0°、90°、180°变化,且有±15°小角度偏差;光照、对比度会不一致有差别。
数据情况:初始只有31张图,后扩充至81张,再增加至115张,包含三个电路板品种。
标注成本:希望最小化标注工作量。
三、技术路线探索与迭代
3.1 尝试一:纯YOLO目标检测(区分元件类型)
最初我们使用YOLOv8n训练一个多类别检测模型,识别插座、电感、电容等5类元件。但遇到两个痛点:
斜向标注引入背景噪声:当电路板旋转45°时,用水平矩形框住斜向元件会包含大量背景,模型学到的是“元件+背景”的混合特征,导致在正常角度下误检。
小样本过拟合:早期只有31张图,模型在训练集上mAP很高(0.995),但对新图片泛化差,白色插座经常漏检。
3.2 尝试二:模板匹配 + 差异检测
我们尝试将标准模板与待检图进行配准,然后逐像素比较ROI区域。但电路板旋转、缩放、透视变形导致SIFT/ORB特征匹配失败,即使加入RANSAC也无法稳定对齐。结论:传统配准对光照和角度变化过于敏感,不适合产线环境。
3.3 尝试三:深度学习 + 透视校正(最终方案)
核心思路:不改变检测图像,只将模板ROI通过单应性矩阵映射到检测图像坐标系,然后与全局元件检测结果比对。这样既利用了深度学习的鲁棒性,又避免了对图像进行几何变换导致的精度损失。
整体流程:
使用YOLOv8训练两个模型:
PCB检测模型:定位图像中所有电路板的矩形框(单类别
pcb)。元件检测模型:检测所有元件(单类别
component)。
对每一块电路板:
裁剪该板区域(外扩30像素)用于计算单应性矩阵。
使用ORB特征 + RANSAC计算从模板电路板到该裁剪区域的单应性矩阵
H。将模板上预定义的ROI(感兴趣区域)通过
H变换到裁剪区域坐标系,再转换回原图坐标。检查全局元件检测框中是否有中心点落在扩展后的ROI内,否则判定为缺失。
多电路板处理:对每个检测到的PCB独立执行上述步骤。
可视化:在原图上绘制电路板框(彩色)、映射后的ROI(蓝色)、元件检测框(黄色),并输出缺失报告。
四、关键技术细节
4.1 数据标注与模型训练
统一为单类别
component:将所有需要检测的元件(插座、电感、电容、屏蔽罩等)标注为同一类,避免类别不平衡和特征混淆。数据增强:对小样本数据进行离线增强(亮度、对比度、小角度旋转、高斯噪声),扩充训练集。
训练参数:使用
yolov8n.pt预训练权重,输入尺寸640×640,学习率0.01,训练150轮,开启早停。
4.2 单应性矩阵计算(关键)
python
def compute_homography(template_board, detected_patch): # 灰度化 + CLAHE增强对比度 gray_t = cv2.cvtColor(template_board, cv2.COLOR_BGR2GRAY) gray_p = cv2.cvtColor(detected_patch, cv2.COLOR_BGR2GRAY) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) gray_t = clahe.apply(gray_t) gray_p = clahe.apply(gray_p) # ORB特征提取与匹配 orb = cv2.ORB_create(nfeatures=2000) kp1, des1 = orb.detectAndCompute(gray_t, None) kp2, des2 = orb.detectAndCompute(gray_p, None) bf = cv2.BFMatcher(cv2.NORM_HAMMING) matches = bf.knnMatch(des1, des2, k=2) good = [m for m, n in matches if m.distance < 0.75 * n.distance] if len(good) < 10: return None src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2) H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) return H
注意:src_pts是模板图像点,dst_pts是检测图像点,因此H满足:检测图像点 = H * 模板图像点。映射ROI时直接使用H,不要取逆。
4.3 畸变检查与降级
当透视变换导致面积畸变过大时,自动降级为相似变换:
python
# 检查畸变程度 pts = np.float32([[0,0], [w_p,0], [0,h_p]]).reshape(-1,1,2) transformed = cv2.perspectiveTransform(pts, H) area_orig = w_p * h_p area_trans = cv2.contourArea(transformed) ratio = area_trans / area_orig if ratio < 0.3 or ratio > 3.0: H = try_affine_transform(template_board, patch) # 备用相似变换
4.4 多电路板处理与结果可视化
对每个PCB板独立计算变换矩阵和ROI映射。
将所有板的ROI扩展10像素后,只绘制中心点落在这些扩展区域内的元件检测框,过滤背景误检。
最终图像垂直拼接或直接在原图上叠加标注。
五、GUI工具开发
基于PyQt5开发了图形界面,集成模型加载、图像选择、参数调节、结果显示等功能。
主要功能:
加载模板图像和ROI配置文件(JSON格式,包含
board_rect和rois)。加载PCB检测模型和元件检测模型。
选择待检测图像,一键运行检测。
显示检测日志、结果图像(彩色PCB框、蓝色ROI、黄色元件框)和缺失报告。
六、效果与总结
6.1 最终效果
对115张训练图(含多方向、多光照)训练后,模型在验证集上mAP50达到0.945。
能够稳定检测0°、90°、180°方向的电路板,对±15°小角度偏差具有鲁棒性。
多电路板同时检测准确,ROI映射偏差控制在10像素以内。
误检主要来自反光强烈的区域,可通过增加负样本进一步优化。
6.2 经验教训
标注统一为单类别:在缺失检测场景下,区分元件类型不是必需的,单类别能极大简化问题。
不要变换检测图像:透视校正应作用于ROI坐标,而非图像本身,避免缩放损失。
数据多样性 > 数据量:多角度、多光照的31张图比单一角度的200张图更有价值。
为每个品种保存模板ROI:小批量多品种下,手工标注模板ROI(一次性)比训练泛化模型更高效。
6.3 环境依赖
bash
pip install PyQt5 opencv-python numpy ultralytics torch torchvision
建议使用Python 3.9~3.11,独立虚拟环境。
七、展望
当前系统已满足产线初步使用,未来可扩展方向:
增加反光区域的负样本训练,降低误检。
支持任意角度的透视校正(如45°),需引入更多样本或使用深度学习配准。
将检测结果对接MES系统,实现数据追溯。
后记:整个项目从最初尝试模板匹配到最终落地,经历了约2个月的迭代。最大的感悟是:工业视觉没有银弹,需要根据数据特点和产线约束灵活选择方案。希望本文能帮助读者少走弯路。
源码与ROI标注工具:可私信获取(附详细注释)。
