Macro to zero pad image

Hi,

I’m trying to create a simple macro that takes the open image (let’s pretend its 256x256 for this example), calculates the FFT of that image, zero padds it to be 512x512 (by altering the canvas size), then takes the inverse FFT.

I would expect the result to be a 512x512 image that consists of the same Fourier coefficients, only interpolated to at finer pixel spacing.

Here is the simple macro I’m trying to use:
fft(‘foreward’);
run(“Canvas Size…”, “width=512 height=512 position=Center zero”);
fft(‘Inverse’);

However, the output image size is 256x256 (same as the original image)

Why does the inverse FFT not operate on the 512x512 image?

More importantly: how can I get it to return the 512x512 inverse FFT of the zero padded image?

Hi Scott,

the FFT display is only a graphical representation of the power spectrum (log scaled, for better visibility of weak components, no phase information). The actual data are hidden in the background and not affected by the image manipulation. You can get the actual Fourier-domain data with checking “Complex Fourier transform” or “Fast Hartley transform” in the FFT Options. As far as I can say, without Java or JavaScript programming, you can’t do a back transform after modifying one of these.
Here is a JavaScript example:

imp = IJ.openImage("http://wsr.imagej.net/images/blobs.gif");
IJ.run(imp, "32-bit", "");
imp = imp.resize(256, 256, "bilinear");
(new FHT).rc2DFHT(imp.getProcessor().getPixels(), false, 256);
IJ.run(imp, "Swap Quadrants", "");
IJ.run(imp, "Canvas Size...", "width=512 height=512 position=Center zero");
IJ.run(imp, "Swap Quadrants", "");
(new FHT).rc2DFHT(imp.getProcessor().getPixels(), true, 512);
imp.show();

I did not care about fixing the range (after upscaling by a factor of 4 in area, one would have to multiply the pixel values by 4) and the progress bar.

You will see ringing (ripples) at the edges, because the image has no continuous continuation when it is periodically repeated. Enlarging this way is not a general-purpose method, only for images with periodic boundary conditions or where the image values are constant (e.g., 0) at the borders.

–Michael

Ooops, correction, Herbert Glünder just told me that “Inverse FFT” also works on the complex Fourier transform, so it is doable via a macro (or interactively). Here is his code for an image of 256x256 pxl:

run("FFT Options...", "complex do");
run("Canvas Size...", "width=512 height=512 position=Center zero");
run("Inverse FFT");
setSlice(2);
run("Delete Slice");

The 2nd slice of the result would be the imaginary part of the output image. Since scaling a real image results in a real image, the imaginary it only contains numerical noise.

–Michael

1 Like

That works perfectly. Now I just need to close the extra windows that popup and put the script in batch mode so the screen won’t flicker. This is so helpful - Thanks!

In the latest ImageJ daily build (1.53a12) you can use “Inverse FFT” with the Fast Hartley Transform, which is faster and does not require a stack. The daily build also fixes a bug that caused the “Inverse FFT” output to be cropped. Here is an example:

  run("Boats (356K)");
  run("Size...", "width=256 height=256");
  run("FFT Options...", "fast do");
  run("Canvas Size...", "width=512 height=512 position=Center zero");
  run("Inverse FFT");

The macro works great for a 256x256 image - it calculates a 256x256 FFT, zeropads it to 1024x1024, then takes an IFFT that is 1024x1024. Vioala - an interpolated image!

However, if I use the macro on a 536x640 image, the FFT calculation returns a 1024x1024 image (no need to zeropad). Then even more surprisingly, when I take the IFFN, it goes back to 536x640 (whether I ask to zeropad or not)!?!!?

Can someone explain what is different here? I’m assuming it something to do with the image dimmensions not being powers of two and the dimmensions not being equal. Is there a workaround that will allow me to zeropad these in the frequency domain in order to interpolate in image domain?

To summarize what I’m looking for: I want to take an NxM image, take the FFT (should also be NxM in my mind), zeropadd that to 1024x1024, then take the IFFT giving an interpolated 1024x1024 image.

Thanks!

ImageJ stores the original image size as “FFT_width” and “FFT_height” image properties and uses this information to crop the inverse transformed image. To prevent the cropping, set the “FFT_width” property to an empty string, as in this example, which requires the 1.52a18 daily build.

  run("Gel (105K)");
  run("FFT Options...", "fast do");
  run("Canvas Size...", "width=1024 height=1024 position=Center zero");
  Property.set("FFT_width", "");
  run("Inverse FFT");