随机移相干涉图相位解包算法(MATLAB 实现)

实现从多幅干涉图中读取数据,使用随机移相算法(Random Phase Shifting, RPS)解包相位,并进行相位展开。


一、算法原理

1.1 干涉图模型

对于 NNN 幅干涉图,每个像素 (x,y)(x,y)(x,y) 的光强模型为:

Ik(x,y)=a(x,y)+b(x,y)cos⁡ϕ(x,y)+θk,k=1,2,...,N I_k(x,y) = a(x,y) + b(x,y)\cos\\phi(x,y) + \\theta_k, \quad k=1,2,...,N Ik(x,y)=a(x,y)+b(x,y)cosϕ(x,y)+θk,k=1,2,...,N

其中:

  • a(x,y)a(x,y)a(x,y):背景光强
  • b(x,y)b(x,y)b(x,y):调制幅度
  • ϕ(x,y)\phi(x,y)ϕ(x,y):待求解的包裹相位
  • θk\theta_kθk:未知的随机移相量

1.2 随机移相算法(RPS)

通过多幅干涉图,可以同时估计 aaa、bbb、ϕ\phiϕ 和 θk\theta_kθk,无需知道移相量。

1.3 相位解包

将包裹相位 −π,π-\\pi, \\pi−π,π 展开为连续相位。


二、完整 MATLAB 代码

2.1 主程序 random_phase_shifting_main.m

matlab 复制代码
%% 随机移相干涉图相位解包算法
clear; clc; close all;

%% ========== 1. 生成/读取干涉图数据 ==========
% 选项1:生成模拟干涉图(用于演示)
N_interferograms = 5;      % 干涉图数量
image_size = [512, 512];   % 图像尺寸

% 生成真实相位(例如:球面波前)
[x, y] = meshgrid(linspace(-1,1,image_size(2)), linspace(-1,1,image_size(1)));
true_phase = 10 * exp(-(x.^2 + y.^2)/0.3);  % 高斯相位分布

% 生成随机移相量(未知)
random_shifts = 2*pi * rand(N_interferograms,1);  % 0~2π 随机移相

% 生成干涉图
interferograms = zeros([image_size, N_interferograms]);
for k = 1:N_interferograms
    % 光强模型:I = a + b*cos(φ + θ_k)
    a = 0.5;  % 背景光强
    b = 0.3;  % 调制幅度
    interferograms(:,:,k) = a + b * cos(true_phase + random_shifts(k));
    
    % 添加噪声
    interferograms(:,:,k) = interferograms(:,:,k) + 0.01*randn(image_size);
end

fprintf('生成 %d 幅干涉图,尺寸 %dx%d\n', N_interferograms, image_size(1), image_size(2));

%% ========== 2. 随机移相相位解包 ==========
fprintf('开始随机移相相位解包...\n');

% 提取每个像素点的时间序列
[N_rows, N_cols, N_frames] = size(interferograms);
wrapped_phase = zeros(N_rows, N_cols);

% 对每个像素点应用 RPS 算法
for i = 1:N_rows
    for j = 1:N_cols
        % 提取该像素的时间序列
        pixel_series = squeeze(interferograms(i,j,:));
        
        % 使用 RPS 算法估计相位
        wrapped_phase(i,j) = rps_algorithm(pixel_series);
    end
    
    % 显示进度
    if mod(i, 50) == 0
        fprintf('  处理第 %d/%d 行\n', i, N_rows);
    end
end

fprintf('包裹相位计算完成\n');

%% ========== 3. 相位解包(展开) ==========
fprintf('开始相位解包...\n');

% 方法1:基于质量的相位解包
unwrapped_phase = quality_guided_unwrap(wrapped_phase);

% 方法2:Goldstein 相位解包(备选)
% unwrapped_phase = goldstein_unwrap(wrapped_phase);

fprintf('相位解包完成\n');

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

% 原始干涉图(第一幅)
subplot(2,3,1); imshow(interferograms(:,:,1), []);
title('干涉图 #1'); colorbar;

% 包裹相位
subplot(2,3,2); imshow(wrapped_phase, [-pi, pi]);
title('包裹相位'); colorbar;

% 解包相位
subplot(2,3,3); imshow(unwrapped_phase, []);
title('解包相位'); colorbar;

% 真实相位(对比用)
subplot(2,3,4); imshow(true_phase, []);
title('真实相位'); colorbar;

% 相位误差
subplot(2,3,5); 
phase_error = abs(unwrapped_phase - true_phase);
imshow(phase_error, []);
title('相位误差'); colorbar;

% 剖面图
subplot(2,3,6);
plot(true_phase(256,:), 'b-', 'LineWidth', 2); hold on;
plot(unwrapped_phase(256,:), 'r--', 'LineWidth', 2);
xlabel('像素位置'); ylabel('相位值');
title('相位剖面图(第256行)');
legend('真实相位', '解包相位');
grid on;

sgtitle('随机移相干涉图相位解包', 'FontSize', 14, 'FontWeight', 'bold');

