
一句话介绍: 这套 MATLAB 程序读取自带的长条灰度导轨表面图,先用维纳滤波和灰度增强稳定图像,再分别在原尺度与 1/8 粗尺度上计算梯度、开运算和自适应二值化;粗尺度结果负责提供可靠种子,细尺度结果负责约束区域生长,最后通过面积筛选与闭运算得到缺陷二值轮廓。
导轨、金属表面这类图像的难点并不是“有没有灰度变化”,而是真实缺陷、材料纹理、划痕、亮点和随机噪声都会产生灰度突变。
如果只在原图上直接做一次边缘检测,细节虽然保留得多,但背景纹理也容易被一起检出;如果把图像压得很粗再检测,噪点会少很多,却又容易把真实缺陷边界变得过于粗糙。
当前程序采用的思路正好利用这两种尺度的互补性:
原始灰度图 → 维纳滤波与灰度增强 → 原尺度梯度候选图 + 粗尺度梯度种子图 → 以粗尺度结果作为种子、沿原尺度候选区域生长 → 小区域清理与闭运算 → 缺陷二值分割结果
它真正解决的不是缺陷类别识别,而是:
在纹理明显的表面图像中,尽量让稳定的粗尺度区域负责“确认缺陷在哪里”,再让细尺度信息负责“把缺陷轮廓补完整”。
1. 当前工程和输入图像到底是什么?
工程非常精简,只有两个核心文件:
文件 | 作用 |
|---|---|
main.m | 完整缺陷分割主程序,包含预处理、双尺度梯度、二值化、种子生长和后处理 |
21.bmp | 程序默认读取的导轨表面灰度图像 |
21.bmp 是一张 190 × 5000 的单通道灰度长条图。画面中既有细密表面纹理和局部亮划痕,也存在较明显的暗色异常区域,这正是程序需要从复杂背景中分离的对象。
当前工程没有训练模型、配置文件或外部函数依赖,算法主链全部写在 main.m 里,因此它属于传统图像处理的离线缺陷分割脚本。
2. 为什么先做 5 × 5 维纳滤波和灰度增强?
程序首先执行 wiener2(I1,[5,5]),使用 5 × 5 邻域做二维维纳滤波。
这一步主要是为了压低局部随机噪声,让后面的梯度计算不要对每一个微小灰度起伏都产生强响应。它并不是把纹理全部抹掉,而是在保留较明显结构变化的同时,先降低细碎噪点对边缘检测的干扰。
随后程序用 imadjust(I2,[],[],0.5) 做灰度映射,当前 Gamma 为 0.5。Gamma 小于 1 时会提升中低灰度区域的显示与响应,使暗部和中间灰度的结构差异在后续梯度处理中更容易被体现出来。
所以这一段的目的可以概括为:
先让图像更稳定,再让缺陷与背景之间的灰度变化更容易被后续梯度捕捉。
3. 为什么同一张图还要构造一个 1/8 粗尺度版本?
滤波后的图像 I2 保留原始尺寸,负责提供较精细的边界信息。
程序同时把 I2 先按最近邻方式缩小到原尺寸的约 1/8:
190 × 5000 → 23 × 625
然后再放大回 190 × 5000,得到 I3。
经过“先缩小、再放大”之后,很多细小纹理和孤立变化会被弱化,留下更粗、更稳定的结构。因此:
I2:细节多,边界精细,但噪声和纹理响应也多;
I3:细节少,边界较粗,但更适合寻找稳定的大区域种子。
这正是当前程序最关键的设计:不是让两个尺度分别给出最终答案,而是让一个尺度负责找种子,另一个尺度负责补边界。
4. 梯度图在这里到底检测什么?
对 I2 和 I3,程序都分别使用 gradient 计算水平、垂直方向的灰度变化,再合成为梯度幅值。
核心关系可以写成:
G(x,y) = √[Gₓ(x,y)² + Gᵧ(x,y)²]
梯度越大,说明这个位置附近灰度变化越剧烈。
对当前导轨表面图来说,缺陷边缘、划痕边缘和部分纹理都可能产生梯度响应。因此梯度只能告诉程序“哪里变化明显”,还不能直接判断“哪里就是缺陷”。
这也是为什么后面还要继续做形态学开运算、双阈值策略和区域生长,而不是把梯度图直接当成最终分割结果。
5. 两个尺度为什么使用不同的形态学和阈值?
原尺度梯度 G2 和粗尺度梯度 G3 的任务不同,所以源码刻意给了不同的处理强度。
原尺度分支先用半径为 2 的菱形结构元素做开运算,然后用 Otsu 自动阈值 τ₂ 的 0.8 倍二值化:
B2 = Gg2 > 0.8·τ₂
这个阈值相对宽松,目的不是只留下最确定的缺陷,而是保留足够多的细尺度候选边界,供后面的生长过程使用。
粗尺度分支则用半径为 7 的菱形结构元素做更强的开运算,并采用 Otsu 阈值 τ₃ 的 1.3 倍二值化:
B3 = Gg3 > 1.3·τ₃
随后再执行 bwareaopen(B3,1200,8),删除面积小于 1200 像素的 8 邻域连通小区域,得到 BW3。
因此两个二值图的定位非常清楚:
B2更敏感,负责提供“可以生长到哪里”;BW3更严格,负责提供“从哪里开始生长”。
6. 粗尺度种子怎样沿细尺度候选区域长出缺陷轮廓?
源码把 BW3 作为初始种子,并固定执行 70 轮局部生长。
每一轮都会遍历当前种子像素;只要某个位置属于 BW3,程序就检查它周围的 3 × 3 邻域,并把细尺度二值图 B2 在对应邻域中的结果写入新的生长图。
从作用上看,这相当于:
粗尺度确认的稳定区域 → 在细尺度候选图中向周围传播 → 逐步吸收与缺陷连通的精细边界
这一步避免了直接把 B2 中所有高梯度纹理都当成缺陷,因为只有与粗尺度种子建立局部连接的候选区域才有机会被纳入最终结果。
源码中还计算了变化量 D,但当前循环条件实际只由 T 控制,D 并没有参与提前停止。因此现有程序会固定执行 70 轮,而不是达到某个收敛阈值后自动结束。
7. 生长完成后为什么还要再做一次形态学后处理?
区域生长结束后,程序并没有直接输出,而是继续做两步清理。
第一步是 bwareaopen(BW3_new,500,8),删除面积小于 500 像素的连通小区域。它负责清掉生长后仍然残留的孤立碎片。
第二步使用半径为 5 的菱形结构元素执行闭运算 imclose。
闭运算更适合处理:缺陷内部的小孔洞;边界上的短小断裂;
相互靠近但没有完全连接的局部区域。
最终得到的 BW5 就是程序显示的缺陷二值分割结果。
8. 当前程序最终输出的是什么?
当前脚本的最终输出不是缺陷类别、长度、面积报表或合格率,而是一张二值掩膜 BW5:
白色 区域表示程序分割出的缺陷区域;
黑色 区域表示背景。
源码最后通过 imshow(BW5) 显示结果,标题为“缺陷分割结果”。
工程中没有附带人工标注真值,也没有 IoU、Dice、准确率、召回率等评价代码,因此不能从现有资料中虚构一个“分割精度”。这套程序当前完成的是缺陷区域自动分割,而不是定量性能评测或缺陷分类。
如果后续要继续做检测系统,可以在 BW5 基础上追加连通域统计,进一步计算缺陷数量、面积、外接矩形、中心位置或长度等指标。
9. 为什么不直接用单一尺度做一次阈值分割?
只使用原尺度时,最大的问题是背景纹理也会产生大量梯度响应。为了保住真实缺陷的细边界,阈值不能设得太高,但阈值一低,噪点和划痕又会明显增加。
只使用粗尺度时,情况相反:噪声确实少了,但真实缺陷边缘被简化,轮廓容易过粗,细节不足。
当前程序把两者拆成两个角色:
粗尺度高门槛筛选稳定种子 + 原尺度低门槛保留精细候选 + 受种子约束的局部生长
这种组合的价值不在于“某一个阈值更准确”,而在于把定位稳定性和边界完整性分别交给不同尺度处理。
10. 哪些参数最值得修改?
当前源码里真正会明显改变分割行为的参数主要集中在尺度、阈值和形态学尺寸上。
参数 | 当前值 | 为什么值得改 | 调整后的主要影响 |
|---|---|---|---|
粗尺度缩放比例 | 1/8 | 决定种子图保留多少细节 | 更粗会抑制更多纹理,但小缺陷也更容易被弱化 |
原尺度开运算半径 | 2 | 控制细尺度候选图的去噪强度 | 增大可减少细碎响应,但可能损失窄边界 |
粗尺度开运算半径 | 7 | 直接影响种子区域的稳定性 | 增大后种子更保守,小缺陷更难保留 |
双阈值系数 | 0.8 / 1.3 | 分别控制候选灵敏度和种子严格程度 | 前者越低越敏感,后者越高种子越保守 |
初始种子最小面积 | 1200 | 决定什么规模的粗尺度区域能进入生长 | 过大可能漏掉小缺陷,过小会引入纹理种子 |
生长轮数 T | 70 | 限制种子沿候选区域传播的距离 | 增大可扩展更远,但计算量增加,也可能吸收更多相连候选区域 |
这些数值与当前 190 × 5000 图像的像素尺度直接相关。换成分辨率明显不同的图像时,尤其是 1200、500 和结构元素半径,不能简单原样照搬。
11. 它适合用在哪里?
当前程序本身就是围绕导轨表面灰度图设计的,适合对已经采集完成的表面图像做离线缺陷区域提取,特别是背景纹理较多、单尺度阈值容易产生噪点的情况。
整个算法只有一个 main.m,双尺度、梯度、Otsu 阈值、形态学和种子生长的关系非常直观,适合观察不同尺度与阈值如何影响最终分割。
BW5 已经把图像转成二值缺陷区域,因此可以继续接连通域分析、面积统计、位置定位或缺陷分类,把“哪里有异常”进一步转换成可测量的工程指标。
当前版本更适合单张灰度图离线验证与专项分割。它没有批量文件管理、实时相机采集、缺陷分类模型、自动参数标定或生产线通信接口,因此不应直接等同于完整的在线机器视觉检测平台。
12. 怎么运行?
直接运行:main
当前脚本会自动读取 21.bmp,依次完成滤波、增强、双尺度构造、梯度计算、形态学处理、二值化、种子生长和最终闭运算,并显示原图与缺陷分割结果。
程序使用了 wiener2、imadjust、imresize、strel、imopen、graythresh、im2bw、bwareaopen、imclose 等图像处理函数,因此需要 MATLAB 的 Image Processing Toolbox。
如果要换成自己的数据,最少需要把新图像放到当前工作目录,并修改 imread('21.bmp') 中的文件名。当前流程按二维灰度图编写,彩色图应先转为单通道灰度图再进入这套处理链。
13. 一句话看懂这个项目
这是一个导轨表面缺陷自动分割程序:它对自带的 190 × 5000 灰度图先做 5 × 5 维纳滤波和 Gamma=0.5 灰度增强,再同时构造原尺度与 1/8 粗尺度图像并计算梯度;原尺度分支用较小形态学结构元素和 0.8 倍 Otsu 阈值保留细致候选区域,粗尺度分支用更强开运算、1.3 倍 Otsu 阈值和 1200 像素面积筛选得到稳定种子,随后固定进行 70 轮 3 × 3 邻域生长,让种子沿细尺度候选区域扩展,最后再通过 500 像素小区域清理和半径 5 的闭运算得到BW5缺陷二值轮廓;它的核心不是训练分类器,而是利用“粗尺度定位稳定、细尺度边界精细”的互补关系完成表面缺陷区域分割。