简单的问题:
我在Matlab中绘制出具有一定分辨率的2D高斯函数。我测试方差或西格玛= 1.0。我想将它与FFT(高斯)的结果进行比较,后者应该产生另一个高斯,其方差为(1./sigma)。由于我使用sigma = 1.0进行测试,我认为我应该得到两个等效的2D内核。
即
g1FFT = buildKernel(rows, cols, mu, sigma) % uses normpdf over arbitrary resolution (rows, cols, 3) with the peak in the center
buildKernel:
function result = buildKernel(rows, cols, mu, sigma)
result = zeros(rows, cols, 3);
center_w = floor(cols / 2);
center_h = floor(rows / 2);
for i = 1:rows
for j = 1:cols
distance = sqrt((center_w - j).^2 + (center_h - i).^2);
g_val = normpdf(distance, mu, sigma);
result(i, j, :) = g_val;
end
end
% normalize so that kernel sums to 1
sumKernel = sum(result(:));
result = result ./ sumKernel;
end
我正在测试mu = 0.0(总是),方差或sigma = 1.0。我想将它与FFT(高斯)的结果进行比较,后者应该产生另一个高斯,其方差为(1./sigma)。
即。
g1FFT = circshift(g1FFT, [rows/2, cols/2, 0]); % fft2 expects center to be in corners
freq_G1 = fft2(g1FFT);
freq_G1 = circshift(freq_G1, [-rows/2, -cols/2, 0]); % shift back to center, for comparison's sake
由于我使用sigma = 1.0进行测试,我认为我应该得到两个等效的2D内核,因为如果sigma = 1.0,则1.0 / sigma = 1.0。因此,g1FFT将等于freq_G1。
然而,我没有。它们具有不同的大小,即使在归一化之后。有什么我想念的吗?
答案 0 :(得分:0)
为了简单起见,我将首先介绍一维信号的情况。可以对多维情况进行类似的观察。
连续时间高斯信号的傅立叶变换本身是高斯函数,如this table所示。可以注意到,时域中的高斯越宽,频域中的变换高斯越窄,μ= 0和sigma = 1 / sqrt(2π)(相当于a = 1 /(2 * sigma ^) 2)在上述变换表中=π),连续时间函数的傅立叶变换
将是类似的函数(只发生变量的变化):
这一切都很好,但这是连续时间信号,我们真的对谨慎的时间信号感兴趣。 不幸的是,并且如wikipedia所示,通过对连续时间高斯函数进行采样而获得的内核的离散傅里叶变换本身不是采样高斯函数。 幸运的是,这种关系通常仍然是近似真实的(没有太多细节,它要求时域内核足够宽但不能太宽,以至于频域近似也足够宽,以使关系也近似对于逆变换,则为true)。在这种情况下,离散时间信号的周期性扩展(具有周期N)的离散傅立叶变换
其中mu = 0且 sigma = sqrt(N /2π)可以用相似的函数近似(直到比例因子和变量的变化):
然后,您可以修改buildKernel
以分别支持行和列的不同标准差sqrt(rows /2π)和sqrt(cols /2π):
function result = buildKernel(rows, cols, mu, sigma)
if (length(mu)>1)
mu_h = mu(1);
mu_w = mu(2);
else
mu_h = mu;
mu_w = mu;
endif
if (length(sigma)>1)
sigma_h = sigma(1);
sigma_w = sigma(2);
else
sigma_h = sigma;
sigma_w = sigma;
endif
center_w = mu_w + floor(cols / 2);
center_h = mu_h + floor(rows / 2);
r = transpose(normpdf([0:rows-1],center_h,sigma_h));
c = normpdf([0:cols-1],center_w,sigma_w);
result = repmat(r * c, [1 1 3]);
% normalize so that kernel sums to 1
sumKernel = sum(result(:));
result = result ./ sumKernel;
end
您可以使用它来获取其FFT是其自身的缩放版本的内核。换句话说,使用
获得内核g1FFTin = buildKernel(rows, cols, mu, [sqrt(rows/2/pi) sqrt(cols/2/pi)]);
会freq_G1
(在您发布的代码中计算)几乎等于g1FFTin * sqrt(rows*cols)
。
最后鉴于你的意图实际上只是为了测试内核的FFT也是(近似)高斯,你可能希望将更多任意内核的FFT与标准偏差sigma
进行比较另一个< / em>在频域中直接计算的适当缩放的高斯核。换句话说,假设一个空间域内核得到:
g1FFTin = buildKernel(rows, cols, mu, sigma);
使用相应的频域表示获得:
g1FFT = circshift(g1FFTin, [rows/2, cols/2, 0]);
freq_G1 = fft2(g1FFT);
freq_G1 = circshift(freq_G1, [-rows/2, -cols/2, 0]);
然后可以将freq_G1
与直接在频域中计算的另一个适当缩放的高斯内核进行比较:
freq_G1_approx = (rows*cols/(2*pi*sigma^2))*buildKernel(rows, cols, mu, [rows cols]/(2*pi*sigma));