From 96e3c0a8530318e9177db10786184912fe1dc0e4 Mon Sep 17 00:00:00 2001 From: dust-to-dust <59217631+dust-to-dust@users.noreply.github.com> Date: Fri, 8 Apr 2022 10:51:57 +0800 Subject: [PATCH] Add support for difference-aware hash calculation. Fix indentation exception --- src/PIL/Image.py | 120 +++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index b8278a509..69b1c0179 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -2694,76 +2694,76 @@ class Image: return ImageQt.toqpixmap(self) def dhash(self) -> str: - """ - Calculate the dHash value of the picture. DHash value can be used to quickly determine the similarity of two pictures. - """ - difference = self._difference(self) - decimal_value = 0 - hash_string = "" - for index, value in enumerate(difference): - if value: - decimal_value += value * (2 ** (index % 8)) - if index % 8 == 7: - hash_string += str(hex(decimal_value)[2:].rjust(2, "0")) - decimal_value = 0 - return hash_string + """ + Calculate the dHash value of the picture. DHash value can be used to quickly determine the similarity of two pictures. + """ + difference = self._difference(self) + decimal_value = 0 + hash_string = "" + for index, value in enumerate(difference): + if value: + decimal_value += value * (2 ** (index % 8)) + if index % 8 == 7: + hash_string += str(hex(decimal_value)[2:].rjust(2, "0")) + decimal_value = 0 + return hash_string -def is_similar_to(self, image, hamming_distance: int = 3) -> bool: - """ + def is_similar_to(self, image, hamming_distance: int = 3) -> bool: + """ - :param image: PIL.Image / dHash(str) - :param hamming_distance: - :return: bool - """ - assert 0 <= hamming_distance <= 64 - dis = self.hamming_distance(image) - return True if dis <= hamming_distance else False + :param image: PIL.Image / dHash(str) + :param hamming_distance: + :return: bool + """ + assert 0 <= hamming_distance <= 64 + dis = self.hamming_distance(image) + return True if dis <= hamming_distance else False -def hamming_distance(self, image) -> int: - """ - Calculate the Hamming distance between two pictures (based on dHash algorithm) - :param image: PIL.Image / dHash(str) - :return: hamming distance. The larger the value, the greater the difference between the two pictures; - otherwise, the more similar they are. - """ - if isinstance(image, str): - return self._hamming_distance_with_hash(image) + def hamming_distance(self, image) -> int: + """ + Calculate the Hamming distance between two pictures (based on dHash algorithm) + :param image: PIL.Image / dHash(str) + :return: hamming distance. The larger the value, the greater the difference between the two pictures; + otherwise, the more similar they are. + """ + if isinstance(image, str): + return self._hamming_distance_with_hash(image) - image1_diff = self._difference(self) - image2_diff = self._difference(image) + image1_diff = self._difference(self) + image2_diff = self._difference(image) - return sum(image1_diff ^ image2_diff) + return sum(image1_diff ^ image2_diff) -@staticmethod -def _difference(image): - """ - *Private method* - Calculate difference sequence - :param image: PIL.Image - :return: bool list - """ - from numpy import array + @staticmethod + def _difference(image): + """ + *Private method* + Calculate difference sequence + :param image: PIL.Image + :return: bool list + """ + from numpy import array - resize_width = 9 - resize_height = 8 - difference = [] # 64-bit boolean sequence + resize_width = 9 + resize_height = 8 + difference = [] # 64-bit boolean sequence - # convert to 9*8 grayscale image - data = array(image.resize((resize_width, resize_height)).convert('L')) - for row in range(resize_height): - for col in range(resize_width - 1): - difference.append(data[row, col] > data[row, col + 1]) + # convert to 9*8 grayscale image + data = array(image.resize((resize_width, resize_height)).convert('L')) + for row in range(resize_height): + for col in range(resize_width - 1): + difference.append(data[row, col] > data[row, col + 1]) - return array(difference) + return array(difference) -def _hamming_distance_with_hash(self, dhash: str) -> int: - """ - *Private method* - calculate hamming distance with perceptual hash - :return: hamming_distance(int) - """ - difference = (int(self.dhash(), 16)) ^ (int(dhash, 16)) - return bin(difference).count("1") + def _hamming_distance_with_hash(self, dhash: str) -> int: + """ + *Private method* + calculate hamming distance with perceptual hash + :return: hamming_distance(int) + """ + difference = (int(self.dhash(), 16)) ^ (int(dhash, 16)) + return bin(difference).count("1") # --------------------------------------------------------------------