You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何选择合适的Sobel核解决FFT 2D卷积中的边界重复问题?

FFT实现Sobel卷积时的核居中解决方案

我用FFT 2D生成Sobel图像,整体效果还行,但顶部和左侧总是出现重复线条。排查后发现是Sobel核K_y和K_x在fft2算法里没居中导致的。试过把核完全居中到m/2和n/2位置,结果出现四个重复图像;尝试把核居中到(0,0)也没解决问题。相关代码如下:

% Get X
X = imread('image.png');

% Gray scaled image
if(size(X, 3) > 1)
  X = rgb2gray(X);
end

% Create kernels for X-direction and Y-direction
K_x = [-1 0 1; -2 0 2; -1 0 1];
K_y = [-1 -2 -1; 0 0 0; 1 2 1];

% Do conv2 with FFT
Gx = conv2_fft(X, K_x);
Gy = conv2_fft(X, K_y);

% Compute the gradients
G = sqrt(Gx.^2 + Gy.^2);

% Compute the orientations
O = atan2d(Gy, Gx);

end

function G = conv2_fft(X, K)
  % Create kernel
  [m, n] = size(X);
  kernel = zeros(m, n);
  [m, n] = size(K);
  kernel(1:m, 1:n) = K;

  % Do FFT2 on X and kernel
  A = fft2(X);
  B = fft2(kernel);

  % Compute the convolutional matrix - abs to remove zero imaginary numbers
  G = abs(ifft2(A.*B));
end

问题核心是FFT卷积本质是循环卷积,当前代码把核直接放在图像左上角,导致循环卷积时图像底部/右侧的像素会“绕回”到顶部/左侧,形成重复线条。要正确实现核居中,需将Sobel核的中心对齐到图像中心,同时避免核被拆分。

修正方案

  1. 计算合理的移位量:针对3×3的Sobel核,移位量取图像与核尺寸差的一半(向下取整),确保核整体居中。
  2. 使用circshift完成循环移位,保证核完整处于图像中心区域。

修改后的conv2_fft函数

function G = conv2_fft(X, K)
    [img_h, img_w] = size(X);
    [k_h, k_w] = size(K);
    
    % 初始化核为图像大小的零矩阵,将Sobel核放在左上角
    kernel = zeros(img_h, img_w);
    kernel(1:k_h, 1:k_w) = K;
    
    % 计算移位量:将核的中心对齐到图像中心
    shift_y = floor((img_h - k_h) / 2);
    shift_x = floor((img_w - k_w) / 2);
    kernel = circshift(kernel, [shift_y, shift_x]);
    
    % 执行FFT卷积
    A = fft2(X);
    B = fft2(kernel);
    G = abs(ifft2(A .* B));
end

补充说明

  • 之前直接将核放到m/2、n/2位置出现四个重复图像,是因为未考虑核自身尺寸,直接移位导致核被循环拆分到四个角落。用circshift配合计算好的移位量,能保证核整体居中。
  • 如果需要和conv2(X, K, 'same')完全一致的线性卷积结果,建议将图像和核都填充到img_h + k_h - 1、img_w + k_w - 1的大小后再执行FFT,此时循环卷积结果等价于线性卷积的有效部分。

内容的提问来源于stack exchange,提问作者euraad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:57:03