## Tests Of Processing Using Sean Burke's IMFFT With IM Q16

#### Images Displayed Below Are Often JPG, But Processing Was Done As PNG or TIFF To Preserve Quality

 Simple FFT/IFT Round Trip FFT to produce tiff stack of frames: path-to-imfft/trunk/demo f lena.png IFT of tiff stack to regenerate image: path-to-imfft/trunk/demo i lena_F_Q16.tiff original image roundtrip result compare -metric rmse lena.png lena_F_Q16_rt_Q16.tiff null: 128.13 (0.00195514) compare -metric psnr lena.png lena_F_Q16_rt_Q16.tiff null: 54.1765

 Simple Binary Square Pattern - Demo Magnitude And Phase Of FFT original image FFT to produce tiff stack of frames: path-to-imfft/trunk/demo f square30.png Then create magnitude and phase (below): convert square30_F_Q16.tiff[0] square30_F_Q16.tiff[2] \ square30_F_Q16.tiff[4] square30_mag.png convert square30_F_Q16.tiff[1] square30_F_Q16.tiff[3] \ square30_F_Q16.tiff[5] square30_phase.png Linearly Stretch Magnitude: min->0%, max->100% convert square30_F_Q16_mag.png -contrast-stretch 0% square30_F_Q16_mag_cs0.png Generate Spectrum From Magnitude (scale=100): convert square30_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(99*u+1)/log(100)" -fill "rgb(1,1,1)" \ -opaque black square30_F_Q16_spec100.png Generate Spectrum From Magnitude (scale=1000): convert square30_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(999*u+1)/log(1000)" -fill "rgb(1,1,1)" \ -opaque black square30_F_Q16_spec1000.png Generate Nearly Equivalent Spectrum, But Faster: convert square30_F_Q16_mag.png -contrast-stretch 0% \ -gamma 2.5 -fill "rgb(1,1,1)" -opaque black \ square30_F_Q16_spec_g2p5.png Generate Nearly Equivalent Spectrum, But Faster: convert square30_F_Q16_mag.png -contrast-stretch 0% \ -gamma 3.5 -fill "rgb(1,1,1)" -opaque black \ square30_F_Q16_spec_g3p5.png

 Simple Patterns - Demo Of Spectra Concepts High frequencies in the FFT (corresponding to rapidly varying intensities in the original image) lie near the outer parts of the spectrum. Low frequencies in the FFT (corresponding to slowly varying intensities in the original image) lie near the center of the spectrum. The zero frequency (DC) point in the spectrum for an NxM original image lies at coordiniage N/2-1,M/2 in the spectrum image. The intensity value in the magnitude image at the DC point is equal the average graylevel in the original image. Edges in an image give rise to transform components lying along lines perpedicular to the edges. Smaller objects have more spread-out transforms; Larger objects have more compressed transform. The transform of uniform object lies along a line perpendicular to the dimension of the object. Gratings (evenly repeated grid lines) produce an array of dots perpendicular to the grating lines. The transform of a constant rectangle of dimension x=a,y=b in image an size NxM is a sinc function: sinc(pi*a/N)*sinc(pi*b/M), where sinc(x)=sin(x)/(x). The spacing between the troughs in the spectrum will be Dx=N/a and Dy=M/b. The transform of a constant circle of diameter d in an image size NxN is a jinc function: jinc(pi*d/N), where jinc(x)=J1(r)/(r) and J1(r) is the Bessel function of the first kind of order one. The spacing from the center to the first trough in the spectrum will be Dr=1.22*N/d. The transform of a Gaussian (Normal) function of sigma=d in an image size NxN is a Gaussian function. The sigma of the Gaussian function in the spectrum will be sigma=N/d. The transform of a set of grid lines of spacing x=a,y=b in image size NxM is an array of dots: The spacing of the dots in the spectrum will be Dx=N/a and Dy=M/b. Square Generate Spectrum From Magnitude (scale=1000): convert square30_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(999*u+1)/log(1000)" -fill "rgb(1,1,1)" \ -opaque black square30_F_Q16_spec1000.png Rectangle 16x32 Generate Spectrum From Magnitude (scale=1000): convert rect16x32_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(999*u+1)/log(10000)" -fill "rgb(1,1,1)" \ -opaque black rect16x32_F_Q16_spec1000.png Circle Diameter 16 Generate Spectrum From Magnitude (scale=5000): convert circle16_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(4999*u+1)/log(5000)" -fill "rgb(1,1,1)" \ -opaque black circle16_F_Q16_spec5000.png Circle Diameter 30 Generate Spectrum From Magnitude (scale=5000): convert circle30_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(4999*u+1)/log(5000)" -fill "rgb(1,1,1)" \ -opaque black circle30_F_Q16_spec5000.png Circle Diameter 60 Generate Spectrum From Magnitude (scale=100000): convert circle60_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(99999*u+1)/log(5000)" -fill "rgb(1,1,1)" \ -opaque black circle60_F_Q16_spec100000.png Gaussian Sigma=16 Generate Spectrum From Magnitude (scale=100000): convert gaussian_128_sigma16_clut_F_Q16_mag.png \ -contrast-stretch 0% -fx "log(99999*u+1)/log(100000)" \ -fill "rgb(1,1,1)" -opaque black \ gaussian_128_sigma16_clut_F_Q16_mag_spec100000.png Profile Of Gauss Sigma 16 Profile Of Magnitude Of Gauss Sigma 16 Gaussian Sigma=8 Generate Spectrum From Magnitude (scale=100000): convert gaussian_128_sigma8_clut_F_Q16_mag.png \ -contrast-stretch 0% -fx "log(99999*u+1)/log(100000)" \ -fill "rgb(1,1,1)" -opaque black \ gaussian_128_sigma16_clut_F_Q16_mag_spec100000.png Profile Of Gauss Sigma 8 Profile Of Magnitude Of Gauss Sigma 8 Grid 8x16 Generate Spectrum From Magnitude (scale=100000): convert grid8x16_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(99999*u+1)/log(5000)" -fill "rgb(1,1,1)" \ -opaque black grid8x16_F_Q16_spec100000.png

 Reconstruction From Magnitude Or Phase Only FFT to produce tiff stack of frames: path-to-imfft/trunk/demo f lena.png Generate Magnitude and Phase Images: convert lena_F_Q16.tiff[0] lena_F_Q16.tiff[2] \ lena_F_Q16.tiff[4] lena_mag.png convert lena_F_Q16.tiff[1] lena_F_Q16.tiff[3] \ lena_F_Q16.tiff[5] square30_phase.png Generate Spectrum From Magnitude (scale=100000): convert lena_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(99999*u+1)/log(5000)" -fill "rgb(1,1,1)" \ -opaque black lena_F_Q16_spec100000.png phase Combine Magnitude With Flat Gray Image: convert -size 256x256 xc:gray gray.png convert \( lena_F_Q16_mag.png -channel R -separate \) \ \( gray.png -channel R -separate \) \ \( lena_F_Q16_mag.png -channel G -separate \) \ \( gray.png -channel G -separate \) \ \( lena_F_Q16_mag.png -channel B -separate \) \ \( gray.png -channel B -separate \) \ lena_mag_gray.tiff IFT of tiff stack to regenerate image: path-to-imfft/trunk/demo i lena_mag_gray_F_Q16.tiff Combine Flat Gray Image With Phase: convert -size 256x256 xc:gray gray.png convert \( gray.png -channel R -separate \) \ \( lena_F_Q16_phase.png -channel R -separate \) \ \( gray.png -channel G -separate \) \ \( lena_F_Q16_phase.png -channel G -separate \) \ \( gray.png -channel B -separate \) \ \( lena_F_Q16_phase.png -channel B -separate \) \ lena_gray_phase.tiff IFT of tiff stack to regenerate image: path-to-imfft/trunk/demo i lena_gray_phase_F_Q16.tiff magnitude only reconstruction phase only reconstruction

 Dynamic Range Change By Coefficient Rooting: (Raising Magnitude To A Power) original FFT to produce tiff stack of frames: path-to-imfft/trunk/demo f lena.png Generate Magnitude and Phase Images: convert lena_F_Q16.tiff[0] lena_F_Q16.tiff[2] \ lena_F_Q16.tiff[4] lena_mag.png convert lena_F_Q16.tiff[1] lena_F_Q16.tiff[3] \ lena_F_Q16.tiff[5] square30_phase.png Generate Spectrum From Magnitude (scale=100000): convert lena_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(99999*u+1)/log(5000)" -fill "rgb(1,1,1)" \ -opaque black lena_F_Q16_spec100000.png phase Increase Dynamic Range: Raise Magnitude To Power Less Than 1.0 convert lena_F_Q16_mag.png -fx "pow(u,0.9)" \ lena_F_Q16_mag_powp9.png Decrease Dynamic Range: Raise Magnitude To Power Greater Than 1.0 convert lena_F_Q16_mag.png -fx "pow(u,1.1)" \ lena_F_Q16_mag_pow1p1.png Combine Modified Magnitude With Phase: convert \( lena_F_Q16_mag_powp9.png -channel R -separate \) \ \( lena_F_Q16_phase.png -channel R -separate \) \ \( lena_F_Q16_mag_powp9.png -channel G -separate \) \ \( lena_F_Q16_phase.png -channel G -separate \) \ \( lena_F_Q16_mag_powp9.png -channel B -separate \) \ \( lena_F_Q16_phase.png -channel B -separate \) \ lena_mag_powp9_phase.tiff IFT of tiff stack to regenerate image: path-to-imfft/trunk/demo i lena_mag_powp9_phase_F_Q16.tiff Combine Modified Magnitude With Phase: convert \( lena_F_Q16_mag_pow1p1.png -channel R -separate \) \ \( lena_F_Q16_phase.png -channel R -separate \) \ \( lena_F_Q16_mag_powp1p1.png -channel G -separate \) \ \( lena_F_Q16_phase.png -channel G -separate \) \ \( lena_F_Q16_mag_powp1p1.png -channel B -separate \) \ \( lena_F_Q16_phase.png -channel B -separate \) \ lena_mag_pow1p1_phase.tiff IFT of tiff stack to regenerate image: path-to-imfft/trunk/demo i lena_mag_pow1p1_phase_F_Q16.tiff increased dynamic range decreased dynamic range original

 Image With "Noise" Pattern - Demo Pattern Filtering By Notch Masking FFT original noisy image (image from http://www.roborealm.com/help/FFT.php) Perform FFT to produce tiff stack of frames: path-to-imfft/trunk/demo f FFT_src.png Then create magnitude and phase (below): convert FFT_src_F_Q16.tiff[0] FFT_src_F_Q16.tiff[2] \ FFT_src_F_Q16.tiff[4] FFT_src_F_Q16_mag.png convert FFT_src_F_Q16.tiff[1] FFT_src_F_Q16.tiff[3] \ FFT_src_F_Q16.tiff[5] FFT_src_F_Q16_phase.png Generate Spectrum From Magnitude (scale=100000): convert FFT_src_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(99999*u+1)/log(100000)" -fill "rgb(1,1,1)" \ -opaque black FFT_src_F_Q16_spec100000.png Phase Mask Spectrum in GIMP or Photoshop Threshhold To Create Binary Notch Mask From Masked Spectrum convert FFT_src_F_Q16_spec100000_masked.jpg \ -threshold 1 FFT_scr_F_Q16_mask.jpg Apply Notch Mask To FFT Stack: convert \( FFT_src_F_Q16.tiff -coalesce \) null: \ FFT_scr_F_Q16_mask.png -compose multiply \ -layers Composite FFT_src_F_Q16_filtfft.tiff Then Perform IFT On Masked FFT Stack: path-to-imfft/trunk/demo i FFT_src_F_Q16_filtfft.tiff Original Noisy Image Create Difference Image And Normalize To See Noise Pattern That Was Removed: convert FFT_src.png FFT_src_F_Q16_filtfft_rt_Q16.tiff \ -compose difference -composite -normalize FFT_src_F_Q16_fft_diff_norm.png

 Image With A Second "Noise" Pattern - Demo Pattern Filtering By Notch Masking FFT original noisy image (image from http://www.mediacy.com/index.aspx?page=AH_FFTExample) Perform FFT to produce tiff stack of frames: path-to-imfft/trunk/demo f clown.png Then create magnitude and phase (below): convert clown_F_Q16.tiff[0] clown_F_Q16.tiff[2] \ clown_F_Q16.tiff[4] clown_F_Q16_mag.png convert clown_F_Q16.tiff[1] clown_F_Q16.tiff[3] \ clown_F_Q16.tiff[5] clown_F_Q16_phase.png Generate Spectrum From Magnitude (scale=100000): convert clown_F_Q16_mag.png -contrast-stretch 0% \ -fx "log(99999*u+1)/log(100000)" -fill "rgb(1,1,1)" \ -opaque black clown_F_Q16_spec100000.png Phase Mask Spectrum in GIMP or Photoshop Threshhold To Create Binary Notch Mask From Masked Spectrum convert clown_F_Q16_spec100000_masked.jpg \ -threshold 1 clown_F_Q16_mask.jpg Apply Notch Mask To FFT Stack: convert \( clown_F_Q16.tiff -coalesce \) null: \ clown_F_Q16_mask.png -compose multiply \ -layers Composite clown_F_Q16_filtfft.tiff Then Perform IFT On Masked FFT Stack: path-to-imfft/trunk/demo i clown_F_Q16_filtfft.tiff Original Noisy Image Create Difference Image And Normalize To See Noise Pattern That Was Removed: convert clown.png clown_F_Q16_filtfft_rt_Q16.tiff \ -compose difference -composite -normalize clown_F_Q16_fft_diff_norm.png