%% ========== 5. 定量评估 ==========
% 计算相位误差统计
valid_mask = true_phase > 0.1;  % 忽略背景区域
rmse = sqrt(mean((unwrapped_phase(valid_mask) - true_phase(valid_mask)).^2));
mae = mean(abs(unwrapped_phase(valid_mask) - true_phase(valid_mask)));

fprintf('\n相位解包精度评估:\n');
fprintf('  RMSE: %.4f rad\n', rmse);
fprintf('  MAE:  %.4f rad\n', mae);
fprintf('  最大误差: %.4f rad\n', max(phase_error(valid_mask)));

%% ========== 6. 保存结果 ==========
save('phase_unwrapping_results.mat', 'wrapped_phase', 'unwrapped_phase', 'true_phase', 'rmse', 'mae');
fprintf('结果已保存到 phase_unwrapping_results.mat\n');

2.2 随机移相算法核心函数 rps_algorithm.m

matlab 复制代码
function phi = rps_algorithm(I_series)
% 随机移相算法(Random Phase Shifting Algorithm)
% 输入:I_series - 像素点的时间序列 [N_frames × 1]
% 输出:phi - 包裹相位

N = length(I_series);

% 方法1:最小二乘法(需要估计移相量)
% 使用迭代法同时估计相位和移相量

% 初始猜测
phi_guess = 0;
shift_guess = 2*pi*(0:N-1)/N;  % 均匀移相猜测

% 迭代优化
max_iter = 50;
tolerance = 1e-6;

for iter = 1:max_iter
    % 固定移相量,估计相位
    phi_old = phi_guess;
    
    % 构建最小二乘问题
    A = ones(N, 3);
    A(:,2) = cos(shift_guess);
    A(:,3) = sin(shift_guess);
    
    % 求解 a, b*cos(phi), b*sin(phi)
    coeffs = A \ I_series;
    
    % 提取相位
    b_cos_phi = coeffs(2);
    b_sin_phi = coeffs(3);
    phi_guess = atan2(b_sin_phi, b_cos_phi);
    
    % 固定相位,估计移相量
    shift_guess = zeros(N,1);
    for k = 1:N
        % 每个移相量的估计
        numerator = I_series(k) - coeffs(1);
        denominator = sqrt(b_cos_phi^2 + b_sin_phi^2);
        if denominator > 0
            shift_guess(k) = acos(numerator / denominator);
        end
    end
    
    % 检查收敛
    if abs(phi_guess - phi_old) < tolerance
        break;
    end
end

phi = phi_guess;
end

2.3 改进的 RPS 算法(使用 SVD)rps_svd.m

matlab 复制代码
function phi = rps_svd(I_series)
% 基于SVD的随机移相算法(更稳定)
% 输入:I_series - 像素点的时间序列 [N_frames × 1]
% 输出:phi - 包裹相位

N = length(I_series);

% 构建数据矩阵
X = zeros(N, 3);
for k = 1:N
    X(k,:) = [1, cos(2*pi*(k-1)/N), sin(2*pi*(k-1)/N)];
end

% SVD分解
[U, S, V] = svd(X, 'econ');

% 提取相位信息
v1 = V(:,1);  % 对应常数项
v2 = V(:,2);  % 对应cos项
v3 = V(:,3);  % 对应sin项

% 计算相位
phi = atan2(v3(2), v2(2));  % 使用第二行(对应cos和sin的系数)
end

2.4 基于质量的相位解包 quality_guided_unwrap.m

matlab 复制代码
function unwrapped_phase = quality_guided_unwrap(wrapped_phase)
% 基于质量的相位解包算法
% 输入:wrapped_phase - 包裹相位 [M×N]
% 输出:unwrapped_phase - 解包相位

[M, N] = size(wrapped_phase);
unwrapped_phase = wrapped_phase;

% 计算相位质量图(基于相位导数方差)
quality_map = calculate_phase_quality(wrapped_phase);

% 找到质量最高的起始点
[max_quality, idx] = max(quality_map(:));
[start_row, start_col] = ind2sub(size(quality_map), idx);

% 初始化已处理标记
processed = false(M, N);
queue = [];

% 将起始点加入队列
queue = [queue; start_row, start_col];
processed(start_row, start_col) = true;

% 定义8邻域
neighbors = [-1,-1; -1,0; -1,1; 0,-1; 0,1; 1,-1; 1,0; 1,1];

while ~isempty(queue)
    % 取出队列中的第一个点
    current = queue(1,:);
    queue(1,:) = [];
    
    % 检查8邻域
    for n = 1:size(neighbors,1)
        neighbor_row = current(1) + neighbors(n,1);
        neighbor_col = current(2) + neighbors(n,2);
        
        % 检查边界
        if neighbor_row < 1 || neighbor_row > M || neighbor_col < 1 || neighbor_col > N
            continue;
        end
        
        % 如果已经处理过,跳过
        if processed(neighbor_row, neighbor_col)
            continue;
        end
        
        % 计算相位差
        phase_diff = wrapped_phase(neighbor_row, neighbor_col) - wrapped_phase(current(1), current(2));
        
        % 相位展开
        if phase_diff > pi
            unwrapped_phase(neighbor_row, neighbor_col) = unwrapped_phase(neighbor_row, neighbor_col) - 2*pi;
        elseif phase_diff < -pi
            unwrapped_phase(neighbor_row, neighbor_col) = unwrapped_phase(neighbor_row, neighbor_col) + 2*pi;
        end
        
        % 标记为已处理并加入队列
        processed(neighbor_row, neighbor_col) = true;
        queue = [queue; neighbor_row, neighbor_col];
    end
