/** This demonstrates using Fourier transforms to process an image, obtain its Fourier transform, display the Fourier transform in a logarithmic scale, and then invert the transform to produce the original image. */ // Image available at https://frinklang.org/frinksamp/AudreyHepburnMoire.jpg // It has a noisy Moire pattern img = new image["file:AudreyHepburnMoire.jpg"] // Comment in the resize below to test different image sizes. //img = img.resize[undef, 1024] [origWidth, origHeight] = img.getSize[] println["image size is [\$origWidth, \$origHeight]"] // Make the image into an efficient data structure (ComplexArray) and then // take its two-dimensional Fourier transform. array = img.toComplexArray[] ff = FFT[array] // Encode the image into an image that contains magnitude-phase components. // The magnitude is encoded into the green channel on a logarithmic scale, // and the phase is encoded into the red channel. // If the flag below is true, this assumes the DC component is in the // center of the image. This needs to match the value in the // .toComplexArrayFromLog call below. img2f = ff.toLogImage[true] println["Resultant image size from FFT is " + img2f.getSize[]] img2f.show["FFT Magnitude-Phase"] img2f.write["fft.png"] // Reverse the FFT of the image and display it. This is all done in memory // and should preserve the original image very closely. inverseF = inverseFFT[ff] inverseImgF = inverseF.toImage[origWidth, origHeight] inverseImgF.show["Inverse FFT"] inverseImgF.write["reconstructed.png"] // Reverse the magnitude-phase encoded image into the original image. This // has gone through a few levels of re-encoding, but the result should look // like the original image. // If the flag below is true, this assumes the DC component is in the // center of the image. This needs to match the value in the .toLogImage call // above. a2 = img2f.toComplexArrayFromLog[true] ia = inverseFFT[a2] back = ia.toImage[origWidth, origHeight] back.show["Inverse from FFT Magnitude-Phase image"]