|
@@ -3,49 +3,67 @@ import khandy
|
|
import numpy as np
|
|
import numpy as np
|
|
|
|
|
|
|
|
|
|
|
|
+def _convert_bool_matrix_to_int(bool_mat):
|
|
|
|
+ hash_val = int(0)
|
|
|
|
+ for item in bool_mat.flatten():
|
|
|
|
+ hash_val |= int(item)
|
|
|
|
+ hash_val <<= 1
|
|
|
|
+ hash_val >>= 1
|
|
|
|
+ return hash_val
|
|
|
|
+
|
|
|
|
+
|
|
def calc_image_ahash(image):
|
|
def calc_image_ahash(image):
|
|
|
|
+ """Average Hashing
|
|
|
|
+
|
|
|
|
+ References:
|
|
|
|
+ http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
|
|
|
|
+ """
|
|
assert khandy.is_numpy_image(image)
|
|
assert khandy.is_numpy_image(image)
|
|
if image.ndim == 3:
|
|
if image.ndim == 3:
|
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
resized = cv2.resize(image, (8, 8))
|
|
resized = cv2.resize(image, (8, 8))
|
|
-
|
|
|
|
- meanval = cv2.mean(resized)[0]
|
|
|
|
- hashval = int(0)
|
|
|
|
- for i in range(8):
|
|
|
|
- for j in range(8):
|
|
|
|
- mask = int(resized[i,j] - meanval >= 1e-5)
|
|
|
|
- hashval |= mask << (i * 8 + j)
|
|
|
|
- return hashval
|
|
|
|
-
|
|
|
|
|
|
|
|
-def calc_image_phash(image):
|
|
|
|
|
|
+ mean_val = np.mean(resized)
|
|
|
|
+ hash_mat = resized >= mean_val
|
|
|
|
+ hash_val = _convert_bool_matrix_to_int(hash_mat)
|
|
|
|
+ return hash_val
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def calc_image_dhash(image):
|
|
|
|
+ """Difference Hashing
|
|
|
|
+
|
|
|
|
+ References:
|
|
|
|
+ http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
|
|
|
|
+ """
|
|
assert khandy.is_numpy_image(image)
|
|
assert khandy.is_numpy_image(image)
|
|
if image.ndim == 3:
|
|
if image.ndim == 3:
|
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
- resized = cv2.resize(image, (32, 32))
|
|
|
|
-
|
|
|
|
- dft = cv2.dft(resized.astype(np.float32))
|
|
|
|
- meanval = cv2.mean(dft[:8,:8])[0]
|
|
|
|
- hashval = int(0)
|
|
|
|
- for i in range(8):
|
|
|
|
- for j in range(8):
|
|
|
|
- mask = int(dft[i,j] - meanval >= 1e-5)
|
|
|
|
- hashval |= mask << (i * 8 + j)
|
|
|
|
- return hashval
|
|
|
|
-
|
|
|
|
|
|
+ resized = cv2.resize(image, (9, 8))
|
|
|
|
|
|
-def calc_image_dhash(image):
|
|
|
|
|
|
+ hash_mat = resized[:,:-1] >= resized[:,1:]
|
|
|
|
+ hash_val = _convert_bool_matrix_to_int(hash_mat)
|
|
|
|
+ return hash_val
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def calc_image_phash(image):
|
|
|
|
+ """Perceptual Hashing
|
|
|
|
+
|
|
|
|
+ References:
|
|
|
|
+ http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html
|
|
|
|
+ """
|
|
assert khandy.is_numpy_image(image)
|
|
assert khandy.is_numpy_image(image)
|
|
if image.ndim == 3:
|
|
if image.ndim == 3:
|
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
- resized = cv2.resize(image, (9, 8))
|
|
|
|
|
|
+ resized = cv2.resize(image, (32, 32))
|
|
|
|
|
|
- hashval = int(0)
|
|
|
|
- for i in range(8):
|
|
|
|
- for j in range(8):
|
|
|
|
- mask = int(resized[i,j] > resized[i,j+1])
|
|
|
|
- hashval |= mask << (i * 8 + j)
|
|
|
|
- return hashval
|
|
|
|
-
|
|
|
|
|
|
+ dct_coeff = cv2.dct(resized.astype(np.float32))
|
|
|
|
+ reduced_dct_coeff = dct_coeff[:8, :8]
|
|
|
|
|
|
|
|
+ # median of coefficients excluding the DC term (0th term)
|
|
|
|
+ # mean_val = np.mean(reduced_dct_coeff.flatten()[1:])
|
|
|
|
+ median_val = np.median(reduced_dct_coeff.flatten()[1:])
|
|
|
|
+
|
|
|
|
+ hash_mat = reduced_dct_coeff >= median_val
|
|
|
|
+ hash_val = _convert_bool_matrix_to_int(hash_mat)
|
|
|
|
+ return hash_val
|
|
|
|
|