从阴影中正确使用fft2和fftshift的形状

时间:2013-10-25 14:42:06

标签: matlab computer-vision fft shape ifft

我试图从Trucco / Verri文本“3D计算机视觉的入门技术”中看到的着色算法重新创建经典形状,但我很难理解matlab中的fft函数。基本上,我需要使用可积性约束来获得图像的深度(Z)。在这种情况下,我不确定何时使用fftshift。这是我到目前为止的代码。基于http://www.mathworks.com/matlabcentral/newsreader/view_thread/285244 我基本上将所有的fft2都包裹在fftshifts中,但我不认为这是正确的用法。有人可以向我解释一下使用情况以及我做错了什么吗?谢谢。基本上,我试图将我的p和q(基于像素强度的更新值)转换为傅里叶域,以便在方程C中使用它们。然后我想将方程C转换回时域因为那会给我Z的深度。我还想根据傅里叶域中的C更新P和Q.

    wx = (2.* pi .* x) ./ m; 
    wy = (2.* pi .* y) ./ n; 
    wx = ifftshift(wx); wy=ifftshift(wy);

    Cp = fftshift(fft2(fftshift(p))); 
    Cq = fftshift(fft2(fftshift(q)));
    C = -1i.*(wx .* Cp + wy .* Cq)./(wx.^2 + wy.^2); 
    Z = abs((ifft2(ifftshift(C)))); 
    p = ifftshift(ifft2(ifftshift(1i * wx .* C))); 
    q = ifftshift(ifft2(ifftshift(1i * wy .* C)));

1 个答案:

答案 0 :(得分:13)

这是一个棘手的问题,因为一般来说没有正确的答案。可能有一些错误的答案。我会尽力解释。如果答案有点过于冗长,您可以随时跳到摘要部分,看看是否有帮助。

陷阱

陷入困境#1:

当您使用Matlab的fft(或在您的情况下为fft2)函数时,输出的第一个元素(在您的情况下为X(1,1))代表DC bias。如果您随后在输出上调用fftshift,则所有内容都会以将DC偏置置于中心的方式移动。在二维情况下,它看起来像这样:

2-Dimensional fftshift

请注意,块1左上角的点移动到中心。虽然这是数据的完全有效表示,但我们必须小心,因为我们已经更改了(1,1)bin的含义。如果我此时尝试逆变换,输出将是错误的!

B = ifft2(fft2(A));            % B is equal to A
C = ifft2(fftshift(fft2(A)));  % C is not equal to A

陷阱#2:

ifftshift函数应该被认为是fftshift操作的反函数。不应将其视为适用于ifft操作的转变。出于这个原因,我觉得函数名称非常容易引起误解。

根据我的经验,最常见的是ifftshift 在<{1}} / fft函数之前ifftfftshift按照fft / ifft功能操作。事实上,我甚至会说,如果你发现自己做了下列事情之一,你可能犯了一个错误:

B = ifftshift(ifft(A));        % Don't do this
C = fft(fftshift(A));          % Don't do this either

以下有用的说明可在Matlab documentation for ifftshift

中找到
  

注意: ifftshift将撤消fftshift的结果。如果矩阵X包含奇数个元素,则必须执行ifftshift(fftshift(X))才能获得原始X。简单地执行fftshift(X)两次就不会产生X

例如:

B = ifftshift(fftshift(A));    % B is equal to A
C = fftshift(fftshift(A));     % C is not equal to A

陷阱#3:

DFT有许多有趣的属性,其中之一就是真实的偶数序列的DFT是真实的和偶数的。我们经常可以将此事实用作简单的健全性检查。如果我们在fft函数中放入一个真实的偶数序列并返回一些不真实甚至是真实的函数,那么我们就会遇到问题。

我们必须仔细注意在DFT时偶数函数的样子。序列3 2 1 0 1 2 3似乎是偶数,对吧?左半部分是右半部分的镜像。如果序列的第四个元素表示t=0,则为真。但是,由于FFT算法的设置方式,第一个元素始终代表t=0元素。

我们可以通过在FFT之前执行ifftshift操作来解决问题,以便将中心移动到第一个元素。请注意,对于长度均匀的序列,假设元素x[N/2+1]为中心。

A1 = [ 3 2 1 0 1 2 3 ];        % A1 real, even sequence about A1(4)
B1 = fft(ifftshift(A1));       % B1 is a real, even sequence
C1 = fft(A1);                  % C1 is _not_ a real, even sequence
abs(B1) == abs(C1)             % B1 and C1 differ only in phase

A2 = [ 0 1 2 3 3 2 1 ];        % A2 real, even sequence about A2(0)
B2= fft(ifftshift(A2));        % B2 is _not_ a real, even sequence
C2= fft(A2);                   % C2 is a real, even sequence
abs(B2) == abs(C2)             % B2 and C2 differ only in phase

正如您在上一个示例中所看到的那样, 不正确 表示“ 始终 使用{在ifftshift之前{1}}。“如果我的数据的第一个元素已经是fft元素怎么办?然后应用t=0将是错误要做的事情。

摘要

一般情况下,ifftshift只应在应用ifftshift / fft之前使用ifftfft函数始终假设数据的第一个元素分别代表ifftt=0。使用这些功能时应该问自己的主要问题是“f=0(或t=0)在我的数据中的位置?”和“我希望他们在哪里生活?”

一般情况下,f=0只应在申请fftshift / fft后使用。给出这些函数的输出,使得第一个元素分别代表ifftf=0。如果您要重新排列数据,以便t=0f=0元素出现在中心,那么t=0就是正确答案。

如果没有更准确地了解您正在使用的数据代表什么,就无法说明是否需要任何fftshiftifftshift函数。请注意,在许多情况下,人们可以正确使用fftshift / fftfft2 / ifft,而无需调用ifft2或{{1} }。