Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Colour-match two sets of images pairwise, adjust colour bqlance in the first set of images.
#!/usr/bin/env python2
# requires PIL (python-imaging)
import Image
import ImageStat
from sys import argv, exit
from os.path import basename, splitext
MODIFIED_SUFFIX = "_mod.jpg"
def match_colours(source_image, target_image):
Calculate per-channel amplification to match colours of the target_file.
Return (x_red, x_green, x_blue).
s = ImageStat.Stat(source_image)
t = ImageStat.Stat(target_image)
k_chans = [ (tc/sc if sc else 1.0) for sc, tc in zip(s.mean, t.mean) ]
return tuple(k_chans)
def amplify_channels(image, factors):
Apply per-channel amplification to the image.
image PIL image
factors a tuple of amplification coefficients, one per channel
Return a new PIL image.
chans = image.split()
chans2 = [ Image.eval(c, lambda x: x*f) for c,f in zip(chans, factors)]
image2 = Image.merge(image.mode, chans2)
return image2
def main(source_images, target_images):
# calculate average transform coefficients using all image pairs
avg_multipliers = []
n = len(zip(source_images, target_images)) # number of pairs
for s, t in zip(source_images, target_images):
simg =
simg.load() # workaround for
timg =
multipliers = match_colours(simg, timg)
ms = [ float(m)/n for m in multipliers ]
if not avg_multipliers:
avg_multipliers = [ float(m)/n for m in multipliers ]
avg_multipliers = [ old_avg+float(m)/n
for old_avg, m
in zip(avg_multipliers, multipliers)]
# transform and save every source image
for s in source_images:
simg =
simg.load() # workaround for
modified = amplify_channels(simg, avg_multipliers)
out_filename = splitext(s)[0] + MODIFIED_SUFFIX
def usage():
help = \
"""%s bad_image_1 bad_image_2 ... good_image_1 good_image_2 ...
Compare bad and good images pairwise, calculate per-channel
amplification coefficients to match colours in average, adjust bad
images and save them to new files appending "%s" to the filename.
print help % (basename(argv[0]), MODIFIED_SUFFIX)
if __name__ == "__main__":
args = argv[1:]
if not args or "-h" in args or "--help" in args:
n = len(args)
bad_imgs = args[0:n//2]
good_imgs = args[n//2:]
main(bad_imgs, good_imgs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment