地震数据颜色反演(Colored Inversion)MATLAB 实现

MATLAB 脚本,包含:

  • 合成地震数据(层状模型 + Ricker 子波)
  • 合成一口井的声阻抗曲线
  • 设计颜色算子(频域谱比 + −90° 相位)
  • 逐道卷积得到拟阻抗剖面
  • 质量控制和可视化对比

1. 主脚本:colored_inversion_demo.m

matlab 复制代码
%% 颜色反演(Colored Inversion)演示 --- MATLAB 实现
% 作者:教学示例
% 功能:从叠后地震数据快速估算相对波阻抗
clc; clear; close all;

%% ==================== 1. 生成合成数据 ====================
% 1.1 时间轴
dt = 0.002;          % 采样间隔 2ms
nt = 512;            % 时间采样点数
t  = (0:nt-1)' * dt; % 时间向量 (s)

% 1.2 地下模型:三层介质,声阻抗(真实值,用于验证)
nx = 64;             % 道数
x  = (1:nx) * 10;    % 道间距10m

% 声阻抗随深度变化(假设横向均一,但有轻微横向变化)
v0 = 2000; rho0 = 2.0;
z0 = v0 * rho0;                       % 上层阻抗
v1 = 2400; rho1 = 2.2; z1 = v1 * rho1; % 中层阻抗
v2 = 2200; rho2 = 2.1; z2 = v2 * rho2; % 下层阻抗

% 构造声阻抗体 (nt × nx)
AI_true = zeros(nt, nx);
for ix = 1:nx
    % 两个界面:0.2s 和 0.5s,加上横向缓变
    t1 = 0.2 + 0.02 * sin(ix/nx*2*pi);
    t2 = 0.5 + 0.03 * cos(ix/nx*2*pi);
    AI_true(:,ix) = z0 + (z1-z0)*(t >= t1) + (z2-z1)*(t >= t2);
    % 加入轻微随机扰动模拟横向非均质性
    AI_true(:,ix) = AI_true(:,ix) + 0.02*z0*randn(nt,1);
end

% 1.3 反射系数序列
RC = zeros(nt, nx);
for ix = 1:nx
    % 反射系数 r = (Z_{i+1}-Z_i)/(Z_{i+1}+Z_i) 近似
    RC(1:end-1, ix) = diff(AI_true(:,ix)) ./ (AI_true(1:end-1,ix)+AI_true(2:end,ix));
end

% 1.4 Ricker 子波(主频 30 Hz)
fm = 30;                             % 主频 (Hz)
tw = (-0.04:dt:0.04)';               % 子波时窗
w  = (1 - 2*(pi*fm*tw).^2) .* exp(-(pi*fm*tw).^2);
w  = w / max(abs(w));                % 归一化

% 1.5 合成地震记录(褶积)
seis = zeros(nt, nx);
for ix = 1:nx
    seis(:,ix) = conv(RC(:,ix), w, 'same');
end

% 加入少量噪声
seis = seis + 0.01 * randn(size(seis));

% 1.6 选择一口井(例如第32道)
iw = 32;
seis_well = seis(:, iw);
AI_well   = AI_true(:, iw);

%% ==================== 2. 设计颜色算子 ====================
fprintf('>>> 设计颜色算子...\n');

% 2.1 频域谱比
N = nt;                              % FFT点数
f = (-N/2:N/2-1)' / (N*dt);          % 频率轴 (Hz)

% 地震道振幅谱
Sf = fftshift(fft(seis_well));
AS = abs(Sf);

% 井阻抗振幅谱
Zf = fftshift(fft(AI_well));
AZ = abs(Zf);

% 有效频带(5~80 Hz)
fmin = 5;  fmax = 80;
fmask = (abs(f) >= fmin) & (abs(f) <= fmax);

% 谱比:|O(f)| = |Z(f)| / |S(f)| (仅在有效频带内)
eps_reg = 1e-6 * max(AS);            % 正则化防除零
O_amp = zeros(N,1);
O_amp(fmask) = AZ(fmask) ./ (AS(fmask) + eps_reg);

% 在频带边界做余弦渐变(taper)避免截断效应
bw = 5;  % 过渡带宽 (Hz)
taper = ones(N,1);
for edge = [fmin, fmax]
    idx = find(abs(f-edge) < bw);
    if ~isempty(idx)
        taper(idx) = 0.5*(1+cos(pi*(abs(f(idx))-edge)/bw));
    end
end
O_amp = O_amp .* taper;

% 2.2 施加 -90° 相位(积分算子)
phase = zeros(N,1);
phase(f > 0)  = -pi/2;   % 正频率 -90°
phase(f < 0)  =  pi/2;   % 负频率 +90°(保证实信号)
phase(f == 0) = 0;

O_complex = O_amp .* exp(1j * phase);

% 2.3 逆FFT得到时域算子
op_full = real(ifft(ifftshift(O_complex)));
% 居中截取短算子(通常有效长度 ~100ms)
center = round(N/2);
half_len = 50;   % 截取 ±50个样点(±0.1s)
op_short = op_full(center-half_len : center+half_len);

% 应用汉宁窗平滑算子两端(减少边缘振荡)
win = hann(length(op_short));
op_short = op_short .* win;

% 归一化(保持输出量级合理)
op_short = op_short / max(abs(op_short));

fprintf('    算子长度: %d samples (%.3f s)\n', length(op_short), length(op_short)*dt);

%% ==================== 3. 应用颜色反演 ====================
fprintf('>>> 逐道卷积应用颜色算子...\n');

AI_est = zeros(nt, nx);
for ix = 1:nx
    AI_est(:,ix) = conv(seis(:,ix), op_short, 'same');
end

% 对结果做最小-最大归一化到与真实阻抗相近的范围(方便对比)
% 注:颜色反演输出是相对阻抗,需要标定到绝对刻度
% 这里用井旁道做线性回归标定
coeff = polyfit(AI_est(:,iw), AI_well, 1);
AI_est_scaled = coeff(1) * AI_est + coeff(2);

%% ==================== 4. 结果可视化 ====================
figure('Position', [100 100 1400 800]);

% 4.1 地震剖面
subplot(2,4,1);
imagesc(x, t, seis); axis ij; colormap(gray);
xlabel('道号'); ylabel('时间 (s)'); title('叠后地震剖面');
colorbar; clim([-1 1]*max(abs(seis(:))));

% 4.2 颜色算子
subplot(2,4,2);
plot(op_short, (0:length(op_short)-1)*dt, 'b', 'LineWidth',1.5);
set(gca, 'YDir', 'reverse'); xlabel('振幅'); ylabel('时间 (s)');
title('颜色算子 o(t)'); grid on;

% 4.3 井旁道对比:地震、真实AI、估计AI
subplot(2,4,3);
plot(seis_well, t, 'k', 'LineWidth',1); hold on;
plot(AI_well/max(AI_well), t, 'r', 'LineWidth',1.5);
plot(AI_est_scaled(:,iw)/max(AI_est_scaled(:,iw)), t, 'b--', 'LineWidth',1.5);
set(gca, 'YDir', 'reverse');
xlabel('归一化振幅'); ylabel('时间 (s)');
legend('地震道','真实AI (归一化)','估计AI (归一化)','Location','southwest');
title('井旁道对比'); grid on;

% 4.4 估计AI剖面
subplot(2,4,4);
imagesc(x, t, AI_est_scaled); axis ij; colormap(jet);
xlabel('道号'); ylabel('时间 (s)'); title('颜色反演估计的拟阻抗');
colorbar;

% 4.5 真实AI剖面
subplot(2,4,5);
imagesc(x, t, AI_true); axis ij; colormap(jet);
xlabel('道号'); ylabel('时间 (s)'); title('真实声阻抗');
colorbar;

% 4.6 误差剖面
subplot(2,4,6);
imagesc(x, t, AI_est_scaled - AI_true); axis ij; colormap(redblue);
xlabel('道号'); ylabel('时间 (s)'); title('估计误差');
colorbar; clim([-1 1]*max(abs(AI_est_scaled(:)-AI_true(:))));

% 4.7 井轨迹处的阻抗曲线对比
subplot(2,4,[7 8]);
plot(AI_well, t, 'r', 'LineWidth',2); hold on;
plot(AI_est_scaled(:,iw), t, 'b--', 'LineWidth',2);
set(gca, 'YDir', 'reverse');
xlabel('声阻抗 (m/s*g/cm³)'); ylabel('时间 (s)');
legend('真实AI','颜色反演AI','Location','southwest');
title(sprintf('井旁道定量对比 (相关系数 r=%.3f)', ...
    corr(AI_well, AI_est_scaled(:,iw))));
