尧图精选

MATLAB超声探伤信号处理与A/B/C扫成像完整实践指南

🕒 发布时间:2026/10/2 18:21:53 📁 来源:尧图网络
简介面向MATLAB超声探伤学习者的小型示例包适合无损检测初学者与相关课程实践。压缩包内共两个文件均为M脚本整体大小仅5KB精简易读。其中主要脚本用于生成高斯余弦脉冲信号模拟超声波短脉冲发射波形配套测试脚本则负责调用信号模型完成回波生成、滤波降噪、傅里叶频谱分析及缺陷位置推算。两个脚本共同构成一段可运行的超声探伤模拟流程覆盖信号产生、介质传播、回波处理和数据可视化等关键环节。虽代码体量不大却集中演示了超声检测中常用的高斯脉冲设计、反射波时间差法定位以及MATLAB绘图函数的使用方法可作为进一步开发探伤算法或开展仿真实验的入门底稿。由于文件为源码形式读者可根据实际需求调整参数并观察波形变化便于动手实践。已有492人学习浏览适合需要快速了解MATLAB在超声探伤中应用的读者参考。1. 超声探伤用 MATLAB 做到底在解决什么超声探伤ultrasonic-testing落到 MATLAB 里核心就一句话从一段回波信号里把缺陷反射找出来算准它的深度和幅度。很多人拿到 ultrasonic-testing.rar 这类源码包跑不出预期效果问题不在算法深而在采样率、声速、探头频率全用默认值仿真图和真实探伤完全对不上。这条路实际是一条完整处理链A 扫信号生成、带通滤波、包络检测、飞行时间换算深度、扫查数据成像。适合信号处理方向毕设、无损检测从业者做算法验证以及想用 MATLAB 复现探伤仪界面的同学。这个方向的核心处理思路二十来年没大改matlab 从老版本装到 2026b处理逻辑依然相同工具版本升级不影响你该怎么算。2. 从零生成可信的 A 扫回波信号脉冲回波模型与参数2.1 脉冲回波模型高斯包络正弦波为什么是默认选择超声探伤里最常碰到的信号是 A 扫横轴时间、纵轴幅度。探头激励脉冲碰到界面后反射回来被同一个探头接收形成一串回波。真实的换能器受高压电脉冲激励后压电晶片会在谐振频率附近做衰减振荡用高斯包络的正弦波去近似这个振荡不是玄学而是工程上公认的做法s(t) A · exp(-(t - t0)^2 / τ²) · sin(2πfc(t - t0))其中 A 是回波幅度t0 是往返传播时间τ 控制脉冲宽度fc 是探头中心频率。高斯包络衰减快旁瓣小和真实探头输出波形很像而且参数少调起来直观。常见探伤场景里回波按到达时间排列始波探头表面的电泄漏信号在 t0 附近缺陷回波在 t2d/c 处底面回波在探头到远端面这个固定距离处。缺陷深度和往返时间的关系是 d c·t/2除以 2 是因为声波走了一个来回这条公式后面所有计算都绕不开。2.2 一发一收 A 扫仿真函数设计与参数表我一般会把 A 扫生成写成一个独立函数参数全部从外部传入避免脚本里到处藏着魔法数。代码这样组织function [t, a_scan] gen_ascan(fs, fc, c, defects) % 生成一发一收 A 扫信号 % fs : 采样率 (Hz) % fc : 探头中心频率 (Hz) % c : 材料纵波声速 (m/s) % defects : 结构体数组, 每个元素含 depth(m) 与 amp(相对幅度) T 30e-6; % 采集时间窗 30 us t (0:1/fs:T).; % 时间轴, 注意是列向量 a_scan zeros(size(t)); for k 1:numel(defects) t0 2 * defects(k).depth / c; % 往返时间 if t0 T, continue; end pulse defects(k).amp * exp(-((t - t0) / 6e-7).^2) ... .* sin(2 * pi * fc * (t - t0)); a_scan a_scan pulse; end end调用时构造两个反射体一个 20 mm 深的缺陷一个 60 mm 深处的底面回波采样率开到 100 MHzfs 100e6; fc 5e6; c 5920; % 钢中纵波声速约 5920 m/s defects(1) struct(depth, 20e-3, amp, 0.4); % 20 mm 缺陷回波 defects(2) struct(depth, 60e-3, amp, 0.8); % 60 mm 底面回波 [t, a_scan] gen_ascan(fs, fc, c, defects); plot(t * 1e6, a_scan); xlabel(时间 (us)); ylabel(幅度);逻辑说明循环里每个缺陷生成一个高斯包络正弦波叠加到总信号上。t0 用往返时间计算超过采集时间窗的直接跳过。τ 取 600 ns按 5 MHz 中心频率算是 3 个周期左右脉冲宽度和真实窄脉冲探头接近。参数典型值作用调参影响fs10~100 MHz采样率低于 2~3 倍 fc 时包络会失真fc2~10 MHz探头中心频率高频分辨力好但衰减大c材料声速深度换算基准偏一点所有深度整体偏移τ0.3~1 us脉冲宽度太宽会把相邻反射叠加amp0~1回波幅度只影响显示不影响时间参数说明采样率不要卡着奈奎斯特采样定理选。探伤要的是包络峰值准确不是单纯不混叠。100 MHz 采 5 MHz 探头一个周期 20 个点包络检测才有足够分辨率。如果采样率只有 10 MHz峰值位置量化误差会直接变成深度误差。2.3 叠加噪声和材料衰减让仿真更像真实探伤真实探头信号里一定有噪声而且越深处回波越弱。材料对超声的衰减随距离指数增加常见做法是给每个回波乘一个距离相关的衰减因子再叠加热噪声att exp(-0.02 * defects(k).depth * 2); % 0.02 Np/mm 衰减系数 pulse defects(k).amp * att * exp(-((t - t0)/6e-7).^2) ... .* sin(2*pi*fc*(t-t0));噪声用 randn 生成后按幅度比例叠加noise_level 0.03; % 噪声幅度约为信号峰值 3% a_scan a_scan noise_level * randn(size(t));这里有个细节衰减系数不能随便乱给。钢的纵波衰减通常在 0.005~0.05 Np/mm 之间和频率强相关频率越高衰减越厉害。仿真时光考虑扩散衰减幅度按 1/d 衰减也能出形但做 DAC 补偿时就要把材料衰减单独建模否则补偿曲线形状不对。噪声幅度也别开太大。3% 噪声在包络检测后基本不影响峰值位置但开到 20% 以上浅缺陷的峰值会被噪声抬起来后面阈值检测就分不清到底哪个峰是真回波。3. 从 A 扫到缺陷参数滤波、包络、飞行时间与 DAC 补偿3.1 带通滤波与希尔伯特包络两个常用函数解决一件事原始 A 扫信号是高频振荡直接找峰值很不稳。标准做法分两步先带通滤波抑制带外噪声再取包络把高频振荡变成平滑的单峰。滤波器我用 designfilt 设计filtfilt 做零相位滤波d designfilt(bandpassiir, ... FilterOrder, 4, ... HalfPowerFrequency1, 2e6, ... HalfPowerFrequency2, 8e6, ... SampleRate, fs); y filtfilt(d, a_scan); env abs(hilbert(y));逻辑说明带通范围设在探头中心频率附近5 MHz 探头给 2~8 MHz 的带宽把低频振动和高频干扰都拦掉。filtfilt 是零相位滤波波形不发生时间偏移这对飞行时间计算很关键。hilbert 求解析信号幅度得到包络曲线峰值位置对应回波到达时刻。参数说明HalfPowerFrequency1 和 HalfPowerFrequency2 是 -6 dB 截止点带宽太宽噪声滤不净太窄会把回波尾巴拉长导致两个相邻缺陷分不开。FilterOrder 取 4 够用太高会出现数值不稳定尤其是采样率高的时候。3.2 计算飞行时间并换算缺陷深度声速校准是定量跳不过去的一关包络求出来后峰值检测用 findpeaks。先设定最小峰高阈值过滤噪声再用 MinPeakDistance 避免同一个回波的几个振荡毛刺被重复检测[peaks, locs] findpeaks(env, ... MinPeakHeight, 0.15, ... MinPeakDistance, fs / fc / 2); % 间隔至少半个周期 tof_us (locs - 1) / fs * 1e6; % 换算成微秒 depth_mm c * tof_us * 1e-3 / 2; % 声速换算深度, 注意除以2逻辑说明locs 是峰值所在的采样点索引减 1 乘采样间隔得到时间。深度换算必须用 c/2这是探伤里最容易算错的地方之一往返距离才是真实深度的两倍。参数说明MinPeakDistance 取 fc 半个周期意思是两个峰至少隔这么远否则算同一个回波。实际使用时这个值要根据探头带宽微调带宽大的探头包络窄可以把间隔进一步缩小。到这里如果只做单点测厚工作就完成了。但探伤不是测厚缺陷波后面还有底面波而且缺陷波幅度受深度影响很大不补偿会出现浅缺陷报警深缺陷漏检的问题。3.3 DAC 曲线补偿让不同深度缺陷都有可比较的波幅DAC距离-波幅曲线补偿要解决的问题是同样大小的缺陷放得越深回波越弱如果不做补偿仪器上显示的波幅不能真实反映缺陷尺寸。常见做法是准备一组不同深度的标准试块测出每个深度平底孔的最大回波波幅然后把波幅-深度关系拟合成曲线。没有试块时可以用衰减模型近似建一条参考曲线R linspace(5, 150, 100); % 深度范围 5~150 mm A0 1; alpha 0.02; % 材料衰减系数 Np/mm DAC_ref A0 ./ R .* exp(-2 * alpha * R); % 扩散衰减材料衰减 plot(R, DAC_ref); xlabel(深度 (mm)); ylabel(参考波幅);逻辑说明扩散衰减按 1/R 衰减材料衰减按 exp(-2αR)两者相乘得到参考曲线。实际探伤中这个曲线由仪器自动补偿但用 MATLAB 做离线数据处理时可以把各回波幅度投影到这个曲线上得到归一化幅度。参数说明alpha 是虚拟参数直接影响曲线形状它只用于没有试块数据时的近似。真正要出定量结论DAC 曲线必须用标准试块实测数据拟合仿真模型只能用来理解原理和验证算法流程。得到 DAC 曲线后每个缺陷回波的等效波幅是 original_amplitude / DAC_ref(depth)这个数值在不同深度间可比缺陷定量的主人才能看明白。4. B 扫与 C 扫成像把一条信号线变成二维探伤图4.1 B 扫灰度图imagesc 的正确用法与坐标轴换算A 扫只管一个点实际探伤要沿直线扫查。探头每移动一步存一条 A 扫一组 A 扫按位置堆叠成矩阵就是 B 扫矩阵用 imagesc 显示成灰度图ascan_matrix []; % 每一行是一条 A 扫 probe_pos []; % 每个位置坐标, 单位 m for k 1:numel(filelist) a_scan load_a_scan(filelist{k}); % 读取一条 A 扫 ascan_matrix(k, :) a_scan.; probe_pos(k) (k - 1) * 1e-3; % 步进 1 mm end depth_mm c * t * 1e3 / 2; % 时间轴换算深度 imagesc(probe_pos * 1e3, depth_mm * 1e3, ... 20 * log10(ascan_matrix eps)); set(gca, YDir, reverse); % 深度越大在图像下方 xlabel(扫查位置 (mm)); ylabel(深度 (mm)); colorbar;逻辑说明imagesc 的第二个参数是 y 轴第三个是强度矩阵。这里把时间轴换算成深度轴再用 set 反转向 y 轴让图像上浅下深符合探伤习惯。显示幅度用 20*log10 转成 dB否则微弱回波在灰度图上完全看不出来。参数说明ascan_matrix 的每一行对应一个探头位置所以调用 imagesc 时矩阵不用转置。如果你发现图像横竖反了先查维度是 k 行还是 k 列这是 B 扫显示最常见的错误来源。4.2 C 扫峰值与深度成像二维分布怎么组织数据C 扫是在一个矩形区域内扫查每个位置取回波包络的峰值和峰值时间生成两幅图峰值幅度图和深度图。[peaks, locs] max(env_matrix, [], 2); % 每条 A 扫的最大峰 tof_us (locs - 1) / fs * 1e6; depth_mm c * tof_us * 1e-3 / 2; figure; subplot(1, 2, 1); imagesc(x_mm, y_mm, reshape(peaks, ny, nx)); % 峰值图 xlabel(x (mm)); ylabel(y (mm)); title(峰值幅度 C 扫); colorbar; subplot(1, 2, 2); imagesc(x_mm, y_mm, reshape(depth_mm, ny, nx)); % 深度图 xlabel(x (mm)); ylabel(y (mm)); title(缺陷深度 C 扫); colorbar;逻辑说明env_matrix 的行是每条 A 扫列是时间采样点。max 沿第二维取每行的最大值和位置得到两个列向量。reshape 是把一维扫描序列按扫查网格还原成二维矩阵顺序要和扫查路径一致不然图像会错乱。常见做法是把扫查路径设计成蛇形或光栅形数据存储顺序和物理位置一一对应。如果用了蛇形路径每隔一行的数据要翻转否则图像会出现锯齿状错位。4.3 图像增强处理借用 matlab 图像处理思路看 B 扫B 扫原始灰度图噪点多缺陷边界模糊。后续定量处理前我会先做两步图像处理中值滤波去噪形态学闭运算把断裂的小缺陷连起来。img_db 20 * log10(ascan_matrix eps); img_f medfilt2(img_db, [3 3]); % 3x3 中值滤波 mask img_f -12; % 阈值分割, 根据噪底调 mask bwmorph(mask, close, 2); % 闭运算补洞 figure; imagesc(probe_pos * 1e3, depth_mm * 1e3, mask); set(gca, YDir, reverse); xlabel(扫查位置 (mm)); ylabel(深度 (mm));参数说明medfilt2 的 [3 3] 窗口适合 B 扫这种行密列密的图窗口太大会抹掉小缺陷。阈值 -12 dB 是从灰度直方图的噪底估计的实际每批数据不一样。bwmorph 的 close 操作把相邻的白色区域连接2 是迭代次数小缺陷相隔很近时才需要开到这个值。图像处理在探伤里的边界要清楚它可以改善显示质量、辅助人工判读但不能用来证明一个小缺陷是否存在。缺陷定论还得回到 A 扫原始包络特征上去。5. MATLAB 超声探伤最容易翻车的 5 个坑现象、原因与解决5.1 采样率看着够深度计算却系统性偏差现象仿真时用 20 MHz 采样 5 MHz 探头波形不混叠但计算出的缺陷深度总比真实值偏大或偏小几十微米。原因采样率只满足波形显示不满足峰值定位精度。20 MHz 采样间隔 50 ns声速 5920 m/s 时对应深度误差约 0.15 mm。包络峰值在采样点之间直接用离散峰值位置就会带量化误差。解决对包络做插值后再找峰或者提高采样率。插值用 spline 对包络做 4 倍过采样env_interp interp1(t, env, ... linspace(t(1), t(end), length(t) * 4), spline);插值后重新找峰深度精度明显提升。这个方法不增加硬件成本适合离线处理。5.2 中文注释乱码加中文路径脚本直接崩现象从老项目里拷贝的 .m 文件用 MATLAB 打开中文注释变成乱码某些版本直接报语法错误。脚本所在路径含中文时 load 命令找不到文件。原因Windows 中文系统下MATLAB 默认按系统编码读文件。现代编辑器把 .m 存成 UTF-8旧版脚本是 GBK两者不匹配就是乱码。解决项目内统一英文注释文件命名只用字母、数字和下划线。中文说明单独放 README.txt不要混进代码文件。如果手头脚本已经乱码用编辑器另存为 UTF-8并在 MATLAB 里执行feature(DefaultCharacterSet, UTF-8);这个设置重启后失效所以更要靠代码文件本身统一编码。这是我踩过最莫名的坑一个中文注释能让你排查半天语法错误。5.3 阈值选全局最大值底面回波被当成缺陷现象把 MinPeakHeight 设成全局最大包络值的一部分后检测出来的第一个峰不是缺陷而是底面回波。原因底面回波通常比缺陷回波强得多全局阈值一高弱的缺陷峰直接被滤掉。阈值看似合理实际没结合探伤场景。解决只允许在缺陷可能出现的时间窗内找峰。探伤里叫闸门MATLAB 里实现就是加一个索引范围gate (t 5e-6) (t 30e-6); % 从始波后到底面波前 env_gate env; env_gate(~gate) 0; [peaks, locs] findpeaks(env_gate, ... MinPeakHeight, 0.1, ... MinPeakDistance, fs/fc/2);闸门范围要基于样品厚度算底面波到达时间 tB 2·d/c缺陷检测窗口设在 tB 之前。窗口开太大把底面波包进来开太小漏检靠近底面的缺陷。5.4 声速用默认值没改所有缺陷整体偏向同一方向现象用钢的 5920 m/s 去算铝试块所有缺陷深度偏差约 15%方向完全一致。原因探伤定量是拿声速当尺子。不同材料纵波声速差异很大钢约 5920 m/s铝约 6300 m/s有机玻璃约 2700 m/s。用错材料相当于拿错误的尺子量长度。解决每个项目用已知厚度试块做一次实测校准。取试样底面回波时间 tB反推实际声速d_known 25e-3; % 标准试块已知厚度 tB 8.43e-6; % 实测底面回波时间 c_eff 2 * d_known / tB; % 校准后的声速 fprintf(校准声速: %.1f m/s\n, c_eff);一次实测校准后面所有深度换算都走这个值。不要用材料手册的理论值当默认值用实测才是真值。5.5 批量 load 回波数据内存爆掉现象几百个 .mat 文件用 load 循环读入文件稍大点 MATLAB 直接提示内存不足命令行失去响应。原因load 把整个变量载入内存循环里又不清理临时变量数据积累到一定量就爆了。解决改成逐条处理、保存结果、立即清变量results zeros(numel(filelist), 2); for k 1:numel(filelist) data load(filelist{k}, a_scan); % 只读需要字段 [p, loc] process_one_scan(data.a_scan); results(k, :) [p, loc]; clear data; endload 指定字段名只读该变量clear 及时释放内存。真遇到超大文件用 memmapfile 做内存映射只按需读取数据段这是最后一招。6. 批量处理管道与校准验证一台普通电脑也能扛两百个文件批量探伤数据处理我一般用 parfeval 建并行池把每个文件的处理任务分给 workerp gcp(nocreate); if isempty(p) p parpool(Processes); % 新版 MATLAB 默认进程池 end futures parallel.Future.empty; for k 1:numel(filelist) futures(k) parfeval(p, process_one_scan, 2, filelist{k}); end all_results zeros(numel(filelist), 2); for k 1:numel(filelist) [idx, p, loc] fetchNext(futures); all_results(idx, :) [p, loc]; end逻辑说明parfeval 每调用一次提交一个任务fetchNext 按完成顺序取结果idx 告诉你结果属于哪个文件。这个模式把 CPU 多核用满两百个文件的分批处理从几分钟压到几十秒。验证技巧不能省批量跑完先抽查三个已知深度缺陷对比检测深度和真实深度偏差超过 1% 就要回查声速校准值和采样率设置。我每次跑批量前会先单文件跑通链路确认参数没被改坏再上全量。这个习惯让我少浪费了很多等待时间希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →