forked from MashiMaroLjc/Learn-to-identify-similar-images
-
Notifications
You must be signed in to change notification settings - Fork 8
/
pHash.py
160 lines (118 loc) · 3.31 KB
/
pHash.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
from PIL import Image
from PIL import ImageFilter
from PIL import ImageOps
import math
#This module classify the image by Discrete Cosine Transform and the accurate rate has a little improve.
#
#author MashiMaroLjc
#version 2016-2-20
def get_code(List,middle):
result = []
for index in range(0,len(List)):
if List[index] > middle:
result.append("1")
else:
result.append("0")
return result
def comp_code(code1,code2):
num = 0
for index in range(0,len(code1)):
if str(code1[index]) != str(code2[index]):
num+=1
return num
def get_middle(List):
li = List.copy()
li.sort()
value = 0
if len(li)%2==0:
index = int((len(li)/2)) - 1
value = li[index]
else:
index = int((len(li)/2))
value = (li[index]+li[index-1])/2
return value
def get_matrix(image):
matrix = []
size = image.size
for height in range(0,size[1]):
pixel = []
for width in range(0,size[0]):
pixel_value = image.getpixel((width,height))
pixel.append(pixel_value)
matrix.append(pixel)
return matrix
def get_coefficient(n):
matrix = []
PI = math.pi
sqr = math.sqrt(1/n)
value = []
for i in range(0,n):
value.append(sqr)
matrix.append(value)
for i in range(1,n):
value=[]
for j in range (0,n):
data = math.sqrt(2.0/n) * math.cos(i*PI*(j+0.5)/n);
value.append(data)
matrix.append(value)
return matrix
def get_transposing(matrix):
new_matrix = []
for i in range(0,len(matrix)):
value = []
for j in range(0,len(matrix[i])):
value.append(matrix[j][i])
new_matrix.append(value)
return new_matrix
def get_mult(matrix1,matrix2):
new_matrix = []
for i in range(0,len(matrix1)):
value_list = []
for j in range(0,len(matrix1)):
t = 0.0
for k in range(0,len(matrix1)):
t += matrix1[i][k] * matrix2[k][j]
value_list.append(t)
new_matrix.append(value_list)
return new_matrix
def DCT(double_matrix):
n = len(double_matrix)
A = get_coefficient(n)
AT = get_transposing(A)
temp = get_mult(double_matrix, A)
DCT_matrix = get_mult(temp, AT)
return DCT_matrix
def sub_matrix_to_list(DCT_matrix,part_size):
w,h = part_size
List = []
for i in range(0,h):
for j in range(0,w):
List.append(DCT_matrix[i][j])
return List
def classify_DCT(image1,image2,size=(32,32),part_size=(8,8)):
""" 'image1' and 'image2' is a Image Object.
You can build it by 'Image.open(path)'.
'Size' is parameter what the image will resize to it and then image will be compared by the pHash.
It's 32 * 32 when it default.
'part_size' is a size of a part of the matrix after Discrete Cosine Transform,which need to next steps.
It's 8 * 8 when it default.
The function will return the hamming code,less is correct.
"""
assert size[0]==size[1],"size error"
assert part_size[0]==part_size[1],"part_size error"
image1 = image1.resize(size).convert('L').filter(ImageFilter.BLUR)
image1 = ImageOps.equalize(image1)
matrix = get_matrix(image1)
DCT_matrix = DCT(matrix)
List = sub_matrix_to_list(DCT_matrix, part_size)
middle = get_middle(List)
code1 = get_code(List, middle)
image2 = image2.resize(size).convert('L').filter(ImageFilter.BLUR)
image2 = ImageOps.equalize(image2)
matrix = get_matrix(image2)
DCT_matrix = DCT(matrix)
List = sub_matrix_to_list(DCT_matrix, part_size)
middle = get_middle(List)
code2 = get_code(List, middle)
return comp_code(code1, code2)
__all__ = [classify_DCT]