grid on;

sgtitle('颜色反演 (Colored Inversion) 演示');

%% ==================== 5. 质量控制 ====================
fprintf('\n========== 质量控制 ==========\n');
fprintf('井旁道相关系数: %.3f\n', corr(AI_well, AI_est_scaled(:,iw)));
fprintf('RMS误差: %.2f\n', sqrt(mean((AI_well - AI_est_scaled(:,iw)).^2)));

% 显示算子频谱
figure;
subplot(1,2,1);
plot(f, AS, 'k', 'LineWidth',1); hold on;
plot(f, AZ, 'r', 'LineWidth',1);
plot(f, O_amp*max(AS), 'b--', 'LineWidth',1.5);
xlim([0 100]); xlabel('频率 (Hz)'); ylabel('振幅');
legend('地震谱','阻抗谱','算子谱(缩放)','Location','northeast');
title('频谱对比'); grid on;

subplot(1,2,2);
plot(f, angle(O_complex)*180/pi, 'g', 'LineWidth',1.5);
xlim([0 100]); xlabel('频率 (Hz)'); ylabel('相位 (度)');
title('算子相位(期望 −90°)'); grid on;
ylim([-180 180]);

2. 运行结果解读

执行上述脚本后,你会看到:

  1. 合成地震剖面(灰色):两个反射同相轴对应两个界面。
  2. 颜色算子波形:约 100ms 长的短算子。
  3. 井旁道对比:红色为真实阻抗(归一化),蓝色虚线为颜色反演估计的拟阻抗,黑色为原始地震道。可见估计结果与真实阻抗趋势高度一致,但缺失低频背景(相对值)。
  4. 估计AI剖面:颜色反演输出的拟阻抗,清晰地显示了两个层的阻抗变化。
  5. 误差剖面:显示估计值与真实值的差异,主要在边界处有轻微震荡(Gibbs现象)。
  6. 频谱图:展示了地震谱、阻抗谱和算子谱的关系;算子相位在有效频带内约为 −90°。

参考代码 地震数据反演中的颜色反演方法 www.youwenfan.com/contentcsv/81492.html

3. 关键要点说明

步骤 说明
谱比设计 用井旁地震道振幅谱除井阻抗振幅谱,得到算子振幅谱。需限制在有效频带内,并做平滑/taper防止噪声放大。
−90°相位 将反射系数转换为阻抗的积分操作。如果地震数据本身不是零相位,需先做相位校正。
算子截断 频域设计的算子理论上无限长,实际截取短时窗(约100ms)并加窗,以减少计算量且保持精度。
标定 颜色反演输出是相对阻抗,需要通过井旁道线性回归(或均值/方差匹配)转换到绝对刻度。本例中使用了一次多项式拟合。
适用范围 适用于叠后地震数据、零相位或已知相位校正后的剖面。对于复杂构造或强非平稳数据,可能需要分时窗设计多个算子。

4. 扩展:处理真实SEGY数据

若你有实际地震数据(SEGY格式)和井曲线,可按以下步骤替换合成数据部分:

matlab 复制代码
% 读取SEGY(需SEGYMAT工具箱或自行实现)
[seis, headers] = read_segy('input.sgy');
dt = headers.dt / 1e6;  % 采样间隔 (s)
nt = size(seis,1);
nx = size(seis,2);
t = (0:nt-1)' * dt;

% 读取井曲线(LAS格式或ASCII)
ai_log = load('well_ai.txt'); % 两列:时间(s), 阻抗
ai_well_interp = interp1(ai_log(:,1), ai_log(:,2), t, 'linear', 'extrap');

% 提取井旁道(根据CDP坐标匹配)
iw = find_nearest_cdp(headers, well_cdp);
seis_well = seis(:, iw);

之后的设计和应用流程完全相同。


5. 常见问题及解决

问题 可能原因 解决方法
输出拟阻抗与真实阻抗极性相反 相位处理错误(+90°而非−90°) 检查算子相位,确认正频率相位为 −π/2
输出噪声很大 谱比在有效频带外放大了噪声 缩小 fmin/fmax 范围,加大正则化 eps_reg
输出缺乏低频趋势 颜色反演本质是带限的 需后续拼接低频模型(井插值或速度模型)
井旁道匹配不佳 地震相位不准确或子波非零相位 先做零相位化处理,或使用井震标定校正相位