3
$\begingroup$

I have the following image: img = Import["https://i.imgur.com/Peu6mwd.png"]

Each column shows the y coordinate of some objects (each row is 0.012 mm apart) and the horizontal coordinate corresponds to the time (one column is 1/35 sec). One can see a general drift from top to bottom with time.

Expressed in plot with axes this is:

enter image description here

I want to display an image showing the FFT amplitudes vs. frequency for each y coordinate.

My code is the following:

img = Import["https://i.imgur.com/Peu6mwd.png"];

{dimx, dimy} = ImageDimensions[img]; 

dy = 0.012; 
dt = 1/35; 

fftData = Abs[Fourier[Flatten@ImageData@ImageTake[img, {#, #}, {0, All}], 
     FourierParameters -> {-1, 1}]] & /@ Range[dimy]; 

fftImg = 
 ImageTake[Image@Rescale[fftData, {0.00001, 0.005}], 
  All, {1, dimx/2}]; 

Graphics[
 Inset[Colorize[fftImg, ColorFunction -> "Rainbow"], Scaled[{.5, .5}],
   Automatic, Scaled[1]], Frame -> True, 
 FrameLabel -> {{"y (mm)", ""}, {"f (Hz)", ""}}, 
 PlotRange -> {{0, 35/2}, {0, dimy*dy}}, 
 AspectRatio -> ImageAspectRatio@fftImg]

which gives:

enter image description here

Do you know a better solution especially to replace the calculation of fftData?. IDL e.g. allows to call the FFT with dimension=1. I did not find any integrated mathematica function.

$\endgroup$
3
  • 3
    $\begingroup$ "Better" in what way? Faster? Smaller? More colors? Something else? What is the metric for "Better" in your context? $\endgroup$ Nov 30, 2016 at 17:14
  • 1
    $\begingroup$ I don't think you need ImageTake. Just use Fourier /@ ImageData[img] to transform every row in your image or Transpose[Fourier /@ Transpose[ImageData[img]]] to transform every column. (I have no idea what the rest of the code does.) $\endgroup$ Nov 30, 2016 at 20:04
  • 1
    $\begingroup$ Use Map. fft=Rescale[Abs[Fourier[#,FourierParameters->{-1,1}]&/@data][[All,1;;Floor[dimx/2]]],{0.00001,0.005}]; Colorize[Image[fft],ColorFunction->"Rainbow"] $\endgroup$ Nov 30, 2016 at 20:32

1 Answer 1

3
$\begingroup$

Here's a way that's pretty close to your approach:

img = Import["https://i.imgur.com/Peu6mwd.png"];
imgData = ImageData[img];
imgDims = Dimensions[imgData];
all = Table[fft = Abs[Fourier[imgData[[i]]]]; fft[[1]] = 0;
   fft[[1 ;; 50]], {i, 1, imgDims[[1]]}];
MatrixPlot[all, AspectRatio -> 1/2] // ImageAdjust

enter image description here

Each row shows the FFT of the corresponding row of the image. This sets the first coefficient to zero because it was large and made the details harder to see. It also plots just the first 50 terms because after about 100 there is not much to see.

$\endgroup$
1
  • $\begingroup$ Thank you, this is very nice solution. $\endgroup$
    – mrz
    Dec 1, 2016 at 0:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.