STFT(短时傅里叶变换)在图像配准中主要用于局部频率分析。以下是MATLAB实现的完整方案:
一、基本原理
图像配准中的STFT通常用于:
- 局部相位分析 - 通过相位相关性实现亚像素精度
- 局部特征提取 - 提取旋转/缩放不变特征
- 多尺度配准 - 不同窗口大小适应不同尺度变换
二、基于STFT的相位相关配准
2.1 主函数:STFT相位相关配准
matlab
function [registered_image, tform, displacement_field] = stft_image_registration(ref_img, mov_img, varargin)
% STFT图像配准 - 基于局部相位相关
% 输入:
% ref_img - 参考图像
% mov_img - 待配准图像
% varargin - 可选参数
% 输出:
% registered_image - 配准后的图像
% tform - 变换矩阵
% displacement_field - 位移场
% 参数设置
p = inputParser;
addParameter(p, 'window_size', 64, @isnumeric); % 窗口大小
addParameter(p, 'overlap', 0.75, @isnumeric); % 重叠比例
addParameter(p, 'max_shift', 20, @isnumeric); % 最大位移
addParameter(p, 'method', 'affine', @ischar); % 变换类型
parse(p, varargin{:});
params = p.Results;
% 图像预处理
if size(ref_img, 3) > 1
ref_img = rgb2gray(ref_img);
end
if size(mov_img, 3) > 1
mov_img = rgb2gray(mov_img);
end
% 确保图像大小一致
[rows, cols] = size(ref_img);
mov_img = imresize(mov_img, [rows, cols]);
% 计算局部位移场
displacement_field = compute_local_displacement(ref_img, mov_img, params);
% 根据位移场估计全局变换
tform = estimate_global_transform(displacement_field, params.method);
% 应用变换
registered_image = imwarp(mov_img, tform, 'OutputView', imref2d(size(ref_img)));
% 可视化结果
if nargout == 0
visualize_registration(ref_img, mov_img, registered_image, displacement_field);
end
end
2.2 计算局部位移场
matlab
function displacement = compute_local_displacement(ref, mov, params)
% 基于STFT相位相关计算局部位移场
[rows, cols] = size(ref);
window_size = params.window_size;
step = round(window_size * (1 - params.overlap));
max_shift = params.max_shift;
% 初始化位移场
displacement = struct();
displacement.dx = zeros(floor(rows/step), floor(cols/step));
displacement.dy = zeros(floor(rows/step), floor(cols/step));
displacement.confidence = zeros(floor(rows/step), floor(cols/step));
displacement.x_pos = zeros(floor(rows/step), floor(cols/step));
displacement.y_pos = zeros(floor(rows/step), floor(cols/step));
% 创建窗口函数(二维汉宁窗)
window = hanning(window_size) * hanning(window_size)';
% 遍历图像块
idx = 1;
for y = 1:step:rows-window_size
for x = 1:step:cols-window_size
% 提取参考图像块
ref_patch = ref(y:y+window_size-1, x:x+window_size-1);
% 提取移动图像块(考虑可能的最大位移)
y_start = max(1, y - max_shift);
y_end = min(rows, y + window_size - 1 + max_shift);
x_start = max(1, x - max_shift);
x_end = min(cols, x + window_size - 1 + max_shift);
mov_patch = mov(y_start:y_end, x_start:x_end);
% 应用STFT相位相关
[dy, dx, conf] = stft_phase_correlation(ref_patch, mov_patch, window, max_shift);
% 存储结果
i = floor(y/step) + 1;
j = floor(x/step) + 1;
displacement.dx(i, j) = dx;
displacement.dy(i, j) = dy;
displacement.confidence(i, j) = conf;
displacement.x_pos(i, j) = x + window_size/2;
displacement.y_pos(i, j) = y + window_size/2;
idx = idx + 1;
end
end
end
2.3 STFT相位相关核心算法
matlab
function [dy, dx, confidence] = stft_phase_correlation(ref_patch, mov_patch, window, max_shift)
% STFT相位相关计算位移
% 确保窗口大小一致
window_size = size(window, 1);
[h1, w1] = size(ref_patch);
[h2, w2] = size(mov_patch);
if h1 ~= window_size || w1 ~= window_size
error('参考图像块大小与窗口不匹配');
end
% 对参考图像块加窗并计算FFT
ref_windowed = ref_patch .* window;
F_ref = fft2(ref_windowed);
% 对移动图像块中心区域加窗并计算FFT
center_y = floor((h2 - window_size)/2) + 1;
center_x = floor((w2 - window_size)/2) + 1;
mov_center = mov_patch(center_y:center_y+window_size-1, center_x:center_x+window_size-1);
mov_windowed = mov_center .* window;
F_mov = fft2(mov_windowed);
% 计算互功率谱
R = F_ref .* conj(F_mov);
R = R ./ (abs(R) + eps); % 归一化,避免除以0
% 逆FFT得到相位相关平面
corr_plane = real(ifft2(R));
% 零频移到中心
corr_plane = fftshift(corr_plane);
% 在允许的位移范围内寻找峰值
center = floor(window_size/2) + 1;
search_range = max_shift;
y_start = center - search_range;
y_end = center + search_range;
x_start = center - search_range;
x_end = center + search_range;
% 确保索引在范围内
y_start = max(1, y_start);
y_end = min(window_size, y_end);
x_start = max(1, x_start);
x_end = min(window_size, x_end);
% 提取搜索区域
search_region = corr_plane(y_start:y_end, x_start:x_end);
% 找到峰值位置
[max_val, max_idx] = max(search_region(:));
[peak_y, peak_x] = ind2sub(size(search_region), max_idx);
% 计算亚像素精度(通过二次拟合)
if peak_y > 1 && peak_y < size(search_region, 1) && ...
peak_x > 1 && peak_x < size(search_region, 2)
% y方向二次插值
y_vals = search_region(peak_y-1:peak_y+1, peak_x);
y_offset = quadratic_interpolation(y_vals);
% x方向二次插值
x_vals = search_region(peak_y, peak_x-1:peak_x+1);
x_offset = quadratic_interpolation(x_vals');
% 计算最终位移
dy = (peak_y - 1 + y_offset) - search_range - 1;
dx = (peak_x - 1 + x_offset) - search_range - 1;
else
dy = peak_y - search_range - 1;
dx = peak_x - search_range - 1;
end
% 置信度(峰值高度)
confidence = max_val;
end
function offset = quadratic_interpolation(vals)
% 二次插值求亚像素偏移
if vals(2) == 0
offset = 0;
else
offset = (vals(1) - vals(3)) / (2 * (vals(1) - 2*vals(2) + vals(3)));
end
end
2.4 估计全局变换
matlab
function tform = estimate_global_transform(displacement, method)
% 从位移场估计全局变换
% 提取有效位移点(高置信度)
threshold = 0.5 * max(displacement.confidence(:));
valid_idx = displacement.confidence > threshold;
if sum(valid_idx(:)) < 4
% 如果有效点太少,使用所有点
valid_idx = displacement.confidence > 0;
end
% 获取对应点
x_src = displacement.x_pos(valid_idx);
y_src = displacement.y_pos(valid_idx);
x_dst = x_src + displacement.dx(valid_idx);
y_dst = y_src + displacement.dy(valid_idx);
% 根据方法选择变换类型
switch lower(method)
case 'translation'
% 计算平均平移
mean_dx = mean(displacement.dx(valid_idx));
mean_dy = mean(displacement.dy(valid_idx));
tform = affine2d([1 0 0; 0 1 0; mean_dx mean_dy 1]);
case 'affine'
% 估计仿射变换
[x_src, y_src] = prepare_points(x_src, y_src);
[x_dst, y_dst] = prepare_points(x_dst, y_dst);
% 使用最小二乘法
A = zeros(2*length(x_src), 6);
b = zeros(2*length(x_src), 1);
for i = 1:length(x_src)
A(2*i-1, :) = [x_src(i), y_src(i), 0, 0, 1, 0];
A(2*i, :) = [0, 0, x_src(i), y_src(i), 0, 1];
b(2*i-1) = x_dst(i);
b(2*i) = y_dst(i);
end
% 求解参数
params = A \ b;
% 构建变换矩阵
tform = affine2d([params(1) params(3) 0; params(2) params(4) 0; params(5) params(6) 1]);
case 'projective'
% 估计透视变换
[x_src, y_src] = prepare_points(x_src, y_src);
[x_dst, y_dst] = prepare_points(x_dst, y_dst);
% 使用RANSAC估计
tform = fitgeotrans([x_src, y_src], [x_dst, y_dst], 'projective');
otherwise
error('未知的变换类型');
end
end
function [x, y] = prepare_points(x, y)
% 准备点集,移除异常值
if length(x) > 100
% 随机采样,避免计算量过大
idx = randperm(length(x), min(100, length(x)));
x = x(idx);
y = y(idx);
end
end
2.5 可视化函数
matlab
function visualize_registration(ref, mov, reg, displacement)
% 可视化配准结果
figure('Position', [100, 100, 1200, 800]);
% 原始图像对比
subplot(2, 3, 1);
imshowpair(ref, mov);
title('配准前(参考 vs 移动)');
% 配准后对比
subplot(2, 3, 2);
imshowpair(ref, reg);
title('配准后(参考 vs 配准)');
% 位移场
subplot(2, 3, 3);
quiver(displacement.x_pos(:), displacement.y_pos(:), ...
displacement.dx(:), displacement.dy(:), 0);
axis ij; axis equal; axis tight;
title('局部位移场');
% 置信度图
subplot(2, 3, 4);
imagesc(displacement.confidence);
colorbar;
title('配准置信度');
xlabel('X位置'); ylabel('Y位置');
% 差分图像(配准前)
subplot(2, 3, 5);
diff_before = imabsdiff(ref, mov);
imshow(diff_before, []);
title(sprintf('配准前差分 (MSE=%.2f)', mean(diff_before(:).^2)));
% 差分图像(配准后)
subplot(2, 3, 6);
diff_after = imabsdiff(ref, reg);
imshow(diff_after, []);
title(sprintf('配准后差分 (MSE=%.2f)', mean(diff_after(:).^2)));
colormap('jet');
end
三、使用示例
3.1 基本使用
matlab
% 示例1:平移配准
ref = imread('cameraman.tif');
mov = imtranslate(ref, [5.5, 3.2]); % 添加平移
% 使用STFT配准
[registered, tform, displacement] = stft_image_registration(...
ref, mov, 'window_size', 64, 'overlap', 0.75, 'method', 'affine');
fprintf('估计的平移: dx=%.2f, dy=%.2f\n', ...
tform.T(3,1), tform.T(3,2));
3.2 旋转和缩放配准
matlab
% 示例2:旋转和缩放配准
ref = imread('pout.tif');
mov = imrotate(ref, 5, 'bilinear', 'crop'); % 旋转5度
mov = imresize(mov, 1.02); % 缩放2%
% 使用STFT配准(需要修改算法以处理旋转缩放)
[registered, tform, displacement] = stft_image_registration(...
ref, mov, 'window_size', 128, 'overlap', 0.5, 'method', 'affine');
3.3 弹性配准
matlab
% 示例3:局部形变配准
function demo_elastic_registration()
% 创建测试图像
ref = imread('coins.png');
ref = imresize(ref, [256, 256]);
% 创建非线性形变
[X, Y] = meshgrid(1:256, 1:256);
Xd = X + 10 * sin(2*pi*Y/128);
Yd = Y + 10 * sin(2*pi*X/128);
% 应用形变
mov = interp2(double(ref), Xd, Yd, 'linear', 0);
mov = uint8(mov);
% STFT配准(局部位移)
params.window_size = 32;
params.overlap = 0.75;
params.max_shift = 15;
displacement = compute_local_displacement(ref, mov, params);
% 可视化局部位移场
figure;
quiver(displacement.x_pos(:), displacement.y_pos(:), ...
displacement.dx(:), displacement.dy(:), 0);
axis ij; axis equal; axis tight;
title('弹性形变位移场');
end
四、高级功能:旋转/缩放不变配准
matlab
function [theta_est, scale_est] = estimate_rotation_scale(ref, mov)
% 使用傅里叶梅林变换估计旋转和缩放
% 转换为频域
F1 = fft2(double(ref));
F2 = fft2(double(mov));
% 幅度谱(移到中心)
M1 = fftshift(log(abs(F1) + 1));
M2 = fftshift(log(abs(F2) + 1));
% 转换为极坐标
[r1, theta1] = polar_transform(M1);
[r2, theta2] = polar_transform(M2);
% 使用相位相关估计旋转
[~, rotation] = phase_correlation(r1, r2);
theta_est = rotation;
% 使用相位相关估计缩放(通过对数径向坐标)
[~, scale] = phase_correlation(theta1, theta2);
scale_est = exp(scale);
% 应用估计的旋转和缩放进行补偿
mov_corrected = imrotate(mov, -theta_est, 'bilinear', 'crop');
mov_corrected = imresize(mov_corrected, 1/scale_est);
end
function [r, theta] = polar_transform(image)
% 将图像从笛卡尔坐标转换到极坐标
[M, N] = size(image);
center = [floor(N/2), floor(M/2)];
max_radius = min(center);
% 创建极坐标网格
rho = linspace(0, max_radius, M);
theta_angles = linspace(0, 2*pi, N);
[r, theta] = meshgrid(rho, theta_angles);
% 插值
X = center(1) + r .* cos(theta);
Y = center(2) + r .* sin(theta);
polar_image = interp2(image, X, Y, 'linear', 0);
r = polar_image;
end
五、性能优化建议
matlab
% 1. 使用并行计算加速
function displacement = compute_local_displacement_parallel(ref, mov, params)
% 开启并行池
if isempty(gcp('nocreate'))
parpool;
end
% 并行计算位移
[rows, cols] = size(ref);
window_size = params.window_size;
step = round(window_size * (1 - params.overlap));
% 预分配
y_positions = 1:step:rows-window_size;
x_positions = 1:step:cols-window_size;
% 并行循环
parfor idx = 1:length(y_positions)*length(x_positions)
[i, j] = ind2sub([length(y_positions), length(x_positions)], idx);
% ... 并行计算每个块的位移
end
end
% 2. GPU加速
function displacement_gpu = compute_local_displacement_gpu(ref, mov, params)
% 将数据传输到GPU
ref_gpu = gpuArray(ref);
mov_gpu = gpuArray(mov);
% 在GPU上执行FFT和相关计算
% ... GPU加速的相位相关代码
% 将结果传回CPU
displacement_gpu = gather(result_gpu);
end
参考代码 STFT算法,用于图像处理中的图像配准 www.3dddown.com/csa/96468.html
六、注意事项
-
窗口大小选择:
- 纹理丰富区域:小窗口(32×32)
- 纹理稀疏区域:大窗口(64×64或更大)
-
重叠比例:
- 高重叠(0.75)提高精度但增加计算量
- 低重叠(0.5)减少计算但可能错过细节
-
应用场景:
- 医学图像(超声、OCT)配准
- 遥感图像对齐
- 显微图像拼接
-
局限性:
- 大形变需要多尺度策略
- 无纹理区域配准困难
- 计算量相对较大