拓冰建站拓冰建站
首页 / 资讯中心 / 正文

机器视觉焊点缺陷检测:Otsu分割与分水岭分离粘连焊点

简介基于计算机视觉的焊点缺陷检测系统设计论文PDF面向图像处理、机器视觉及工业质检方向的研究生和工程师适用于课题研究、算法选型与论文写作参考。资源围绕点焊生产线中常见的虚焊、漏焊、焊穿等缺陷提出了一套完整的视觉检测方案先对焊点图像进行平滑去噪预处理再采用Otsu方法自动选取阈值完成图像分割随后进行倒三角距离变换以增强焊点与背景的对比度最后利用分水岭算法精确分割焊点并结合面积、形状等特征计算实现缺陷自动分类。文中给出了与传统检测方法的对比与实验验证能够帮助读者理解机器视觉在焊接质量检测中的落地思路。资源共1个文件为PDF格式压缩包大小308KB轻量易用目前已有209人学习下载适合作为相关课题的专业指导资料。1. 焊点检测的机器视觉改造这套方案先解决最扎手的粘连分割生产线点焊出来的焊点不是教科书里的标准圆多数时候是几个焊点叠在一起、边缘被焊渣包围、光照一变化灰度就飘。基于计算机视觉的焊点缺陷检测系统要处理的第一个难题不是分类而是先把粘连的焊点一个个干净地切出来。这篇来自《测控技术》2015年的设计论文给的是一条完整的落地路径500万像素工业CCD采集、Otsu自动阈值分割、倒三角距离变换、分水岭算法分离粘连焊点、最小二乘圆拟合、再按面积和内部灰度判虚焊与焊穿。它适合两类人一是产线上想给点焊机配视觉检测的工程师二是正要写机器视觉课程设计或毕业论文、需要一套能讲清楚原理的检测方案的学生。这套方法不依赖深度学习特征可解释参数可调拿到就能照着搭。2. 系统方案与硬件选型500万CCD配同轴光源精度和像素是怎么算出来的2.1 系统构成与工作流相机、上位机、控制台的职责划分论文把整个检测系统拆成四块视频采集设备、控制单元、上位机PC以及上位机检测软件。视频采集设备再往下分是工业数字摄像机、光学镜头和光源这三样决定了图像质量的上限上位机是核心控制部分负责摄像机采集控制检测软件负责图像处理和信号输出控制工作台接收上位机指令做后续的剔料或报警动作。硬件通过1394接口与上位机相连采集的图像数据直接传给上位机处理。在实际产线里这道流程可以整理成一条单向链路产品到位触发 → 相机采集 → 图像经1394传输 → 上位机跑分割与分类算法 → 输出判别信号 → 控制台执行剔除。注意这里没有PLC做中间转译上位机直接输出结果信号好处是延迟低坏处是上位机死机时整条检测线会停所以论文里才强调要保证相机、镜头和光源由支架固定减少外部环境变量对图像的影响。2.2 把0.1mm检测精度换算成相机参数论文给的关键指标是0.1mm检测精度、500万像素工业面阵CCD、单像素尺寸0.04mm。这三个数放在一起是能互相印证的检测对象是100mm长、40mm宽的不锈钢材料横向100mm如果对应约2500个像素算下来每个像素就是0.04mm左右。0.1mm精度意味着缺陷区域在图像上至少占2到3个像素既没过采样导致数据冗余和算法变慢也没欠采样导致小缺陷根本显现不出来。这个换算逻辑在选相机时很实用。500万像素听起来唬人但真正决定检测能力的是“视野范围÷像素数”得到的单像素物理尺寸。同样500万像素拍100mm视野和拍500mm视野精度差5倍。论文选工业面阵CCD而不是CMOS或线阵相机也是因为它要在固定视野内同时兼顾分辨率和帧率面阵结构对静态工件的单次成像最直接。配1394接口而非USB主要是工业现场传输稳定性考虑1394连接在长距离和持续采集场景下丢帧率更低2015年前后工业相机的主流接口就是它。硬件模块选型参数作用工业相机500万像素面阵CCD单像素约0.04mm覆盖100mm×40mm视野满足0.1mm精度镜头定焦光学镜头保证成像清晰度与CCD靶面匹配光源LED同轴白光正面打光均匀背景灰度突出焊点轮廓接口1394稳定传输图像数据至上位机上位机工业PC完成图像处理、缺陷判别、信号输出2.3 光源为什么选同轴白光正面打光焊点检测的光源方案里环形光、条形光、同轴光各有适用场景。论文最终选的是LED颗粒的同轴白色光源、正面打光方式理由是“使得背景亮度均匀即像素灰度值保持一致”。这句话在工程上非常关键不锈钢表面反光厉害如果用环形光焊点边缘会出现一圈角度不同的高光带同一个焊点内部灰度差能拉到几十甚至上百灰度级Otsu阈值分割的假设是图像上有清晰的双峰灰度分布背景灰度飘得越厉害类间方差越难取到稳定极值。同轴光的本质是让光线沿镜头光轴方向垂直照射被测面反射光中只有平行于光轴的分量能原路返回进入镜头镜面反射方向不匹配的部分被滤掉所以背景会呈现均匀的暗场或均匀的亮场具象到像素上就是灰度值在小范围内波动。这样后面做全局阈值分割时焊点和背景的灰度差才是稳定的。我一般还会在光源支架上加一圈遮光罩防止车间顶灯和日光直射造成灰度漂移论文里用支架固定相机和光源已经考虑了这一点但产线环境光变化往往比实验室大得多。3. 焊点图像提取与Otsu分割平滑卷积核与大津法阈值怎么落地3.1 为什么不能直接对原图做二值化焊点图像入手后的第一个坑就是直接二值化。二值化是一个逐像素的灰度映射它不关心像素之间的空间关系。实际焊点图里存在三类干扰一是图像获取和传输过程中产生的噪声点类似椒盐噪声二是背景里的焊渣灰度和焊点边缘接近直接二值化会一起被划成前景三是多个焊点粘连在一起二值化后连成一个连通域根本数不清个数。论文明确说“传统的分割算法不能较好地适应此种情形”指的就是这三个问题。所以处理流程必须是串行的先平滑去噪再做全局阈值分割得到二值图后续通过距离变换和分水岭把粘连焊点拆开。少了第一步第三步分水岭会把噪声点也当成一个局部区域产生大量碎片少了第三步粘连焊点会被合并成一个区域面积特征直接失真后面圆拟合和缺陷分类全错。3.2 平滑处理卷积核尺寸与计算逻辑图像平滑在论文里给的是一个标准卷积公式原始图像为f(x,y)卷积核为C(s,t)核大小为m×n处理后图像为g(x,y)a(m−1)/2b(n−1)/2m和n取奇数。这里核的中心对应输出像素卷积核滑动覆盖邻域后求和赋值。核尺寸是奇数这个细节不是随意写的是为了保证核有唯一的中心像素否则卷积结果会有半个像素的偏移。卷积核取多大直接影响后续分割。核太小比如3×3对高斯噪声有轻微抑制但对付不了焊渣这种成片的杂质核太大比如15×15以上焊点边缘会被抹掉一层边缘变圆钝距离变换算出的中心位置和半径都会偏。论文的检测对象是焊点直径在几十到上百像素之间我一般先用5×5高斯核做平滑再用3×3中值滤波扫掉孤立噪点高斯负责整体去噪中值负责去冲击噪声两者配合比单用高斯稳得多。这段是参考论文平滑思路的常见做法具体核尺寸要靠标定图试出来。3.3 Otsu大津法原理与选型理由大津法解决的问题是“阈值取多少”。固定阈值在实验室里看起来很美——打开一张图拉一下灰度直方图取波谷当阈值就行但产线连续工作后光源衰减、工件批次差异、环境光微变都会让整张图的灰度分布整体平移固定阈值立刻失效。Otsu不需要人工干预它遍历0到255所有候选阈值对每个阈值把像素分成前景背景两类计算类间方差取类间方差最大的那个阈值。类间方差的核心公式是σ²ω₀ω₁(μ₀−μ₁)²其中ω₀、ω₁是两类像素占全图的比例μ₀、μ₁是两类的平均灰度。两类灰度均值差越大且比例越均衡类间方差越大说明这个阈值把两类像素分得越开。Otsu的隐含假设是图像灰度分布接近双峰焊点和背景灰度差明显正好符合前面同轴光源制造出来的均匀背景条件。要注意Otsu不是万能的如果背景灰度不均匀、出现第三个灰度峰阈值会偏向占比大的那一类造成前景区域膨胀或收缩——所以平滑和光源稳定必须在它之前做好。3.4 OpenCV复现这一步的代码与参数import cv2 import numpy as np # 读入灰度图焊点检测全程用单通道图像处理即可 img cv2.imread(solder_joint.bmp, cv2.IMREAD_GRAYSCALE) # 第一步高斯平滑核5x5sigma1.0 # sigma控制权重衰减速度sigma越大模糊越强 blur cv2.GaussianBlur(img, (5, 5), 1.0) # 第二步中值滤波去孤立噪点核3x3 # 中值滤波对椒盐噪声特别有效且不引入新灰度值 blur cv2.medianBlur(blur, 3) # 第三步Otsu自动阈值分割 # threshold参数传0配合THRESH_OTSU标志时会被忽略 _, binary cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU)这段代码里GaussianBlur的核尺寸决定去噪力度5×5在焊点尺寸约40像素时不会明显侵蚀边缘sigma取1.0~1.5之间太大边缘模糊太小高斯核退化成均值滤波。中值滤波的核只能取奇数3×3够用。Otsu在OpenCV里的写法是threshold函数传0作为阈值参数函数自己算最佳阈值并返回所以返回值里第一个量是算出来的阈值可以打印出来观察它随批次的变化。还有一个必须确认的细节二值化后焊点应该是白色255还是黑色0取决于焊点相对背景的明暗。论文的焊点经距离变换后中心灰度小、边缘灰度大说明焊点原始区域大概率比背景暗。如果跑出来前景背景反了把THRESH_BINARY换成THRESH_BINARY_INV即可我在产线上第一次跑就栽在这个极性问题上。4. 倒三角距离变换与分水岭粘连焊点分割的两板斧4.1 距离变换到底在变换什么二值图里只有0和255两类值它包含的信息是“哪里是焊点、哪里是背景”但完全不知道“焊点内部是什么结构”。粘连焊点半成品图里两个焊点交叠后二值层面上就是一个连通的白色区域找不到分界线。距离变换做的事是把这个白色区域里每个像素到最近背景像素的实际距离算出来替换掉原来的二值灰度让图像从“黑白二分”变成“从中心到边缘渐变的灰度图”。对近似圆形的焊点来说从中心沿径向到边缘距离值依次递减中心点离背景最远边缘点距离接近1。论文里说的“中心灰度值小、边缘灰度值大”是它们把距离值做了方向映射后的显示效果本质上表达的是同一个空间关系。有了这个渐变的灰度信息分水岭才有地形起伏可以划分否则一张平地白图上无山可爬。两者是配套的距离变换造地形分水岭切割地形。4.2 倒三角算法两次扫描替代全局计算理论上距离变换要算每个像素到所有背景像素的最小距离是全局操作图稍微大一点计算量就爆炸。论文采用倒三角法把这个全局问题近似成局部传播问题。做法是准备两个3×3模板一个前向模板、一个后向模板。前向模板按从左到右、自上而下的顺序扫描图像模板中心下方的像素值由模板覆盖区域内计算出的最小值替换后向模板按从右到左、自底向上的顺序再扫一遍。倒三角的关键在于中心像素到最近背景的距离可以由它左、上、左上、右上这些已更新过的邻居距离加1推导出来前向扫描装了半边信息后向扫描补上另外半边两趟下来距离场就收敛了。计算量从O(W×H×N)降成O(W×H)这里的N是背景像素数实际场景里N可能占一半图像这个优化直接决定了系统能不能跟上产线节拍。论文强调“倒三角”而不直接用OpenCV的cv2.distanceTransform就是在讲这个效率问题。4.3 分水岭分割把灰度地形切开分水岭算法理解起来有个很直观的画面把距离变换后的灰度图假想成地形图灰度值高的地方是山脊灰度值低的地方是盆地。往每个盆地注水水面上升相邻盆地里的水快要汇合的地方就是分水岭——也就是粘连区域的切割线。论文的处理路径是先把灰度图像空间转化为梯度空间再对梯度图做二值化分成灰度高于和低于阈值的两部分一部分叫陆地、一部分叫水域中间的边界就是分水岭。实际工程中用OpenCV实现分水岭几乎不会做论文描述的“梯度图二值化”那一步而是直接用标记分水岭替代核心是一句cv2.watershed。它接收一个三通道图像和一个标记矩阵标记矩阵里提前标好哪些区域确定是焊点分水岭只负责从这些标记出发划分边界。这么做的原因是原始分水岭对噪声太敏感轻微的灰度扰动就会多出一堆假盆地产生过度分割标记分水岭相当于人为限定盆地数量贴合焊点数。每个焊点中心在距离图上是一个局部极大值或者论文映射后的局部极小值把这些极值点提取出来做连通域标记就是分水岭的种子。4.4 OpenCV复现distanceTransform与watershed配合# binary是上一章Otsu输出的二值图前景应为白色 # DIST_L2计算欧氏距离maskSize5是精度较高的近似核 dist cv2.distanceTransform(binary, cv2.DIST_L2, 5) # 归一化到0~255方便显示和定阈值 dist_norm cv2.normalize(dist, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8) # 标记阈值大于0.4倍最大距离视为焊点中心区域 # 这个系数是整条流水线最需要标定的参数密集焊点取低稀疏焊点取高 _, markers_bin cv2.threshold(dist_norm, 0.4 * 255, 255, cv2.THRESH_BINARY) # 先形态学开运算消除标记区域内的细小空洞和毛刺 markers_bin cv2.morphologyEx(markers_bin, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8)) # 连通域标记每个焊点中心区域得到一个独立编号 _, markers cv2.connectedComponents(markers_bin) # 分水岭约定背景标记为1未知区域标记为0 # 所以把所有标签1再把未知区域重新置0 markers markers 1 markers[markers_bin 0] 0 # watershed输入需要8位三通道图像标记必须是32位单通道 # labels原地震动边界区域会被置为-1 cv2.watershed(cv2.cvtColor(blur, cv2.COLOR_GRAY2BGR), markers)这里两个参数值得单独说。第一个是maskSize5它控制距离变换邻域计算的近似精度取5比取3更接近真实欧氏距离代价是稍慢一点对焊点这种需要精确半径的场景我直接用5。第二个是0.4倍阈值这个数不是论文给定的而是按“标记区域覆盖焊点中心但不连到边界”的原则试出来的。标记阈值取太高一个焊点里可能出现两个分离的极值区域分水岭会把好焊点切成两半取太低两个粘连焊点的中心区域连通成一个标记分水岭无岭可切。我一般会把dist_norm的直方图画出来取第一个峰到第二个峰之间的谷值位置换算成比例一批产品标定一次效果比拍脑袋定0.4稳得多。5. 焊点缺陷判别的常见问题与避坑面积判虚焊、灰度判焊穿的五个坑5.1 最小二乘圆拟合拟合对象是边缘不是区域分水岭分割后的每个焊点区域已经独立了但直接用连通域像素计算面积受分割边界毛刺影响很大而且拿不到圆心和半径判断不了焊点圆度是否合格所以论文在分割后加了一步圆拟合。拟合的原理是最小二乘法设圆心为(A,B)半径为R每个边缘样本点(xᵢ,yᵢ)到圆心距离的平方与R²的差最小化。展开后得到关于a、b、c的二次函数对它求偏导等于零解三元线性方程组就能得到圆心和半径。论文里公式(3)的Q(a,b,c)就是那个误差平方和。工程实现上要注意拟合对象。分水岭标定的labels矩阵里每个焊点区域是一个独立的标签值先取出该标签的掩膜再在掩膜上找轮廓。轮廓提取用RETR_EXTERNAL只取最外层轮廓不能带内孔否则焊点中心区域叠加出第二层点集拟合圆会被拉偏。OpenCV里cv2.minEnclosingCircle给的是最小外接圆cv2.fitEllipse给的是最小二乘椭圆严格做“最小二乘拟合圆”最接近的是对轮廓点自己算方程组。我实际测试下来合格焊点近似正圆fitEllipse返回的长短轴之差能当一个辅助圆度特征比单用一个圆半径信息更丰富。circles [] for label_id in range(1, markers.max() 1): mask np.where(markers label_id, 255, 0).astype(np.uint8) contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) if not contours: continue # 多个轮廓取面积最大的排除边缘残留碎片 contour max(contours, keycv2.contourArea) pts contour.squeeze() if pts.ndim ! 2 or len(pts) 5: continue # 点数太少不构成圆 (x, y), r cv2.minEnclosingCircle(pts) area cv2.contourArea(contour) circles.append((x, y, r, area, label_id))轮廓的CHAIN_APPROX_NONE保留全部轮廓点不压缩保证最小二乘拟合有足够样本点用max按面积挑最大轮廓是因为分水岭偶尔会在焊点外围切出一圈薄边碎片面积显著小于主区域直接忽略。这里判断“点数少于5就跳过”是防止残留的小噪声区域混进后面分类。5.2 虚焊和焊穿的判别特征组合论文对缺陷的判别逻辑很简洁只针对两种主要缺陷虚焊和焊穿。虚焊是两侧电极压力过小或电流过小导致焊件没贴紧、熔合不充分表现是焊点面积比正常焊点小一圈焊穿是电流过大工件被直接烧穿表现是焊点内部灰度均匀、没有正常焊点那种明显的亮色反射中心。前者看几何后者看灰度。面积阈值怎么定正常焊点面积标定后取均值虚焊的判定线通常设在均值的60%~80%低于就判虚焊。这正好呼应论文里“虚焊面积较小”的结论。焊穿判定不能只看面积因为焊穿边缘可能外扩面积未必小。需要在拟合圆内部做一个圆形ROI半径取拟合半径的0.7~0.8倍避开口部边缘统计ROI内的灰度方差。正常焊点中心区域反射亮、边缘暗方差大焊穿区域因为穿孔破坏了金属表面结构反射均匀方差明显小于正常焊点。用“面积阈值判虚焊、灰度方差判焊穿”一前一后串成判断链比单看任一特征稳。5.3 产线落地的五个踩坑记录坑一Otsu二值化前景背景极性搞反。现象是距离变换图完全不按论文描述的“中心灰度小、边缘灰度大”分布分水岭跑出来碎片极多。原因是焊点在原图里是暗底亮斑还是亮底暗斑取决于光源类型和金属反射不同批次材料表面状态会变。解决方法是每次切换产品或调整光源后先打印二值图确认焊点区域是255不对就用THRESH_BINARY_INV重新生成。坑二距离图标记阈值0.4一把走天下换产品就崩。现象是焊点密集排列时正常焊点被切开稀疏排列时粘连焊点又合在一起。原因是不同位置的焊点距离分布完全不同同一个标记阈值不可能同时适配。解决方法是每个产品型号单独标定一组阈值收集20张有代表性的图叠加画出距离图直方图取波谷比例作为初始值再按分割结果微调。坑三焊渣被当成小焊点误检漏检同时升高。现象是背景焊渣经过距离变换和分水岭后自成一块拟合出很小半径的圆被当作虚焊误报率几十个百分点。原因是焊渣灰度与焊点边缘接近Otsu把它归进前景。解决方法是在面积分类前加一个最低面积过滤取标定正常焊点面积的70%作为下限小于下限的区域直接丢弃不进分类器。坑四车间环境光变化造成灰度漂移。现象是上午调好的阈值到下午误检率飙升Otsu自己算出的阈值跟着变化。原因是遮光罩没加或光源支架松了日光角度变化引起背景灰度整体偏移。解决方法是先检查机械固定再谈算法软件侧把每次Otsu算出的阈值打日志观察它是否随时间段漂移漂移超过10个灰度级就检查遮光和光源这是产线视觉落地的第一课。坑五分水岭把一个好焊点切成了碎块。现象是一个焊点被分成两三块每块面积都偏小全部误判成虚焊。原因是焊点表面的纹理、划痕在距离图上形成小的局部谷底原始分水岭把每个谷底当独立盆地。解决方法是改用标记分水岭先用形态学开运算把细纹理抹掉再连通域提取标记标记数量被限制成“一个焊点最多一个中心”分水岭只负责边界划分不再生成新区域。6. 效果验证与参数调优技巧200块样本的对比实验怎么读6.1 配备前后的对比实验设计论文第3节的系统功能测试提供了一个很好的验证模板在点焊机没有视觉系统前生产200块产品用人工检测配备视觉系统后再生产200块用视觉检测两边做数据对比。结论是配备视觉系统后能较好地识别出有缺陷的焊点避免误检漏检的情况。这个实验设计的精髓在于保持样本量一致、生产条件一致只改变检测手段。人工目检在连续工作两小时后注意力下降漏检率会明显上升视觉系统正好补上人眼疲劳这段短板。在实际复现这套方案时建议沿用这个200块样本的验证思路但评价指标拆成三个漏检率、误检率和判定一致性。漏检率指有缺陷焊点被当成了合格品这是质量事故必须压到最低误检率指合格品被当成缺陷品它带来的是返工和产能损失判定一致性是同一批图像用视觉系统跑三次结果完全一致的比例用于验证算法稳定性。def report_stats(gt_labels, pred_labels): # gt是人工确认的标签1正常0缺陷 # pred是视觉检测输出1正常0缺陷 tp sum(1 for g, p in zip(gt_labels, pred_labels) if g 1 and p 1) fn sum(1 for g, p in zip(gt_labels, pred_labels) if g 1 and p 0) fp sum(1 for g, p in zip(gt_labels, pred_labels) if g 0 and p 1) tn sum(1 for g, p in zip(gt_labels, pred_labels) if g 0 and p 0) print(漏检率: %.2f%% % (fn / (tp fn) * 100)) print(误检率: %.2f%% % (fp / (fp tn) * 100)) print(一致性: %.2f%% % ((tp tn) / len(gt_labels) * 100))6.2 参数调优顺序与一个快速验证习惯这套流程的调参点集中在四个位置高斯核与中值核的尺寸、Otsu的前景极性、距离图标记阈值、面积与灰度方差分类阈值。我踩下来的顺序是先把光源和相机曝光固定死让同轴光下背景灰度均值稳定在一个窄区间再确认二值图极性正确接着调距离图标记阈值保证分水岭不碎也不粘连最后才是面积阈值和灰度方差阈值。前三步错了调面积阈值全是白费。快速验证方面不要每调一次参数就看一两张效果图那样对分割质量的判断会被偶然性带偏。我一般会固定抽20张跨时段、跨批次的生产图跑一遍流程后把分水岭和圆拟合的结果叠加在原图上输出一张标注图一张一张过记录“碎了多少个”“漏了哪几个”“多出来哪几个”。全部改完后重新跑一遍这20张确认没有回归。从那以后我每次给产线配视觉检测方案都强制自己走完这20张回归验证再上线哪怕是只改了一个核尺寸也要重跑。算法在实验室里跑出九成五不算数产线连续焊两小时还能稳定在九成以上才算数。希望帮到你。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门