2013-10-25 26 views
3

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

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))); 
+0

如果你可以多说一点你正在做的事情,这将有所帮助。就目前而言,您的代码将无法运行,并且没有任何关于这些代码片段的含义。 – nispio

+0

嗨,我添加了一些代码的解释,我希望现在更清楚,基本上我想将p和q转换为傅立叶域,在傅立叶域中创建另一个方程C,然后返回到时域和方程C应该给Z. – user2009114

回答

13

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

陷阱

疑难杂症#1:

当您使用Matlab的fft(或你的情况fft2)功能,输出的第一个元素(在你的情况X(1,1))表示DC bias。如果您随后在输出端上拨打fftshift,则所有情况都会以DC偏置为中心的方式转移。在二维情况下,它看起来是这样的:

2-Dimensional fftshift

请注意,这是在框的左上角点被移到中央。虽然这是一个完全有效的数据表示,但我们必须小心,因为我们有更改了(1,1)箱的含义。如果我在这一点上尝试进行逆变换,那么输出结果就会错误!

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 

你可以通过最后一个例子中看到的,这将是不正确说 “总是使用ifftshiftfft之前。”如果我的数据的第一个元素已经是t=0元素,该怎么办?然后申请ifftshift将是错误事情要做。

摘要

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

一般来说,fftshift应该只施加fft/ifft后使用。这些函数的输出被赋予这样的第一要素分别为f=0t=0代表。如果你想重新排列数据,使得f=0t=0元素出现在中央,然后fftshift是正确的答案。

不具有正是你正在使用的数据代表了更深入的了解,这将是很难说是否有任何ifftshiftfftshift个功能是必要的。请注意,有很多情况下,您可以正确使用fft/fft2ifft/ifft2而无需调用fftshiftifftshift

+0

如果矩阵具有偶数维,似乎fftshift(fftshift(A))等于原始矩阵A. ifftshift(ifftshift(A))也是一样。 – Arturo

+0

最后一个例子中的错字? B2 = fft(ifftshift(A)); - > B2 = fft(ifftshift(A2)); – Dov

+0

@Dov我想是的,谢谢。固定。 – nispio