Fred's ImageMagick Scripts



    Licensing:

    My scripts are available free of charge for non-commercial use, ONLY.

    For use of my scripts in commercial (for-profit) environments or non-free applications, please contact me (Fred Weinhaus) for licensing arrangements. My email address is fmw at alink dot net.

    If you: 1) redistribute, 2) incorporate any of these scripts into other free applications or 3) reprogram them in another scripting language, then you must contact me for permission, especially if the result might be used in a commercial or for-profit environment.

    Usage, whether stated in the script or not, is restricted to the above licensing arrangements. It is also subject to the ImageMagick license, which can be found at: http://www.imagemagick.org/script/license.php

FFTDECONVOL


Performs deconvolution on an image in the frequency domain.

Download Script

last modified: August 27, 2013



USAGE: fftdeconvol [-n noise] infile filtfile outfile
USAGE: fftdeconvol [-h or -help]

-n .... noise .... estimate of the noise to signal power ratio; float>=0;
.................. default=0

PURPOSE: To perform deconvolution on an image in the frequency domain.

DESCRIPTION: FFTDECONVOL perform deconvolution on an image in the frequency domain using a filter image and an estimate of the noise to signal power ratio. Two inputs are required. The convolved image and a grayscale spatial domain convolution filter. Both the convolved image and the grayscale spatial domain convolution filter are transformed to the frequency domain using +fft. Then the fft of the image is divided by the fft of the filter and the product is then returned to the spatial domain using +ift. Since the filter may have noise, which will get amplified by the division when the signal is near zero, a small constant, representing the noise to signal power ratio is added to the denominator prior to the division in order to avoid a division by zero. Any alpha channel on the filter will be removed automatically before processing. If the image has an alpha channel it will not be processed, but simply copied from the input to the output. Currently not be processed, but simply copied from the input to the output. This is useful only for deconvolving an image that has been blurred by the same convolution.

ARGUMENTS:

-n noise ... NOISE is the estimate of the small constant added to the denominator in the division process and represents the noise to signal power ratio. Values are floats>=0. Usually one simply uses trial an error with an arbitrary small value for the noise typically in the range of about 0.001 to 0.0001. But there are techniques for making a proper estimate. The default=0.

The filter image must be appropriately centered and padded with black to the same size as the input image.

REQUIREMENTS: IM version 6.5.4-7 or higher, but compiled with HDRI enabled in any quantum level of Q8, Q16 or Q32. Also requires the FFTW delegate library.

LIMITATIONS: This script works well only with even, square images. Otherwise, the FFT will pad them with black to conform. However, there will be excessive ringing due to the color discontinuity associated with the padding. This even, square limitation is a ramification of the current IM implementation that needs addressing at some future time. It is not a limitation of FFTW.

See Fourier Transform with ImageMagick, for more details.

CAVEAT: No guarantee that this script will work on all platforms, nor that trapping of inconsistent parameters is complete and foolproof. Use At Your Own Risk.


EXAMPLES


Removing Horizontal Motion Blur

Input
(see script, fftconvol)

Filter
convert -size 128x128 xc:black -fill white \
-draw "line 61,64 67,64" -alpha off motion7.png

Arguments:
-n 0



Removing Horizontal Motion Blur With Added Noise

Input
(see script, fftconvol)

# create noise
convert -size 128x128 xc:gray +noise random \
-channel green -separate noise_gray.png

# add noise to motion blurred image
convert cameraman2_motion7.png noise_gray.png +swap \
-compose mathematics -set option:compose:args "0,1,0.01,-0.005" \
-composite cameraman2_motion7_noise.png

Filter
convert -size 128x128 xc:black -fill white \
-draw "line 61,64 67,64" -alpha off motion7.png

 

 

Arguments:
-n 0.005

Arguments:
-n 0.0005

Arguments:
-n 0.00005



Removing Lens Defocus

Input
(see script, fftconvol)

Filter
convert -size 128x128 xc:black -fill white \
-draw "circle 64,64 67,64" -alpha off defocus7.png

Arguments:
-n 0



Removing Lens Defocus With Added Noise

Input
(see script, fftconvol)

# create noise
convert -size 128x128 xc:gray +noise random \
-channel green -separate noise_gray.png

# add noise to motion blurred image
convert cameraman2_defocus7.png noise_gray.png +swap \
-compose mathematics -set option:compose:args "0,1,0.01,-0.005" \
-composite cameraman2_defocus7_noise.png

Filter
convert -size 128x128 xc:black -fill white \
-draw "line 61,64 67,64" -alpha off motion7.png

 

 

Arguments:
-n 0.005

Arguments:
-n 0.0005

Arguments:
-n 0.00005



What the script does is as follows:

  • Computes the real and imaginary components of both the image and the filter
  • Rolls the center of the transformed filter images to the
    upper left corner and stretches it to full dynamic range.
  • Performs complex number division using the four resulting transformed images
  • Converts the real and imaginary products back to the spatial domain

This is equivalent to the following IM commands.

  • width=`identify -ping -format "%w" $infile`
  • height=`identify -ping -format "%h" $infile`
  • cx=`convert xc: -format "%[fx:floor(($width+1)/2)]" info:`
  • cy=`convert xc: -format "%[fx:floor(($height+1)/2)]" info:`
  • gain=`convert $filtfile -format "%[fx:1/mean]" info:`
  • qnoise=`convert xc: -format "%[fx:quantumrange*$noise]" info:`
  • convert \( $filtfile -roll -${cx}-${cy} +fft -evaluate multiply $gain \) \
    \( $infile -alpha off +fft \) \
    \( -clone 0 -clone 0 -compose multiply -composite \) \
    \( -clone 1 -clone 1 -compose multiply -composite \) \
    \( -clone 4 -clone 5 -compose plus -composite -evaluate add $qnoise \) \
    \( -clone 0 -clone 2 -compose multiply -composite \) \
    \( -clone 1 -clone 3 -compose multiply -composite \) \
    \( -clone 7 -clone 8 -compose plus -composite \) \
    \( -clone 6 -clone 9 -compose divide -composite \) \
    \( -clone 0 -clone 3 -compose multiply -composite \) \
    \( -clone 1 -clone 2 -compose multiply -composite \) \
    \( -clone 11 -clone 12 +swap -compose minus -composite \) \
    \( -clone 6 -clone 13 -compose divide -composite \) \
    -delete 0-9,11,12,13 +ift \
    -crop ${width}x${height}+0+0 +repage $outfile