Correct usage of fft2 and fftshift for shape from shading

放肆的年华 提交于 2019-12-02 21:25:54

This is a tricky question because in general there is not a right answer. There may be some wrong answers though. I will try to explain. If the answer get a little bit too wordy, you can always just skip down to the summary section and see if it helps.

Gotchas

Gotcha #1:

When you use Matlab's fft (or in your case fft2) function, the first element of the output (in your case X(1,1)) represents the DC bias. If you subsequently call fftshift on your output, everything gets shifted around in a way that places the DC bias at the center. In the 2-dimensional case, it looks something like this:

Notice that the point that was at the top-left corner of block 1 gets moved to the center. While this is a perfectly valid representation of the data, we have to be careful because we have changed the meaning of the (1,1) bin. If I were to attempt an inverse transform at this point, the output would be wrong!

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

Gotcha #2:

The ifftshift function should be thought of as the inverse of the fftshift operation. It should not be thought of as a shift that applies to ifft operation. For this reason, I feel that the function names are very misleading.

In my experience, it is most common for an ifftshift to precede an fft/ifft function, and for an fftshift to follow fft/ifft function. In fact, I would go so far as to say that if you ever find yourself doing one of the following things, you have probably made a mistake:

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

The following helpful note is found in the Matlab documentation for ifftshift

Note: ifftshift will undo the results of fftshift. If the matrix X contains an odd number of elements, ifftshift(fftshift(X)) must be done to obtain the original X. Simply performing fftshift(X) twice will not produce X.

For example:

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

Gotcha #3:

The DFT has many interesting properties, one of which is that the DFT of a real, even sequence is real and even. We can often use this fact as a simple sanity check. If we put a real, even sequence into the fft function and get back something back that is not real and even, we have a problem.

We must take careful note of what an even function looks like when it comes to the DFT. The sequence 3 2 1 0 1 2 3 appears to be even, right? The left half is a mirror image of the right half. This would be true if the fourth element of the sequence represented t=0. However, because of the way the FFT algorithm is set up, the first element always represents the t=0 element.

We can remedy the problem by performing an ifftshift operation before the FFT in order to shift the center to the first element. Note that for a sequence with even length, the element x[N/2+1] is assumed to be the center.

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

As you can see by the last example, it would be incorrect to say "always use ifftshift before fft." What if the first element of my data is already the t=0 element? Then applying ifftshift would be the wrong thing to do.

Summary

In general, ifftshift should only be used before applying an fft/ifft. The fft and ifft functions always assume that the first element of your data represents t=0 and f=0 respectively. The main question you should ask yourself when using these functions is "where does t=0 (or f=0) live in my data?" and "Where do I want them to live?"

In general, fftshift should only be used after applying an fft/ifft. The output of these functions is given such that the first element represents f=0 and t=0 respectively. If you want to rearrange your data such that the f=0 and t=0 elements appear in the center, then fftshift is the right answer.

Without having a more thorough understanding of exactly what the data you are working with represents, it would be impossible to say whether any ifftshift or fftshift functions are necessary. Note that there are many situations in which one might use fft/fft2 and ifft/ifft2 correctly without ever needing to invoke fftshift or ifftshift.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!