如何选择合适的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核的中心对齐到图像中心,同时避免核被拆分。
修正方案
- 计算合理的移位量:针对3×3的Sobel核,移位量取图像与核尺寸差的一半(向下取整),确保核整体居中。
- 使用
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
相关产品推荐
相关产品推荐