end
end

function quality_map = calculate_phase_quality(wrapped_phase)
% 计算相位质量图
[M, N] = size(wrapped_phase);
quality_map = zeros(M, N);

% 计算相位梯度
[dx, dy] = gradient(wrapped_phase);

% 计算梯度方差作为质量度量
window_size = 5;
for i = 3:M-2
    for j = 3:N-2
        window_dx = dx(i-2:i+2, j-2:j+2);
        window_dy = dy(i-2:i+2, j-2:j+2);
        
        % 质量 = 1 / (方差 + 小常数)
        var_dx = var(window_dx(:));
        var_dy = var(window_dy(:));
        quality_map(i,j) = 1 / (var_dx + var_dy + 1e-6);
    end
end
end

2.5 Goldstein 相位解包(备选)goldstein_unwrap.m

matlab 复制代码
function unwrapped_phase = goldstein_unwrap(wrapped_phase)
% Goldstein 相位解包算法
[M, N] = size(wrapped_phase);
unwrapped_phase = wrapped_phase;

% 寻找残差点
residues = find_residues(wrapped_phase);

% 连接残差点形成枝切线
branch_cuts = connect_residues(residues, M, N);

% 沿路径积分展开相位
unwrapped_phase = integrate_phase(wrapped_phase, branch_cuts, M, N);
end

function residues = find_residues(wrapped_phase)
% 寻找残差点
[M, N] = size(wrapped_phase);
residues = [];

for i = 2:M-1
    for j = 2:N-1
        % 计算2×2区域的相位环绕数
        p1 = wrapped_phase(i,j);
        p2 = wrapped_phase(i,j+1);
        p3 = wrapped_phase(i+1,j+1);
        p4 = wrapped_phase(i+1,j);
        
        % 计算环绕数
        circ = 0;
        circ = circ + wrap_to_pi(p2 - p1);
        circ = circ + wrap_to_pi(p3 - p2);
        circ = circ + wrap_to_pi(p4 - p3);
        circ = circ + wrap_to_pi(p1 - p4);
        
        % 如果环绕数不为0,则为残差点
        if abs(circ) > pi/2
            residues = [residues; i, j, circ];
        end
    end
end
end

function angle = wrap_to_pi(angle)
% 将角度包裹到 [-pi, pi]
while angle > pi
    angle = angle - 2*pi;
end
while angle < -pi
    angle = angle + 2*pi;
end
end

三、运行说明

3.1 直接运行

  1. 将代码保存为 .m 文件
  2. 运行 random_phase_shifting_main.m
  3. 程序会生成模拟干涉图并执行相位解包

3.2 使用真实干涉图

如果你的干涉图是真实拍摄的,修改数据读取部分:

matlab 复制代码
% 读取真实干涉图
file_list = dir('interferograms/*.png');
N_interferograms = length(file_list);

interferograms = zeros([image_size, N_interferograms]);
for k = 1:N_interferograms
    img = imread(file_list(k).name);
    interferograms(:,:,k) = double(img) / 255;
end

3.3 参数调优建议

参数 建议值 说明
N_interferograms 5~9 干涉图数量,越多精度越高
random_shifts 0~2π 随机移相范围
max_iter 30~50 RPS 迭代次数
质量图窗口 3×3~7×7 相位质量计算窗口

四、算法优化建议

4.1 提高计算效率

matlab 复制代码
% 向量化计算(避免双重循环)
pixel_series = reshape(interferograms, [], N_interferograms);
wrapped_phase_vector = arrayfun(@rps_algorithm, num2cell(pixel_series, 2));
wrapped_phase = reshape(wrapped_phase_vector, image_size);

4.2 处理噪声

matlab 复制代码
% 添加预滤波
filtered_interferograms = imgaussfilt3(interferograms, [1,1,0]);

% 使用中值滤波去除孤立噪声点
wrapped_phase = medfilt2(wrapped_phase, [3,3]);

4.3 多尺度相位解包

matlab 复制代码
% 金字塔相位解包
pyramid_levels = 3;
current_phase = wrapped_phase;
for level = 1:pyramid_levels
    % 下采样
    small_phase = imresize(current_phase, 0.5);
    % 解包
    small_unwrapped = quality_guided_unwrap(small_phase);
    % 上采样并作为初始估计
    current_phase = imresize(small_unwrapped, 2) + current_phase;
end

参考代码 随机移相解包相位 读取多幅干涉图之后用随机移相算法解包相位 www.youwenfan.com/contentcsw/81823.html

五、应用场景

应用 说明
光学干涉测量 表面形貌测量、波前重建
电子散斑干涉 变形测量、振动分析
合成孔径雷达 InSAR 地形测绘
医学成像 相位对比MRI、光学相干断层扫描