我想在matlab中验证卷积定理。
首先,我做了2D高斯的二维离散卷积 图像灰度图(x,y)。
其次,我计算了傅里叶变换 相同的2D高斯和原始图像。然后执行标量乘法 在这两个傅立叶变换中,接着是结果的逆傅里叶变换。
最后,我将计算两个结果之间的MSE。但是,我发现错误是800 +。
这是我的代码:
[row, col] = size(graymap);
[row_2, col_2] = size(z);
result = zeros(row, col);
for i = 1: col
for j = 1:row
accumulation_value = 0;
for k = -4:4
for h = -4:4
if ((i+k > 0 && i+k < col + 1) && (j+h > 0 && j+h < row + 1))
value_image = double(graymap(i+k, j+h));
else
value_image = 0;
end
accumulation_value = accumulation_value + value_image * double(z(5 + k, 5 + h));
weighted_sum = weighted_sum + z(5 + k, 5 + h);
end
end
result(i,j) = (accumulation_value);
end
result_blur_1 = uint8(255*mat2gray(result));
M = size(graymap,1);
N = size(graymap,2);
resIFFT = ifft2(fft2(double(graymap), M, N) .* fft2(double(z), M, N));
result_blur_2 = uint8(255*mat2gray(resIFFT));
err = immse(result_blur_1, result_blur_2);
z是9 * 9高斯核。我不翻转它,因为它是对称的。
我认为我的卷积实现是正确的,因为结果与conv2(graymap,z,'same')相同。
因此,我认为第二部分有问题。事实上,我对填充如何工作感到困惑。可能它是大型MSE的原因。
答案 0 :(得分:1)
第二部分的实施确实存在问题。通过fft实现卷积时要记住的最重要的规则是,您实际上是在计算 圆形 卷积,而不是 线性 强>卷积。幸运的是,存在两种情况相同的条件。这个条件是两个数组应该是零填充的,其大小等于每个减去1 (在所有维度中)的大小之和。因此,如果您使用的是尺寸为X
x M
的图片N
,以及尺寸为Z
x P
的图片Q
,则你应该用零填充两个数组,以便 至少 维M+P-1
x N+Q-1
。任何额外的零都不会受到伤害,因此匹配友好的 &#39;尽可能的大小(例如使用nextpow2
)。您只需要获取第一个M+P-1
x N+Q-1
值。
现在,如果您只想要卷积的完整结果,这将直接进行。但是因为你想要卷积的中心部分(选项&#39;相同&#39;),你需要选择正确的索引。第一个索引将是ceil(([P Q] - 1)/2) + 1
,然后您将获取与图像大小一样多的连续索引。
以下是将所有内容放在一起的示例:
M = randperm(1024,1);
N = randperm(1024,1);
X = rand(M,N);
P = randperm(64,1);
Q = randperm(64,1);
Z = rand(P,Q);
% 'standard' convolution with option 'same'
C1 = conv2(X,Z,'same');
R = 2^nextpow2(M+P-1);
S = 2^nextpow2(N+Q-1);
% convolution with fft. Notice the zero-padding to R,S
C2 = real(ifft2(fft2(X,R,S) .* fft2(Z,R,S)));
n = ceil(([P Q] - 1)/2);
ind{1} = n(1) + (1:M);
ind{2} = n(2) + (1:N);
C2 = C2(ind{:});
err = immse(C1,C2)
我收到1e-26