1

我正在为一个类编写一个 c++ 程序来在频域中进行卷积,我注意到最终结果在拐角处有错误。所以我在 MATLAB 中进行了尝试,得到了完全相同的结果。例如

使用来自http://engronline.ee.memphis.edu/eece7214/images/Downlodable.htm的摄影师

我做了

a = imread('cameraman.pgm');
h = ones(25,25)/25/25;
a(512,512) = 0;
h(512,512) = 0;
c = ifft2(fft2(a).*fft2(h))/256;
c = c(1:256, 1:256);
c = real(c);
imwrite(c,'test2.png')

在提取左上角之前,我看了看 c,发现它与 imfilter(a, h) 的答案相同,只是它从角落翻译了一点点。冈萨雷斯的数字图像处理对此只字未提,谷歌在没有任何帮助的情况下让我的眼睛因搜索而流血(每个人都重复冈萨雷斯给出的提取左上角的相同指令)。

与主要问题无关,我还想知道为什么我必须在这个 MATLAB 代码中除以 256。在我的 C++ 代码中,我不必对结果进行缩放,得到的答案与此 MATLAB 代码相同。

编辑:我做了一点一维向量的玩弄(做 conv 和 ifft(fft*fft)),我认为“错误”来自显示左上角的“完整”卷积的输出,而不是“相同”的卷积。但即使是这种情况,我也不确定如何确定性地编码“提取这部分只是为了得到'相同'而不是'完整'的左上角 256x256 部分”

编辑:更多的谷歌搜索通过http://jeremy.fix.free.fr/IMG/pdf/fftconvolution.pdf产生了一个可能的解决方案。它有很多我以前从未见过的数学符号,但据我所知,如果你正在卷积 nxn 和 mxm,请提取 m:(m+n-1) 以从fft 近似。我仍然想听听比我更专业的人的意见,所以不要选择不根据此更新发表评论!

4

2 回答 2

2

MATLAB 索引数组从 1 到 N。
规范 C 用法(和大多数 C 矩阵数学库)索引数组从 0 到 N-1。这可能是一对一差异的根源。

要成为一个身份,裸 ifft(fft(x)) 算法在某处需要 1/N 的比例因子。一些 C 库将 1/N 放在 fft() 中。许多人将比例因子构建到 ifft() 中。有些人在两者中都放了 1/sqrt(N)。有些不添加内置比例因子,要求用户根据需要进行缩放以获得身份。

于 2011-10-01T05:31:33.410 回答
0

您需要将其移动一半的窗口大小。在这种情况下,您应该这样做: c = c(13:256+12,13:256+12); 而不是: c = c(1:256, 1:256);

您正在用零填充信号,但没有得到任何使用,因为您将信号从 1 带到 256 - 您仍然在边缘有抖动,在右边角落有有价值的信号,您会丢失。

于 2014-04-28T11:04:05.323 回答