I am attempting to recreate a classical shape from shading algorithm seen in the Trucco/Verri text "Introductory Techniques for 3d Computer Vision", but I am having a hard time understanding the fft function in matlab. Essentially, I need to use the integrability constraint to get the depth (Z) of an image. I am not sure when to use fftshift or not in this scenario. Here is the code I have so far. Based on http://www.mathworks.com/matlabcentral/newsreader/view_thread/285244 I basically wrapped all my fft2s in fftshifts, but I don't think this is the correct usage. Could someone please explain to me the usage and what I am doing wrong? Thank you. Basically, I'm trying to take my p and q (values which are the updates based on pixel intensities) transform them into the Fourier domain so as to use them in the equation C. Then I want to transform the Equation C back to the time domain because that will give me Z the depth. I also want to update P and Q based on C in the Fourier Domain.
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)));
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 casefft2
) function, the first element of the output (in your caseX(1,1)
) represents the DC bias. If you subsequently callfftshift
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!
Gotcha #2:
The
ifftshift
function should be thought of as the inverse of thefftshift
operation. It should not be thought of as a shift that applies toifft
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 anfft
/ifft
function, and for anfftshift
to followfft
/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:The following helpful note is found in the Matlab documentation for
ifftshift
For example:
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 representedt=0
. However, because of the way the FFT algorithm is set up, the first element always represents thet=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 elementx[N/2+1]
is assumed to be the center.As you can see by the last example, it would be incorrect to say "always use
ifftshift
beforefft
." What if the first element of my data is already thet=0
element? Then applyingifftshift
would be the wrong thing to do.Summary
In general,
ifftshift
should only be used before applying anfft
/ifft
. Thefft
andifft
functions always assume that the first element of your data representst=0
andf=0
respectively. The main question you should ask yourself when using these functions is "where doest=0
(orf=0
) live in my data?" and "Where do I want them to live?"In general,
fftshift
should only be used after applying anfft
/ifft
. The output of these functions is given such that the first element representsf=0
andt=0
respectively. If you want to rearrange your data such that thef=0
andt=0
elements appear in the center, thenfftshift
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
orfftshift
functions are necessary. Note that there are many situations in which one might usefft
/fft2
andifft
/ifft2
correctly without ever needing to invokefftshift
orifftshift
.