| # Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import heapq, logging |
| |
| from PIL import Image |
| from PIL import ImageChops |
| |
| from autotest_lib.client.cros.image_comparison import comparison_result |
| from autotest_lib.client.cros.video import method_logger |
| |
| |
| """ |
| |
| *** Consider using PdiffImageComparer instead of this class *** |
| * This class uses pixel by pixel comparer while PdiffImageComparer encapsules |
| * the perceptualdiff tool available in ChromeOS |
| |
| """ |
| |
| |
| class RGBImageComparer(object): |
| """ |
| Compares two RGB images using built-in python image library. |
| |
| """ |
| |
| |
| def __init__(self, rgb_pixel_threshold): |
| self.pixel_threshold = rgb_pixel_threshold |
| |
| |
| @method_logger.log |
| def compare(self, golden_img_path, test_img_path, box=None): |
| """ |
| Compares a test image against a known golden image. |
| |
| Both images must be RGB images. |
| |
| @param golden_img_path: path, complete path to a golden image. |
| @param test_img_path: path, complete path to a test image. |
| @param box: int tuple, left, upper, right, lower pixel coordinates |
| defining a box region within which the comparison is made. |
| |
| @return: int, number of pixels that are different. |
| |
| """ |
| golden_image = Image.open(golden_img_path) |
| test_image = Image.open(test_img_path) |
| |
| if golden_image.mode != 'RGB': |
| logging.debug('Golden image was not RGB. Converting to RGB.') |
| golden_image = golden_image.convert('RGB') |
| |
| if test_image.mode != 'RGB': |
| logging.debug('Test image was not RGB. Converting to RGB.') |
| test_image = test_image.convert('RGB') |
| |
| if box is not None: |
| golden_image = golden_image.crop(box) |
| test_image = test_image.crop(box) |
| |
| diff_image = ImageChops.difference(golden_image, test_image) |
| maxcolors = diff_image.size[0] * diff_image.size[1] |
| colorstuples = diff_image.getcolors(maxcolors) |
| max_debug_count = 100 |
| |
| logging.debug("***ALL Color counts: %d", maxcolors) |
| logging.debug(heapq.nlargest(max_debug_count, colorstuples)) |
| |
| # getcolors returns a list of (count, color) tuples where count is the |
| # number of times the corresponding color in the image. |
| |
| above_thres_tuples = [t for t in colorstuples |
| if any(pixel > self.pixel_threshold |
| for pixel in t[1])] |
| |
| logging.debug("Color counts above thres.: %d", len(above_thres_tuples)) |
| logging.debug(heapq.nlargest(max_debug_count, above_thres_tuples)) |
| |
| diff_pixels = sum(t[0] for t in above_thres_tuples) |
| |
| return comparison_result.ComparisonResult(diff_pixels, '') |
| |
| |
| def __enter__(self): |
| return self |
| |
| |
| def __exit__(self, exc_type, exc_val, exc_tb): |
| pass |