from os.path import abspath, dirname, join import unittest from photohash.photohash import average_hash, distance, is_look_alike, hash_distance TESTS_ROOT = join(dirname(abspath(__file__))) ASSETS_ROOT = join(TESTS_ROOT, 'assets') MODULE_ROOT = join(TESTS_ROOT, '../') class PhotoHashTestCase(unittest.TestCase): def setUp(self): self.photos = [ { 'path': join(ASSETS_ROOT, 'minneapolis.jpg'), 'average_hash': 'ffffffffc7000000', }, { 'path': join(ASSETS_ROOT, 'santa_monica.jpg'), 'average_hash': '01ffffff1f3f0008', }, { 'path': join(ASSETS_ROOT, 'snow.jpg'), 'average_hash': '67047df9fcf0408f', }, { 'path': join(ASSETS_ROOT, 'santa_monica_small.jpg'), 'average_hash': '01ffffff1f3f0008', }, ] def test_average_hash(self): """average_hash should output the expected hash for each test image""" for photo in self.photos: self.assertEqual(photo['average_hash'], average_hash(photo['path'])) def test_hash_distance(self): """hash_distance should know the hamming distance between two strings""" self.assertEqual(hash_distance('roses', 'toned'), 3) self.assertEqual(hash_distance('are', 'are'), 0) self.assertEqual(hash_distance('read', 'daer'), 4) def testhash_distance_same_length_required(self): """hash_distance should throw a ValueError if the two strings are not the same length""" self.assertRaises(ValueError, hash_distance, 'short', 'very long') def test_distance(self): """distance should know the distance between the average_hash of two test images""" for i in range(len(self.photos)): for j in range(i, len(self.photos)): hamming_distance = hash_distance( self.photos[i]['average_hash'], self.photos[j]['average_hash'] ) self.assertEqual( hamming_distance, distance(self.photos[i]['path'], self.photos[j]['path']) ) def test_is_look_alike(self): """is_look_alike should know if two images look similar""" # Test that the same image will return True. self.assertTrue(is_look_alike(self.photos[2]['path'], self.photos[2]['path'])) # And if we use the most strict tolerance. self.assertTrue(is_look_alike(self.photos[2]['path'], self.photos[2]['path'], tolerance=0)) # And if we use the least strict tolerance. self.assertTrue( is_look_alike(self.photos[2]['path'], self.photos[2]['path'], tolerance=16) ) # Test that different images return False self.assertFalse(is_look_alike(self.photos[0]['path'], self.photos[1]['path'])) # Test that a scaled verision of the same image is within default tolerance. self.assertTrue(is_look_alike(self.photos[1]['path'], self.photos[3]['path']))