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

use*_*114 4 matlab fft shape computer-vision 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)));
Run Code Online (Sandbox Code Playgroud)

nis*_*pio 14

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

陷阱

陷阱#1:

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

二维ffthift

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

B = ifft2(fft2(A));            % B is equal to A
C = ifft2(fftshift(fft2(A)));  % C is not equal to A
Run Code Online (Sandbox Code Playgroud)

陷阱#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
Run Code Online (Sandbox Code Playgroud)

以下有用的注释可在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
Run Code Online (Sandbox Code Playgroud)

陷阱#3:

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

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

我们可以通过ifftshift在FFT之前执行操作来解决该问题,以便将中心移位到第一元素.请注意,对于具有偶数长度的序列,该元素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
Run Code Online (Sandbox Code Playgroud)

正如您在上一个示例中所看到的,说" 始终使用之前" 是不正确的.如果我的数据的第一个元素已经是元素怎么办?然后申请将是错误的事情.ifftshiftfftt=0ifftshift

摘要

通常,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.