test_photohash.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. from os.path import abspath, dirname, join
  2. import unittest
  3. from photohash.photohash import average_hash, distance, is_look_alike, hash_distance
  4. TESTS_ROOT = join(dirname(abspath(__file__)))
  5. ASSETS_ROOT = join(TESTS_ROOT, 'assets')
  6. MODULE_ROOT = join(TESTS_ROOT, '../')
  7. class PhotoHashTestCase(unittest.TestCase):
  8. def setUp(self):
  9. self.photos = [
  10. {
  11. 'path': join(ASSETS_ROOT, 'minneapolis.jpg'),
  12. 'average_hash': 'ffffffffc7000000',
  13. },
  14. {
  15. 'path': join(ASSETS_ROOT, 'santa_monica.jpg'),
  16. 'average_hash': '01ffffff1f3f0008',
  17. },
  18. {
  19. 'path': join(ASSETS_ROOT, 'snow.jpg'),
  20. 'average_hash': '67047df9fcf0408f',
  21. },
  22. {
  23. 'path': join(ASSETS_ROOT, 'santa_monica_small.jpg'),
  24. 'average_hash': '01ffffff1f3f0008',
  25. },
  26. ]
  27. def test_average_hash(self):
  28. """average_hash should output the expected hash for each test image"""
  29. for photo in self.photos:
  30. self.assertEqual(photo['average_hash'], average_hash(photo['path']))
  31. def test_hash_distance(self):
  32. """hash_distance should know the hamming distance between two strings"""
  33. self.assertEqual(hash_distance('roses', 'toned'), 3)
  34. self.assertEqual(hash_distance('are', 'are'), 0)
  35. self.assertEqual(hash_distance('read', 'daer'), 4)
  36. def testhash_distance_same_length_required(self):
  37. """hash_distance should throw a ValueError if the two strings are not the same length"""
  38. self.assertRaises(ValueError, hash_distance, 'short', 'very long')
  39. def test_distance(self):
  40. """distance should know the distance between the average_hash of two test images"""
  41. for i in range(len(self.photos)):
  42. for j in range(i, len(self.photos)):
  43. hamming_distance = hash_distance(
  44. self.photos[i]['average_hash'],
  45. self.photos[j]['average_hash']
  46. )
  47. self.assertEqual(
  48. hamming_distance,
  49. distance(self.photos[i]['path'], self.photos[j]['path'])
  50. )
  51. def test_is_look_alike(self):
  52. """is_look_alike should know if two images look similar"""
  53. # Test that the same image will return True.
  54. self.assertTrue(is_look_alike(self.photos[2]['path'], self.photos[2]['path']))
  55. # And if we use the most strict tolerance.
  56. self.assertTrue(is_look_alike(self.photos[2]['path'], self.photos[2]['path'], tolerance=0))
  57. # And if we use the least strict tolerance.
  58. self.assertTrue(
  59. is_look_alike(self.photos[2]['path'], self.photos[2]['path'], tolerance=16)
  60. )
  61. # Test that different images return False
  62. self.assertFalse(is_look_alike(self.photos[0]['path'], self.photos[1]['path']))
  63. # Test that a scaled verision of the same image is within default tolerance.
  64. self.assertTrue(is_look_alike(self.photos[1]['path'], self.photos[3]['path']))