4

我正在尝试从 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)));
4

1 回答 1

16

这是一个棘手的问题,因为通常没有正确答案。虽然可能有一些错误的答案。我会尽力解释。如果答案有点冗长,你可以直接跳到摘要部分,看看它是否有帮助。

陷阱

问题 #1:

当您使用 Matlab 的fft(或在您的情况下fft2)函数时,输出的第一个元素(在您的情况下X(1,1))表示DC 偏置。如果你随后调用fftshift你的输出,一切都会以一种将直流偏置置于中心的方式发生变化。在二维情况下,它看起来像这样:

二维 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运营的转变。出于这个原因,我觉得函数名称非常具有误导性。

根据我的经验,最常见的是 an位于/函数ifftshift之前, an位于/函数之后。事实上,我什至会说,如果你发现自己做了以下事情之一,那么你可能犯了一个错误:fftifftfftshiftfftifft

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

在Matlab 文档中可以找到以下有用的说明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

正如您在最后一个示例中看到的那样,说“总是在之前使用”是不正确的。如果我的数据的第一个元素已经是元素怎么办?那么申请将是错误的事情。ifftshiftfftt=0ifftshift

概括

一般来说,ifftshift应该只在应用/之前使用。和函数始终假定数据的第一个元素分别表示和。使用这些函数时,您应该问自己的主要问题是“ (或)存在于我的数据中的什么位置?” “我希望他们住在哪里?”fftifftfftifftt=0f=0t=0f=0

一般来说,fftshift应该只在应用/之后使用。给出这些函数的输出,使得第一个元素分别表示和。如果您想重新排列数据以使and元素出现在中心,那么这是正确的答案。fftifftf=0t=0f=0t=0fftshift

如果没有更彻底地了解您正在使用的数据究竟代表什么,就不可能说是否需要任何功能ifftshiftfftshift功能。请注意,在许多情况下,人们可能会正确使用fft/fft2ifft/ifft2而无需调用fftshiftor ifftshift

于 2013-10-26T22:27:15.890 回答