-
Notifications
You must be signed in to change notification settings - Fork 2
/
dhash.py
executable file
·90 lines (80 loc) · 2.82 KB
/
dhash.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class dhash(object):
"""
usage:
calculate the dhash value of an image
hash = dhash.calculate_hash(image)
calculate the hamming distance between two images
hamming_distance = dhash.hamming_distance(image1, image2)
calculate the hamming distance between two dhash values
hamming_distance = dhash.hamming_distance(dhash1, dhash2)
"""
@staticmethod
def calculate_hash(image):
"""
calculate the dhash of an image
:param image: PIL.Image
:return: dhash (str)
"""
difference = dhash.__difference(image)
# 1 => 8, 8 => 16
decimal_value = 0
hash_string = ""
for index, value in enumerate(difference):
if value:
decimal_value += value * (2 ** (index % 8))
if index % 8 == 7:
# 0xf=>0x0f
hash_string += str(hex(decimal_value)[2:].rjust(2, "0"))
decimal_value = 0
return hash_string
@staticmethod
def hamming_distance(first, second):
"""
calculate hamming distance
:param first: dhash (str)
:param second: dhash (str)
:return: hamming distance
"""
if isinstance(first, str):
return dhash.__hamming_distance_with_hash(first, second)
hamming_distance = 0
image1_difference = dhash.__difference(first)
image2_difference = dhash.__difference(second)
for index, img1_pix in enumerate(image1_difference):
img2_pix = image2_difference[index]
if img1_pix != img2_pix:
hamming_distance += 1
return hamming_distance
@staticmethod
def __difference(image):
"""
find the difference with image
:param image: PIL.Image
:return: difference (int)
"""
resize_width = 9
resize_height = 8
# resize enough to hide the details
smaller_image = image.resize((resize_width, resize_height))
# reduce color i.e. convert to grayscale
grayscale_image = smaller_image.convert("L")
# difference calculation
pixels = list(grayscale_image.getdata())
difference = []
for row in range(resize_height):
row_start_index = row * resize_width
for col in range(resize_width - 1):
left_pixel_index = row_start_index + col
difference.append(
pixels[left_pixel_index] > pixels[left_pixel_index + 1])
return difference
@staticmethod
def __hamming_distance_with_hash(dhash1, dhash2):
"""
find difference using 2 dhash values
:param dhash1: str
:param dhash2: str
:return: difference (int)
"""
difference = (int(dhash1, 16)) ^ (int(dhash2, 16))
return bin(difference).count("1")