File: test_hash_is_constant.py

package info (click to toggle)
python-imagehash 4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,060 kB
  • sloc: python: 1,041; makefile: 81; sh: 31
file content (129 lines) | stat: -rw-r--r-- 4,480 bytes parent folder | download
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
import hashlib

import numpy
import PIL
from packaging import version
from PIL import ImageFilter

import imagehash
from tests import TestImageHash


def _calculate_segment_properties(segment):
	length = len(segment)
	min_y = min(coord[0] for coord in segment)
	min_x = min(coord[1] for coord in segment)
	max_y = max(coord[0] for coord in segment)
	max_x = max(coord[1] for coord in segment)
	return {
		'length': length,
		'min_x': min_x,
		'min_y': min_y,
		'max_x': max_x,
		'max_y': max_y
	}


def _pillow_has_convert_fix():
	"""
	Pillow version 7.0.0 introduced a fix for a rounding error in Image.convert("L") which means that segmentation is
	slightly different after this release.
	The PR which fixed the rounding and caused this inconsistency is https://github.com/python-pillow/Pillow/pull/4320
	"""
	return version.parse(PIL.__version__) >= version.parse('7.0.0')


class Test(TestImageHash):
	def setUp(self):
		self.image = self.get_data_image()
		self.peppers = self.get_data_image('peppers.png')

	def test_average_hash(self):
		result_hash = imagehash.average_hash(self.image)
		known_hash = 'ffd7918181c9ffff'
		self.assertEqual(str(result_hash), known_hash)

	def test_phash(self):
		result_hash = imagehash.phash(self.image)
		known_hash = 'ba8c84536bd3c366'
		self.assertEqual(str(result_hash), known_hash)

	def test_dhash(self):
		result_hash = imagehash.dhash(self.image)
		known_hash = '0026273b2b19550e'
		self.assertEqual(str(result_hash), known_hash)

	def test_whash(self):
		result_hash = imagehash.whash(self.image)
		known_hash = 'ffd391818181a5e7'
		self.assertEqual(str(result_hash), known_hash)

	def test_color_hash(self):
		result_hash = imagehash.colorhash(self.image)
		known_hash = '07007000000'
		self.assertEqual(str(result_hash), known_hash)

	def test_crop_resistant_hash(self):
		result_hash = imagehash.crop_resistant_hash(self.peppers)
		if _pillow_has_convert_fix():
			known_hash = (
				'c4d9f3e3e1c18101,'
				'706c6e66464c99b9,'
				'98d8f1ecd8f0f0e1,'
				'a082c0c49acc6dbd,'
				'f1f39b99c1c1b1b1,'
				'3a7ece1c9df4fcb9'
			)
		else:
			known_hash = (
				'c4d9f1e3e1c18101,'
				'706c6e66464c99b9,'
				'98d8f1ecd8f0f0e1,'
				'a282c0c49acc6dbd,'
				'b1f39b99e1c1b1b1,'
				'3a7ece1c9df4fcb9'
			)
		self.assertEqual(str(result_hash), known_hash)

	def test_crop_resistant_segmentation(self):
		# Image pre-processing
		image = self.peppers.convert('L')
		if _pillow_has_convert_fix():
			known_bw_md5 = '61db06218cc8b9aba14812d965869120'
		else:
			known_bw_md5 = '61442e74c83cfea67d182481c24c5f3e'
		self.assertEqual(
			hashlib.md5(image.tobytes()).hexdigest(),
			known_bw_md5,
			"This hash should match, unless pillow have changed Convert('L') again"
		)
		image = image.resize((300, 300), imagehash.ANTIALIAS)
		# Add filters
		image = image.filter(ImageFilter.GaussianBlur()).filter(ImageFilter.MedianFilter())
		pixels = numpy.array(image).astype(numpy.float32)
		# Segment
		segments = imagehash._find_all_segments(pixels, 128, 500)
		known_segment_count = 6
		self.assertEqual(len(segments), known_segment_count)
		if _pillow_has_convert_fix():
			known_segments = sorted([
				{'length': 595, 'min_x': 20, 'min_y': 0, 'max_x': 60, 'max_y': 31},
				{'length': 1458, 'min_x': 61, 'min_y': 0, 'max_x': 156, 'max_y': 58},
				{'length': 3505, 'min_x': 0, 'min_y': 111, 'max_x': 97, 'max_y': 191},
				{'length': 8789, 'min_x': 112, 'min_y': 145, 'max_x': 299, 'max_y': 260},
				{'length': 12153, 'min_x': 157, 'min_y': 0, 'max_x': 299, 'max_y': 148},
				{'length': 60916, 'min_x': 0, 'min_y': 0, 'max_x': 299, 'max_y': 299}
			], key=lambda x: (x['length'], x['min_x'], x['min_y'], x['max_x'], x['max_y']))
		else:
			known_segments = sorted([
				{'length': 591, 'min_x': 20, 'min_y': 0, 'max_x': 60, 'max_y': 31},
				{'length': 1451, 'min_x': 61, 'min_y': 0, 'max_x': 156, 'max_y': 58},
				{'length': 12040, 'min_x': 157, 'min_y': 0, 'max_x': 299, 'max_y': 147},
				{'length': 3452, 'min_x': 0, 'min_y': 111, 'max_x': 97, 'max_y': 191},
				{'length': 8701, 'min_x': 112, 'min_y': 145, 'max_x': 299, 'max_y': 259},
				{'length': 61179, 'min_x': 0, 'min_y': 0, 'max_x': 299, 'max_y': 299}
			], key=lambda x: (x['length'], x['min_x'], x['min_y'], x['max_x'], x['max_y']))
		segment_properties = sorted([
			_calculate_segment_properties(segment) for segment in segments
		], key=lambda x: (x['length'], x['min_x'], x['min_y'], x['max_x'], x['max_y']))
		self.assertEqual(segment_properties, known_segments)