基于计算机视觉的焊点缺陷检测系统设计与实现指南
发布时间:2026/9/30 10:15:42来源:尧图网络
简介《基于计算机视觉的焊点缺陷检测系统设计》是一篇面向机器视觉、图像处理与工业质检领域的学术论文适合从事焊接缺陷自动检测研究的工程师、科研人员及高校学生参考。针对点焊生产线上虚焊、漏焊、焊穿等常见缺陷论文设计了完整的图像处理检测流程先平滑去噪再用Otsu自适应阈值分割随后做倒三角距离变换强化焊点特征并以分水岭算法分离重叠或异常焊点最终依据面积等特征对缺陷分类。实验表明该方法能有效检测多种排列的焊点效率与准确性均优于传统模板匹配和人工目检。资源为单个PDF文件共1个文件总计308KB内容涵盖论文全文、图表、实验数据及参考文献适合用作算法设计参考、课题研究起点或课程论文素材。目前已有209人学习下载。1. 基于计算机视觉的焊点缺陷检测系统设计到底在解决什么问题产线上焊点缺陷判定大多靠老师傅人眼加放大镜换班后标准就漂。基于计算机视觉的焊点缺陷检测系统设计就是把这套经验固化成相机、光源、算法和判定逻辑组成的自动流程解决虚焊、桥连、少锡、漏焊这几类最常见缺陷的漏检和误判。这套系统设计的难点不在深度学习而在成像稳定性、焊点定位精度和判定阈值。前两个做不好换个批次产品检测精度就崩。它适合正在做机器视觉类毕业设计的学生也适合想给小批量产线加自动检测的工艺工程师。下文按系统设计、最小可跑代码、深度学习补充、落地排错、验证收尾展开。核心顺序是先把同一个焊点在不同光照下稳定找到再谈缺陷分类顺序反了后面全是坑。2. 焊点缺陷检测系统的总体设计思路从检测目标、相机选型到检测流程2.1 焊点缺陷检测到底要检什么写系统设计文档的第一步是把“缺陷”这个词拆成可计算的视觉特征。焊点缺陷按成像表现可以分成两大类一类是几何形状缺陷另一类是表面灰度缺陷。几何形状缺陷包括桥连、少锡、锡珠、漏焊这类缺陷在图像上有清晰的轮廓变化适合用传统图像处理解决表面灰度缺陷主要是虚焊和冷焊表现为焊点表面反光能力下降图像上偏暗、纹理粗糙单靠阈值很难稳定区分。缺陷类型成像表现可提取的特征传统视觉可行性桥连相邻焊点之间出现连锡连通区域异常大焊点间距、连通域面积、外接圆半径高少锡焊点面积比良品基准小边缘不饱满轮廓面积、圆弧度、暗区占比高锡珠主焊点附近出现独立小圆点小面积连通域、圆形度高漏焊焊盘上几乎没有焊料露出基板ROI内灰度均值、焊盘区域占比高虚焊表面发暗、反光弱、纹理粗糙灰度均值、灰度方差、暗区比例一般冷焊焊点表面氧化发暗边界不连续灰度均值、边缘强度一般这张表的作用是确定算法边界。几何类缺陷可以写成“面积大于多少就报NG”而虚焊类缺陷是连续量没有明确边界。我在实际方案里通常把虚焊和冷焊单独拎出来留给深度学习做二阶段复核前端传统视觉只负责几何缺陷和区域定位。这样系统设计文档里的检测项清晰答辩时也容易解释哪些缺陷是明确可判据的哪些需要模型概率输出。2.2 硬件与成像方案选型先定光源再定算法焊点检测系统里最容易翻车的是成像环节。焊点表面是镜面反射直射光会在图像中心形成一片亮斑把缺陷细节全部吃掉。常见的做法是用低角度环形光或带漫射板的同轴光让光线从侧面入射焊点轮廓形成暗场缺陷就会表现为灰阶断裂。光源的角度、高度和亮度一旦确定就要用支架锁死不要每班去调。相机选型主要看分辨率和帧率。焊点检测属于静态或半静态应用帧率要求不高但分辨率直接决定小缺陷能不能被看见。像素精度的估算公式是像素精度等于视野尺寸除以传感器分辨率。例如视野为30mm×30mm使用500万像素相机2448×2048像素精度约12μm/pixel一个0.3mm的桥连在图像上约有25个像素足够检测。如果视野换成60mm×60mm同样相机像素精度变成24μm/pixel0.2mm锡珠就只剩下约8个像素这时候就要考虑换更高分辨率相机或者分区域拍摄。镜头建议选定焦FA镜头光圈设在f/8左右景深可以覆盖焊点的高度差。快门和增益固定不要开自动曝光。自动曝光会把光源波动“掩盖”成灰度不变但缺陷的对比度同时也会被抹平这对后续阈值分割是灾难。2.3 检测流程与软件架构一条能解释清楚的数据链路软件架构按“采集、定位、分割、特征、判定、输出”来组织。采集模块控制相机触发和光源定位模块负责找到每个焊点的中心和半径分割模块在焊点ROI内提取缺陷区域特征模块计算面积、灰度、方差、圆形度等指标判定模块把特征映射成缺陷类型输出模块保存NG图像并记录坐标。整个系统设计成两段式传统视觉做第一段负责焊点定位和几何缺陷深度学习做第二段只接收第一段送来的困难样本。原因很实际传统视觉可解释性强出问题改一个阈值就能验证深度学习模型一换参数就要重训练不适合在产线上反复试错。先跑通传统视觉基线统计哪些样本分错再决定要不要加深度学习这是最省时间的推进方式。3. 用 OpenCV 在本地跑通最小焊点检测系统定位、分割与缺陷判定3.1 焊点定位与ROI提取的代码实现先写一个不依赖任何第三方深度学习库的最小系统用OpenCV完成焊点定位。输入是一张灰度图输出是所有焊点的中心坐标和半径。import cv2 import numpy as np def detect_solder_joints(gray, search_roiNone): # 如果传入固定ROI只在该区域内找焊点减少丝印和油污干扰 if search_roi is not None: x, y, w, h search_roi work_img gray[y:yh, x:xw].copy() else: x, y 0, 0 work_img gray.copy() # 焊盘和焊点通常比基板亮用OTSU自动阈值把前景分离出来 _, thresh cv2.threshold(work_img, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 闭运算填平焊点内部的反光暗纹让轮廓更完整 kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) thresh cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations2) # 找外轮廓按面积过滤掉小噪声和大型基板区域 contours, _ cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) joints [] for c in contours: area cv2.contourArea(c) if area 200 or area 50000: continue (cx, cy), radius cv2.minEnclosingCircle(c) joints.append((round(cx x, 1), round(cy y, 1), round(radius, 1))) return joints这段代码的关键点是OTSU阈值、闭运算和面积过滤。不要用固定阈值比如“灰度大于180”因为光源亮度稍有变化固定阈值就会把良品焊点切掉一部分。OTSU会根据当前图像的灰度分布自动找分界点稳定性高很多。闭运算的核大小用5×5椭圆iterations设为2能填补焊点内部的暗纹。面积范围200到50000要根据分辨率和视野调整在12μm/pixel下一个直径1mm的焊点面积约为5500像素下限200可以滤掉细小灰尘上限50000可以滤掉大块基板区域。3.2 焊点内部缺陷区域的分割别让反光骗了算法焊点内部缺陷分割是整条链路上最容易出问题的一步。镜面反射会让焊点中心产生高亮饱和区如果不做处理直接二值化会把高亮区当成正常焊点暗色的虚焊区域混在周围阴影里。我的做法是先对ROI做高斯模糊然后用OTSU提取焊点范围再在焊点范围内找低于正常亮度的暗区。def extract_dark_defect(roi_gray, brightness_ref180): # 先模糊压低传感器噪声避免单个坏点形成虚假缺陷 blur cv2.GaussianBlur(roi_gray, (5, 5), 0) # 正常焊点灰度集中在brightness_ref附近暗区低于这个值减40 dark_mask cv2.inRange(blur, 0, brightness_ref - 40) # 限定在焊点范围内基板本身也是暗的不能当作缺陷 _, roi_mask cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) dark_mask cv2.bitwise_and(dark_mask, roi_mask) # 开运算去掉零星小点核不要超过3x3 kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) dark_mask cv2.morphologyEx(dark_mask, cv2.MORPH_OPEN, kernel) return dark_mask这里的brightness_ref是良品焊点的灰度均值需要在现场用十个以上良品样本实测后取平均。bias取40是一个保守值光源稳定时可以缩到30光源波动大时必须放到50。开运算核为什么不能大因为一个0.2mm的锡珠在12μm/pixel下只有约17像素直径3×3开运算勉强保留5×5以上就会把它当噪声滤掉这一步是很多小缺陷漏检的根源。3.3 缺陷特征计算与判定逻辑分割完成后需要把缺陷区域转换成可判定的数值。常见特征是焊点灰度均值、灰度标准差、暗区面积占比。判定逻辑用规则实现保证每条规则都能被现场工程师理解。def inspect_joint(gray, cx, cy, r, brightness_ref180): # 生成焊点圆域mask只统计圆内的像素 mask np.zeros(gray.shape, np.uint8) cv2.circle(mask, (int(cx), int(cy)), int(r), 255, -1) gray_masked cv2.bitwise_and(gray, gray, maskmask) mean_val cv2.mean(gray_masked, maskmask)[0] std_val float(np.std(gray_masked[mask 255])) # 提取暗区并计算面积占比 blur cv2.GaussianBlur(gray_masked, (5, 5), 0) dark_mask cv2.inRange(blur, 0, brightness_ref - 40) dark_area cv2.countNonZero(dark_mask) total_area np.pi * r * r dark_ratio dark_area / total_area # 判定规则按优先级排列 if mean_val 130: label 虚焊/冷焊 elif dark_ratio 0.12: label 少锡 elif std_val 45: label 疑似虚焊 else: label OK return label, {mean: round(mean_val, 1), std: round(std_val, 1), dark_ratio: round(dark_ratio, 3)}三条规则的顺序有讲究。均值低于130直接判虚焊因为无论是虚焊还是冷焊表面灰度都会大幅下降暗区占比超过12%判少锡意味着焊点表面有一块明显的低灰度区域常见于焊料不足灰度标准差大于45判疑似虚焊因为正常焊点即使有反光灰度分布也是平滑的而虚焊表面粗糙会造成灰度波动。注意这里的判定阈值是经验值。视角、分辨率、光源角度不同阈值必须重新标定。建议把良品和缺陷样本各取50张把特征值打印出来看分布再决定阈值而不是直接抄参数。4. 进阶设计用深度学习补上虚焊分类这一块最难啃的骨头4.1 传统视觉解决不了的样本交给分类网络很多初学者会先去看cs231n这类课程然后想直接上YOLO。实际上焊点缺陷检测里目标检测网络并不是必须的。焊点的位置已经被前面的定位模块框好了剩下的问题只是“这个焊点切片属于哪一类”本质是图像分类不是目标检测。还有一个容易被忽略的点计算机视觉是这次要解决的任务机器学习是解决任务的手段两者不是并列关系。传统视觉在几何缺陷上表现好但在虚焊和冷焊上会翻车。原因在于虚焊和冷焊在图像上没有清晰的边界暗区比例和灰度均值往往与正常焊点重叠规则阈值怎么调都压不住误检。这时用分类网络学习局部纹理和上下文特征能把这部分错误率压下来。4.2 数据准备焊点切片、目录结构与增强策略深度学习部分的数据准备最关键的是切片和标注一致性。先用3.1节的定位代码把每个焊点中心提取出来再以半径的1.2倍裁出正方形切片统一缩放到64×64像素。目录结构建议按缺陷类型分文件夹方便ImageFolder直接读取data/train/normal/ data/train/bridge/ data/train/insufficient/ data/train/solder_ball/ data/train/cold/ data/val/normal/ data/val/bridge/ data/val/insufficient/ data/val/solder_ball/ data/val/cold/切片数量建议每类不少于600张正常类可以多到1500张以上。如果现场不良品不够可以先从历史NG图里裁再用图像增强扩充。增强要克制明暗抖动和对比度抖动可以模拟光源波动小角度旋转模拟焊板摆放偏差但不要做水平翻转和垂直翻转因为桥连的方向信息会丢失翻转后同一张图可能变成另一类缺陷。4.3 训练一个轻量焊点分类网络模型结构与关键参数用小网络而不是直接套大模型原因有两个焊点切片只有64×64信息量不大大模型容易过拟合产线推理需要低延迟一个几万参数的卷积网络在CPU上也能跑。下面是一个可直接用的PyTorch实现。import torch import torch.nn as nn class SolderNet(nn.Module): def __init__(self, num_classes5): super().__init__() self.features nn.Sequential( nn.Conv2d(1, 32, 3, padding1), nn.BatchNorm2d(32), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), nn.Conv2d(32, 64, 3, padding1), nn.BatchNorm2d(64), nn.ReLU(inplaceTrue), nn.MaxPool2d(2), nn.Conv2d(64, 128, 3, padding1), nn.BatchNorm2d(128), nn.ReLU(inplaceTrue), nn.AdaptiveAvgPool2d(1), ) self.classifier nn.Linear(128, num_classes) def forward(self, x): x self.features(x) return self.classifier(x.view(x.size(0), -1))输入是单通道灰度图经过三层卷积和池化最后用AdaptiveAvgPool2d把特征图压成128维。网络结构不需要太深层数越多对数据量的要求越高。from torchvision import datasets, transforms from torch.utils.data import DataLoader transform transforms.Compose([ transforms.Resize((64, 64)), transforms.Grayscale(num_output_channels1), transforms.RandomApply( [transforms.ColorJitter(brightness0.2, contrast0.2)], p0.5 ), transforms.RandomRotation(5), transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) train_set datasets.ImageFolder(data/train, transformtransform) train_loader DataLoader(train_set, batch_size32, shuffleTrue, num_workers4, drop_lastTrue)训练参数建议初始学习率1e-3优化器Adam损失函数CrossEntropyLoss训练30轮。学习率用ReduceLROnPlateau调度patience设为3factor设为0.5意思是验证集loss连续三轮不降时学习率减半。焊点数据集小loss曲线波动大固定步长的StepLR容易错过最优值所以用这种按验证集表现的调度方式。训练时需要每轮记录验证集的混淆矩阵。重点看normal类被误判成缺陷的比例这个值直接决定过杀率同时看cold类被误判成normal的比例这个值决定漏检率。产线上漏检率比过杀率更严重后者的代价是人工复检前者会把不良品放过去。4.4 两阶段融合别让深度学习接管所有环节两阶段融合的规则是传统视觉判定为OK且置信度高的样本直接放行判定为NG的样本全部送分类网络复判分类网络输出概率在0.5到0.8之间的样本转人工复检。这样做的理由是几何缺陷已经被传统视觉稳定检出不需要让网络重新学一遍网络只处理最难判定的灰度类缺陷数据量少也能训练。每次检测时把切片和预测结果按日期存档。每周把新增样本合并进训练集重新微调模型。这个数据回流机制比一次性把模型训到极致更符合产线节奏。5. 焊点缺陷检测系统落地避坑五个高频翻车点与排查顺序5.1 焊点定位偏移先查治具和相机再查算法现象同一块板放两次检测到的焊点中心相差30个像素以上ROI裁剪错位后灰度均值和暗区占比都明显变化误报率上升。原因定位偏移很少是算法问题。最常见的是治具定位销磨损焊板每次摆放位置有偏差其次是相机支架刚度不够产线震动导致相机轻微移动。螺纹紧固件在连续震动下会慢慢松动一周后偏移量就会积累到不可接受。解决治具加两个定位销把焊板自由度限制死相机支架加三角形筋板螺丝打螺纹胶。然后在图像里设一个mark点每次检测前先找mark点计算平移量对焊点坐标做整体补偿。mark点找不到时直接拒检不输出结果。这个顺序不要反先解决物理定位再谈算法补偿。5.2 分割阈值一换光源就崩问题出在固定阈值和自动曝光现象同一套阈值参数上午良品率99%下午过杀率跳到15%同一块板隔几天测一会儿OK一会儿NG。原因环形光源LED有老化特性亮度随时间缓慢下降产线窗户进来的环境光也会叠加到图像上。如果相机开了自动曝光灰度会自动拉回平均值但缺陷对比度同时被抹平如果没开自动曝光固定阈值又会把光源波动直接折算成灰度偏移。解决分三步。第一在光源和焊板之间加漫射板隔断大部分环境光干扰。第二固定快门和增益关闭自动曝光。第三每次开机用标准白板拍一张基准图计算灰度均值再把这个均值作为当天所有阈值的补偿基准。例如基准均值是200当前均值是190所有灰度阈值都减去10。这样光源老化只影响整体亮度不影响缺陷对比度。5.3 小缺陷被形态学滤波滤掉了这是最冤的漏检现象直径0.2mm的锡珠在图像上只有十几个像素正常检测流程里完全看不到桥连检测时又把这种独立小点当成无关噪声跳过。原因为了压背景噪点把形态学开运算的核设成了5×5甚至7×7小缺陷在开运算时被当成孤立噪点抹掉。面积过滤下限也设置随意经常被调得过高。解决形态学核能不用就不用必须用时从3×3开始作用只限定在清除单个像素的传感器噪声。面积过滤下限由缺陷最小尺寸反推在12μm/pixel分辨率下0.2mm缺陷直径约17像素面积下限按圆周率估算约220像素这时候下限设在150比较安全。凡是可能影响缺陷保留的滤波都要留出30%以上的余量。5.4 误检率高原因是ROI太宽松、特征太单一现象报警率20%人工复查发现大部分报警来自焊点周围的丝印字符、油污、焊盘划痕。原因ROI范围取得太大把焊点圆以外的背景也统计进去了。丝印字符是白色的在灰度均值计算里会被当成焊点的一部分焊盘划痕是暗的又会被当成虚焊暗区。单靠一个灰度特征无法区分“焊点内部的暗”和“焊点外部的暗”。解决特征统计之前先用圆形mask把所有统计像素约束在焊点圆内半径取检测半径的1.2倍不要取整块矩形ROI。暗区特征增加位置约束暗区连通域必须与焊点中心距离小于0.8倍半径否则判定为背景。再加上分类网络复判误检率通常能压到2%以内。5.5 检测结果不稳定放着“玄学”问题不管会越陷越深现象系统判定OK的板过电测仍然出现不良同一个缺陷今天报虚焊明天报少锡人工复检也很难复现。原因这看起来像玄学实际上是检测边界没有定义清楚。二维图像只能看到表面灰度测不到焊点高度和内部空洞。虚焊如果表现为高度不足图像上不一定有明显的暗区冷焊内部氧化藏在焊点底部表面灰度可能还是正常。算法输出抖动往往来自训练数据标签不一致不同标注人员对同一张图的类别判断不同。解决在系统设计文档里明确检测项边界只声明“表面外观缺陷检测”不承诺高度和内部质量。标签做交叉复核每张图至少两个人标注不一致的样本单独抽查。对连续出现的“OK但电测不良”案例单独建档分析是否属于检测盲区而不是盲目调阈值。5.6 排查顺序从触发到判定每一步都做最小实验遇到问题先回到硬件链路。第一步检查光源触发是否稳定第二步检查采图是否清晰第三步检查定位是否偏移第四步检查分割是否把缺陷保留下来第五步检查特征值是否合理最后才去调整判定阈值或重新训练模型。很多人跳过硬件的排查一上来就调参数结果是参数越调越复杂问题却始终没有被定位到根源。每次改动只动一个变量记录改动前后的对比图这套习惯能省下大量返工时间。6. 最后的落地技巧用标定板和ROI先验让系统换线不返工一个焊点检测系统真正上线后换产线是逃不掉的。可能上午测板A下午就要切到板B。如果每次换线都重新调定位和阈值这套系统很难被现场接受。我的做法是提前做好两件事标定板和ROI先验。先打印一块标准棋盘格标定板贴在治具基准面上用相机拍一张图自动计算出每毫米对应的像素数。焊点检测不需要标定畸变参数只需要像素与毫米的换算关系。有了这个比例软件里的所有面积和半径阈值都能从毫米直接换算成像素换线时不用靠猜。注意标定板要放在焊板同样高度高度差会直接改变放大倍率。ROI先验的做法是在固定治具上每个焊点的理论位置是稳定的。首次调试时手动确认一次所有焊点的坐标和半径保存成模板文件。产线切换时软件先抓mark点计算当前图像与模板的平移量然后自动变换模板坐标逐焊点检测。不要每次都用全图搜索焊点这样既慢又容易被基板纹理干扰。ROI先验配合局部搜索搜索半径设为焊点间距公差的3倍既能容忍微小偏移又能防止误框到旁边的焊点。每天开机后做一次灰度一致性校验拍白板算灰度均值与基准值对比。偏差超过15就提示“光源亮度异常”这时候不是去调阈值而是去查光源电源和漫射板位置。产线上很多“时好时坏”的疑难杂症最后都指向这里。最后说一句我自己踩过的坑。我第一次做这个系统把大部分时间花在调CNN上后来发现产线上最难的不是分类而是让相机每次看到的焊点都长一个样。从那以后我改变了顺序先固定相机、光源和治具再调算法返工量少了很多。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网