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

HISTMATCH


Modifies one image to try to match its histogram and optionally saturation to that of another image.

Download Script

last modified: August 27, 2013



USAGE: histmatch [-c colormode] [-L] infile1 infile2 outfile
USAGE: histmatch [-h or -help]

-c .... colormode ..... colorspace/channel to use to compute the image
....................... histograms; choices are: gray, intensity, luminance,
....................... lightness, brightness, average and rgb;
....................... default=gray
-L .................... save the lookup table image; if saved, it will
....................... be named histmatch_lut.png
....................... infile2 will be modified to match infile1

PURPOSE: To modify one image to try to match its histogram and optionally saturation to that of another image.

DESCRIPTION: HISTMATCH modifies one image to try to match its histogram and optionally saturation to that of another image. The second image will be modified to match the first image. Saturation changes only apply to color images, not grayscale ones. The choice of colormode determines what colorspace or channel will be used to compute the histograms of the two images. A non-linear transformation is then computed from the cumulative histograms of the two images. This non-linear transformation is then applied to each channel of the second image using -clut to generate the output. If colormode=rgb,then each channel will be processed independently.

IMPORTANT: This histogram transformation can only do so much. Once information is lost, it generally cannot be adequately recovered. This would be the case, for example, if the second image has too narrow a histogram, such from too little contrast or mostly one color. The histogram can be spread out to increase the dynamic range, but any one bin cannot be broken into multiple bins. Likewise, if the second image has too high a contrast, the histogram will be very wide and much of the data will be contained in the very high and very low bins and little data in the middle bins. Again any one bin cannot be broken into multiple bins, but small bins can be combined.

ARGUMENTS:

-c colormode ... COLORMODE is the colorspace/channel to use to compute the histograms of the two images. The choices are: gray, intensity, luminance, lightness, brightness, average, and rgb. Values of gray and intensity are equivalent. If colormode=rgb, then each channel of the image will be processed independently. The default is gray.

Gray or Intensity uses statistics from -colorspace Gray.
Luminance uses statistics from -colorspace Rec709Luma.
Lightness uses statistics from the lightness channel of -colorspace HSL.
Brightness uses statistics from the brightness channel of -colorspace HSB.
Average uses statistics from the first channel of -colorspace OHTA.
RGB uses statistics independently from each channel of either sRGB or RGB.
See definitions at: http://www.imagemagick.org/script/command-line-options.php#colorspace

Note: generally there are only slight differences between the various non-rgb colormode results. Colormode=rgb can cause color balance shifts. and odd colors may creep in.

-L ... Save the lookup table image. If saved, it will be named histmatch_lut.png

REQUIRES: IM version 6.4.5-1 or higher if modifying saturation due to the use of -set option:modulate:colorspace. Otherwise, requires IM version 6.3.9-2 due to the use of -format "%[colorspace]". Also, requires NetPBM PGM. See http://netpbm.sourceforge.net/

NOTE: Thanks to Anthony Thyssen for the suggested changes from shell calculations for the histograms to the use of AWK. This has produced a 10x performance speed up.

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


Attempt To Increase Brightness And Contrast On Dark And Low Contrast Image

Reference Image (infile1)

Dark, Low Contrast Image (infile2)

Arguments:
-c gray
(default)

Arguments:
-c rbg



Attempt To Decrease Brightness And Contrast On Bright And High Contrast Image

Reference Image (infile1)

Dark, Low Contrast Image (infile2)

Arguments:
-c gray
(default)

Arguments:
-c rbg



Attempt To Match One Image's Colorization To Another Image

Reference Image (infile1)

Image To Change (infile2)

Arguments:
-c rgb



Attempt To Match One Image's Colorization To Another Image
(ref: http://www.listofimages.com/spring-landscape-blue-clouds-fields-grass-green-landscape-skies-spring.html)
(img: http://www.tripadvisor.com/Tourism-g293955-Mongolia-Vacations.html)

Reference Image (infile1)

Image To Change (infile2)

Arguments:
-c rgb



What the script does is as follows:

  • Converts both images to desired colorspace/channel
  • Gets the histogram from those images
  • Generates the cumulative histograms and uses those to create a
    non-linear transformation look up table as a 1D image.
  • Applies the look up table image using -clut to transform the second image

This is equivalent to the following IM commands for the gray colormode
and no saturation modification.

  • convert $infile1 -colorspace gray -separate $tmpIA1
  • convert $infile2 -colorspace gray -separate $tmpIA2
  • # get histograms of each image above
  • # generate cumulative histograms
  • # generate look up table array
  • echo "P2 $len 1 $maxval\n ${lutArr[*]}" | convert - -scale 256x1! $tmpL
  • convert $infile2 $tmpL -clut $outfile