-4

i am trying to plot the figure of FFT magnitude of an image using the following code in the command window:

a= imread('lena','png')
figure,imshow(a)
ffta=fft2(a)
fftshift1=fftshift(ffta)
magnitude=abs(fftshift1)
figure,imshow(magnitude),title('magnitude')

However, the figure with the title magnitude shows nothing, even though MATLAB shows that it has computed abs() on fftshift. The figure is still empty, and there is no error. Also, why do we need to compute the phase shift before magnitude?

rayryeng
  • 102,964
  • 22
  • 184
  • 193
newbie
  • 1
  • 1
  • thanks for editing the post @luismendo .would u please let me know why have you flagged the question down .if you know the answer .please share.if you have not than i am sorry but i do need the answer.second what formatting did you use for the code. i am pretty new here – newbie Aug 24 '14 at 18:09
  • 2
    I didn't flag your question, but I suspect that you got downvoted because your code is not reproducible. We aren't able to reproduce the results on our end because you didn't provide the image you used to produce the problem. However, I have provided an answer as your symptoms are very common when dealing with the FFT for first time users. Good luck! – rayryeng Aug 24 '14 at 18:11
  • 3
    I did downvote. A vote down means "The question doesn't show research or effort; it's unclear or not useful". In your case, I find the question unclear, and not showing much effort. Is the image b/w or color? (If color, do you know what you're doing when you apply `fft2`?) Ideally provide the image so that we can reproduce the problem. As for formatting code, there's a button in the toolbar for that. Or simply add four spaces before each line. Don't be discouraged by downvotes; you'll learn how to make a good question – Luis Mendo Aug 24 '14 at 19:01
  • @luis i cannot add an image because i dont have 10 reputation to post – newbie Aug 24 '14 at 19:29
  • @newbie I hope you get that rep soon. Meanwhile, you can use some external image sharing service. – Luis Mendo Aug 24 '14 at 19:33
  • @LuisMendo yes luis i know what i was trying to do when i was applying fft ,i was trying to see how the spatial points are represented by frequency .the concept of dct and its best computational relative fft,have plagued my progress for quiet some time. – newbie Aug 24 '14 at 22:08
  • 1
    @newbie What I meant is: when applying the FFT to a _color_ image, Matlab computes the FFT of each color component separately, which might or might not be what you want – Luis Mendo Aug 24 '14 at 22:32
  • @LuisMendo it is a good discussion. atleast i know want you look for .well i only posted this question here when i ran out of luck on web options,cuz,neither the color nor the b/w image was working with the online code and there tweaks.and i didnt know where the problem was.so i pruned the code to the very basic.and made it too neat. – newbie Aug 28 '14 at 09:57

2 Answers2

3

The reason why this is probably happening is because of the following things:

  1. When you take the 2D fft of your image, it will produce a double valued result, even though your image is mostly unsigned 8-bit integer. MATLAB assumes that double formatted images have their intensities / colours between [0,1]. By doing imshow on just the magnitude itself, you will most likely get an entirely white image because I suspect a good majority of the FFT coefficients are bigger than 1. This is probably the blank figure that you're referring to.
  2. Even if you rescale the magnitude so that it is between [0,1], the DC coefficient will be so large that if you try to display the image, you'll only see a white dot in the middle while every other component will be black.

As a side note, the reason why you are doing fftshift is because by default, MATLAB assumes that the origin of the FFT for 2D is located at the top left corner. Doing fftshift will allow the origin to be in the middle, which is what we would intuitively expect of the 2D FFT.


In order to remedy this situation, I would suggest doing a log transformation on the FFT coefficients so you can visually see the results. I would also normalize the coefficients once you log transform it so that they go between [0,1]. Do not actually modify the FFT coefficients as this would be improper. You need to leave them the same way that it is because if you intend to do any processing on the spectrum, you would start by working on the raw image. Doing filter design or anything of that sort will require the raw spectrum, as the final filter will depend on these coefficients untouched. Unless you actually want to do a log operation as part of your pipeline, then leave these coefficients as is. As such, this can be done through the following MATLAB code:

imshow(log(1 + magnitude), []);

I'm going to show an example, using your code that you have provided but using another image as you haven't provided one here. I'm going to use the cameraman.tif image that's part of the MATLAB system path. As such:

a= imread('cameraman.tif');
figure,imshow(a);
ffta=fft2(a);
fftshift1=fftshift(ffta);
magnitude=abs(fftshift1);
figure;
imshow(log(1 + magnitude), []); %// NEW
title('magnitude')

This is what I get:

enter image description here

enter image description here


As you can see, the magnitude is displayed more nicely. Also, the DC coefficient is in the middle of the spectrum thanks to fftshift.


If you want to apply this for colour images, fft2 should still work. It will apply the 2D fft to each colour plane by itself. However, if you want this to work, you'll not only need to take the log transform, but you'll also need to normalize each plane separately. You have to do this because if we tried doing the imshow command we did earlier, it would normalize it so that the greatest value in the spectrum of the colour image gets normalized to 1. This will inevitably produce that same small dot effect that we talked about earlier.

Let's try a colour image that's built-in to MATLAB: onion.png. We will use the same code that you used above, but we need an additional step of normalizing each colour plane by itself. As such:

a = imread('onion.png');
figure,imshow(a);
ffta=fft2(a);
fftshift1=fftshift(ffta);
magnitude=abs(fftshift1);
logMag = log(1 + magnitude); %// New
for c = 1 : size(a,3); %// New - normalize each plane
    logMag(:,:,c) = mat2gray(logMag(:,:,c));
end
figure; imshow(logMag); title('magnitude');

Note that I had to loop through each colour plane and use mat2gray to normalize each plane to [0,1]. Also, I had to create a new variable called logMag because I have to modify each colour plane individually, and you can't do this with a single imshow call.

With this, these are the results I get:

enter image description here

enter image description here

What's different with this spectrum is that we are applying the FFT to each colour plane separately, and so you'll see a whole bunch of colour spatters because for each location in this image, we are visualizing a linear combination of components from the red, green and blue channels. For each location, we have a value in between [0,1] for each colour plane, and the combination of these give you a colour at this location. You could say that darker colours are for locations that have a relatively low magnitude for at least one of the colour channels, while locations that are brighter have a relatively high magnitude for at least one of the colour channels.

Hope this helps!

rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • thanks alot for such a descriptive reply @ray but i already had tried it .but i tried it again and with this added i am getting the error check display range: high must be greater than low. but there is one thing i am using a colored image instead of a black and white one – newbie Aug 24 '14 at 18:31
  • 2
    @newbie - You **can't** do this on a colour image as that would be a 3D matrix. `fft2` stands for **two-dimensional** FFT. That's the reason why it doesn't work. You either have to apply the FFT on each colour plane separately, or convert the image into grayscale through `rgb2gray` then run the code again. This is why you got downvoted - you didn't give us enough information to diagnose your problem. Instead of me wasting effort in helping you, I would have suggested something completely different if I knew your image was in colour. – rayryeng Aug 24 '14 at 18:34
  • +1 for detailed answer to an unclear question. BTW, `fft2` applied on a colour image automatically works on each color separately, doesn't it? – Luis Mendo Aug 24 '14 at 19:06
  • 1
    @LuisMendo - I was actually curious and I looked at the `fft2` and you're right. It actually calls `fftn` under the hood. As such, I don't know why the OP can't get the stuff to work if they (claimed to) have tried what I suggested. Ah well. Good call! – rayryeng Aug 24 '14 at 19:09
  • @rayryeng You deserved it (in my opinion) :-) – Luis Mendo Aug 24 '14 at 19:31
  • i got the same error with a greenchurch black and white image but not with the cameraman.tif one.it produced the same result mentioned here but the matlab complained about the image being too big(greenchurch) @ray – newbie Aug 24 '14 at 19:38
  • @newbie - How big is this image? What's the resolution? – rayryeng Aug 24 '14 at 19:40
  • @newbie - I figured it out. For colour images, you need to normalize each plane individually. I'll add some more edits. Check my edited post. – rayryeng Aug 24 '14 at 19:43
  • @LuisMendo - Thanks :) I think I figured out the problem. We need to normalize each colour plane separately. I added some more edits. – rayryeng Aug 24 '14 at 19:48
  • @ray the greenchurch.png(black and white) is 1200*900pix ,whereas cameraman.tif is 421*342pix. i am using matlab 2009b – newbie Aug 24 '14 at 19:57
  • @newbie - That's weird. It may be your MATLAB version, or it may be just too large. – rayryeng Aug 24 '14 at 20:06
  • @ray i tried your normalized plane edited code.and it is working on a colored image of size 512*512 pix ,sorry i cannot vote for u cuz i need 15 rep for that.but i like your answer so i am appreciating your effort in writing ,how ever the log function you mentioned in the previous code is still giving me the same checkdisplayrange error and without log () function it is giving me a blank screen.i think it is the scaling problem.i am mentioning all this so that it can be helpful to someone else. nimrodm code did produce some widely sparse dots as a result. – newbie Aug 24 '14 at 21:44
0

Can't be sure about your version of "lena.png", but if it's a color RGB picture, you need to convert it first to grayscale, or at least select which RGB plane you want to examine.

I.e., the following works for http://optipng.sourceforge.net/pngtech/img/lena.png (color png):

clear; close all;

a  = imread('lena','png');
ag = rgb2gray(a);
ag = im2double(ag);

figure(1);
imshow(ag);

F = fftshift( fft2(ag) );  % also try fft2(ag, N, N) where N < image size. Say N=128.
magnitude=abs(F);

figure(2);
imshow(magnitude);
nimrodm
  • 23,081
  • 7
  • 58
  • 59
  • i tried your code too .im2double is a good edition it handles the image scaling problem(sorry i cannot vote unless i have 15 reps) . i have just one question why is the magnitude representation so sparse(far seperated dots).usually the representation is somewhat like a bright spot at the center on a black or gray screen, just curious – newbie Aug 24 '14 at 22:17