【问题标题】:Correct usage of fft2 and fftshift for shape from shading从阴影中正确使用 fft2 和 fftshift
【发布时间】:2013-10-25 14:42:05
【问题描述】:

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

【问题讨论】:

  • 如果您能多说一点您正在尝试做的事情,将会有所帮助。就目前而言,您的代码将无法运行,并且没有任何关于片段含义的上下文。
  • 嗨,我添加了一些代码解释,希望现在更清楚,基本上我想将 p 和 q 转换为傅立叶域,在傅立叶域创建另一个方程 C 然后返回时域和方程 C 应该给出 Z。

标签: matlab computer-vision fft shape ifft


【解决方案1】:

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

陷阱

问题 #1:

当您使用 Matlab 的 fft(或在您的情况下为 fft2)函数时,输出的第一个元素(在您的情况下为 X(1,1))表示 DC bias。如果您随后在输出上调用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 最常见的是 fft/ifft 函数,fftshift 跟随 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

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

总结

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

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

如果不更彻底地了解您正在处理的数据究竟代表什么,就不可能说是否需要任何 ifftshift 或 fftshift 函数。请注意,在许多情况下,人们可能会正确使用 fft/fft2 和 ifft/ifft2,而无需调用 fftshift 或 ifftshift。

【讨论】:

  • 如果矩阵的维数是偶数,则 fftshift(fftshift(A)) 似乎等于原始矩阵 A。ifftshift(ifftshift(A)) 也是如此。
  • 最后一个例子中的错字? B2= fft(ifftshift(A)); --> B2= fft(ifftshift(A2));
猜你喜欢
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 2011-12-06
相关资源
最近更新 更多