From c1fefec997d7eb4f4682749289a8a6d5294ef5e4 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 15 Jul 2018 07:46:32 +1000 Subject: [PATCH] Added Image average_difference --- Tests/helper.py | 22 +--------------------- Tests/test_image.py | 23 ++++++++++++++++++++++- src/PIL/Image.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/Tests/helper.py b/Tests/helper.py index b6ef6dc13..543f6c9bf 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -33,19 +33,6 @@ else: pass -def convert_to_comparable(a, b): - new_a, new_b = a, b - if a.mode == 'P': - new_a = Image.new('L', a.size) - new_b = Image.new('L', b.size) - new_a.putdata(a.getdata()) - new_b.putdata(b.getdata()) - elif a.mode == 'I;16': - new_a = a.convert('I') - new_b = b.convert('I') - return new_a, new_b - - class PillowTestCase(unittest.TestCase): def __init__(self, *args, **kwargs): @@ -130,14 +117,7 @@ class PillowTestCase(unittest.TestCase): a.size, b.size, msg or "got size %r, expected %r" % (a.size, b.size)) - a, b = convert_to_comparable(a, b) - - diff = 0 - for ach, bch in zip(a.split(), b.split()): - chdiff = ImageMath.eval("abs(a - b)", a=ach, b=bch).convert('L') - diff += sum(i * num for i, num in enumerate(chdiff.histogram())) - - ave_diff = float(diff)/(a.size[0]*a.size[1]) + ave_diff = a.average_difference(b) try: self.assertGreaterEqual( epsilon, ave_diff, diff --git a/Tests/test_image.py b/Tests/test_image.py index 7222e389b..3b14ad8cf 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,6 +1,6 @@ from helper import unittest, PillowTestCase, hopper -from PIL import Image +from PIL import Image, ImageFilter from PIL._util import py3 import os @@ -492,6 +492,27 @@ class TestImage(PillowTestCase): self.assertEqual(ext_individual, ext_multiple) + def test_average_difference(self): + for mode_a, mode_b in [ + ("RGB", "RGBA"), + ("P", "RGB"), + ("I;16", "RGB") + ]: + im_a = hopper(mode_a) + im_b = hopper(mode_b) + self.assertEqual(im_a.average_difference(im_b), 0) + + im = hopper() + im_resized = im.resize((im.width * 2, im.height * 2)) + diff = im.average_difference(im_resized) + self.assertEqual(diff, 0) + self.assertEqual(im_resized.average_difference(im), diff) + + im_blur = im.filter(ImageFilter.BLUR) + diff = im.average_difference(im_blur) + self.assertNotEqual(diff, 0) + self.assertEqual(im_blur.average_difference(im), diff) + def test_remap_palette(self): # Test illegal image mode im = hopper() diff --git a/src/PIL/Image.py b/src/PIL/Image.py index f13a98276..7d7781631 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -851,6 +851,41 @@ class Image(object): """ pass + def average_difference(self, im): + """ + Returns the average pixel value difference between this and another + image + + :param im: Comparison image + """ + from . import ImageMath + + a, b = self, im + if a.mode == 'I;16': + a = a.convert('I') + if b.mode != a.mode: + b = b.convert(a.mode) + + if a.mode == 'P': + a_data = a.getdata() + b_data = b.getdata() + a = new('L', a.size) + b = new('L', b.size) + a.putdata(a_data) + b.putdata(b_data) + + if (a.width * a.height) < (b.width * b.height): + b = b.resize(a.size) + elif (b.width * b.height) < (a.width * a.height): + a = a.resize(b.size) + + diff = 0 + for ach, bch in zip(a.split(), b.split()): + chdiff = ImageMath.eval("abs(a - b)", a=ach, b=bch).convert('L') + diff += sum(i * num for i, num in enumerate(chdiff.histogram())) + + return float(diff) / (a.size[0] * a.size[1]) + def convert(self, mode=None, matrix=None, dither=None, palette=WEB, colors=256): """