FFT understanding

Dear all,

I have a more fundamental question about FFT.
I was reading up on FFT using http://cns-alumni.bu.edu/~slehar/fourier/fourier.html
I downloaded one of the sinusoidal images from this website and run FFT within Fiji on it.

Then I created a sinusoidal image by myself. FFT gives a more chessboard-like pattern.

I would like to understand why the FFT pattern of both images look so differently.

Thank you very much

You’re seeing this because ImageJ pads your image to a dimension of the closest power of 2 and fills the padded image with your image’s mean value, before doing the transform.
See https://github.com/imagej/imagej1/blob/master/ij/plugin/FFT.java#L165

So the FFT you’re seeing is from this image

If you use a square power of 2 wide image, you’ll get the expected result:

newImage("Untitled", "32-bit black", 256, 256, 1);
run("Macro...", "code=v=sin(x/6)");
setMinAndMax(200, 255);



Dear Jerome,

great, thank you very much! Would I need to pay attention on images having a 2^x size when using e.g. the Bandpass Filter?


Hi @aklemm

Previously there was a discussion on a similar issue here

The “next generation” imagej fft is being implemented using ops and imglib. The interfaces are being designed so that one can run it in “simple mode” where all the padding is done behind the scenes… or alternatively one can access the padding operations directly (so they can see what is going on behind the scenes).


Hi Brian,

thank you, also for pointing me to the other discussions! Very helpful.

Hi Anna,

you can use my FFT Box plugin (download at http://scepticalphysiologist.com/code/code.html) to get FFT spectra and FFT filter on images of any size (not just powers of two).


1 Like

Can you explain why the image (proper size) OP processed looks like continous line of points while yours has two points corresponding to the frequency of bands?

I understand yours but I don’t understand the OP’s result. I processed those bands myself and got same dashed line. Whats wrong with that image?


Hi @sonodelirii, welcome to the forum,

It may be that the scaling of intensities is deceiving… When I tried this:

Bad scaling:

Good scaling:

Hope this helps,

1 Like

Thank you bogovicj, that is a great point and not something that I considered.

However I am still struggling to interpret the FFT image. I am new to fourier space mathematics so feel free to point out basic things.

The spacing between the peaks is about 20 pixels and since the pattern is consistent so is the spacing between any of the other stripes of equal value.

Seems to me FFT image should only show 2 very well defined points correlating to that frequency, ~20 units per cycle.

But the FFT image suggests that lower and higher frequency information is present from 2 to 64 units per cycle but in nearly same rate of occurrence judging from relative brightness.

The reason I am digging in to this image so much is because I am trying to solve a more complex problem but wanted to work out all the problems that can occur with a more simple image.


Good day!

I fear you became a “victim” of the log-representation of the Fourier power spectrum.

Generally, logarithmic representations shouldn’t be used without specifying the “dynamic range”, i.e. the number of displayed decades. This is not done when using ImageJ’s FFT command. Consequently, numerical artifacts may be presented that may have various causes, e.g. rounding.

That said, I suspect you deal with spectral components that are in fact artifacts.

Here is a demo-macro that sets a defined number of displayed decades:

n = 128;
dec = 6;
newImage( "Grating", "32-bit black", n, n, 1 );
for ( j = 0; j < n; j++ ) {
	for ( i = 0; i < n; i++ ) {
		setPixel( i, j, 0.5*(1+cos( i * PI / 10.666666666666666 )) );
run( "FFT Options...", "raw do" );
run( "Square Root" );
rename( "AS of Grating" );
run( "Set... ", "zoom=400 x=" + n/2 + " y=" + n/2 );
run( "Duplicate...", "title=" + dec + "dec_log-AS of Grating" );
getRawStatistics( N, mn, mi, mx );
run( "Divide...", "value=" + d2s( mx, 9 ) );
run( "Log" );
run( "Multiply...", "value=" + d2s( 1 / log( 10 ), 9 ) );
setMinAndMax( -dec, 0 );
run( "8-bit" );
run( "Set... ", "zoom=400 x=" + n/2 + " y=" + n/2 );

(AS: Modulus of the Fourier Amplitude Spectrum.)
Please note that the three spectral amplitude values are 4096, 8192, 4096, just as the theory predicts:

With 6 displayed decades of the log-amplitude spectrum no spurious signals are displayed:

With 8 displayed decades of the log-amplitude spectrum you see them: