├── README.md ├── drawMatches.py ├── hashes.py ├── knn.py └── knnsingle.py /README.md: -------------------------------------------------------------------------------- 1 | Image-similarity 2 | =============== 3 | 4 | Different programs for calculating percentage similarity of two images 5 | 6 | * hashes.py - Calculate Image similarity based on phash 7 | * drawMatches.py - mapping of similar points of 2 images 8 | * knn.py - iterate through all images in given folder to find similar images (sim % > 80) and delete them 9 | * knnsingle.py - mapping similar points in 2 images using knn 10 | 11 | Usage: 12 | * python < hashes.py / drawMatches.py / knnsingle.py > < img1 > < img2 > 13 | * python knn.py < dir > 14 | -------------------------------------------------------------------------------- /drawMatches.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import sys 4 | # from scipy import ndimage 5 | 6 | def rotateImage(image, angle): 7 | image_center = tuple(np.array(image.shape)/2) 8 | rot_mat = cv2.getRotationMatrix2D(image_center,angle,1.0) 9 | result = cv2.warpAffine(image, rot_mat, image.shape,flags=cv2.INTER_LINEAR) 10 | return result 11 | 12 | def drawMatches(img1, kp1, img2, kp2, matches): 13 | """ 14 | My own implementation of cv2.drawMatches as OpenCV 2.4.9 15 | does not have this function available but it's supported in 16 | OpenCV 3.0.0 17 | 18 | This function takes in two images with their associated 19 | keypoints, as well as a list of DMatch data structure (matches) 20 | that contains which keypoints matched in which images. 21 | 22 | An image will be produced where a montage is shown with 23 | the first image followed by the second image beside it. 24 | 25 | Keypoints are delineated with circles, while lines are connected 26 | between matching keypoints. 27 | 28 | img1,img2 - Grayscale images 29 | kp1,kp2 - Detected list of keypoints through any of the OpenCV keypoint 30 | detection algorithms 31 | matches - A list of matches of corresponding keypoints through any 32 | OpenCV keypoint matching algorithm 33 | """ 34 | 35 | # Create a new output image that concatenates the two images together 36 | # (a.k.a) a montage 37 | rows1 = img1.shape[0] 38 | cols1 = img1.shape[1] 39 | rows2 = img2.shape[0] 40 | cols2 = img2.shape[1] 41 | 42 | out = np.zeros((max([rows1,rows2]),cols1+cols2,3), dtype='uint8') 43 | 44 | # Place the first image to the left 45 | out[:rows1,:cols1,:] = np.dstack([img1, img1, img1]) 46 | 47 | # Place the next image to the right of it 48 | out[:rows2,cols1:cols1+cols2,:] = np.dstack([img2, img2, img2]) 49 | 50 | # For each pair of points we have between both images 51 | # draw circles, then connect a line between them 52 | for mat in matches: 53 | 54 | # Get the matching keypoints for each of the images 55 | img1_idx = mat.queryIdx 56 | img2_idx = mat.trainIdx 57 | 58 | # x - columns 59 | # y - rows 60 | (x1,y1) = kp1[img1_idx].pt 61 | (x2,y2) = kp2[img2_idx].pt 62 | 63 | # Draw a small circle at both co-ordinates 64 | # radius 4 65 | # colour blue 66 | # thickness = 1 67 | cv2.circle(out, (int(x1),int(y1)), 4, (255, 0, 0), 1) 68 | cv2.circle(out, (int(x2)+cols1,int(y2)), 4, (255, 0, 0), 1) 69 | 70 | # Draw a line in between the two points 71 | # thickness = 1 72 | # colour blue 73 | cv2.line(out, (int(x1),int(y1)), (int(x2)+cols1,int(y2)), (255, 0, 0), 1) 74 | 75 | 76 | # Show the image 77 | cv2.imshow('Matched Features', out) 78 | cv2.waitKey(0) 79 | cv2.destroyAllWindows() 80 | 81 | if len(sys.argv) == 3: 82 | img1 = cv2.imread(sys.argv[1]) # Original image 83 | img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) 84 | img1 = cv2.resize(img1, (600, 300)) 85 | # rotated = ndimage.rotate(img1, 45) 86 | 87 | img2 = cv2.imread(sys.argv[2]) # Rotated image 88 | img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) 89 | img2 = cv2.resize(img2, (300, 150)) 90 | # cv2.imshow("asa",rotated) 91 | cv2.waitKey(0) 92 | 93 | 94 | orb = cv2.ORB(1000,1.2) 95 | # orb = cv2.SIFT() 96 | 97 | # Detect keypoints of original image 98 | (kp1,des1) = orb.detectAndCompute(img1, None) 99 | 100 | # Detect keypoints of rotated image 101 | (kp2,des2) = orb.detectAndCompute(img2, None) 102 | 103 | bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) 104 | 105 | # Do matching 106 | matches = bf.match(des1,des2) 107 | 108 | drawMatches(img1, kp1, img2, kp2, matches[:10]) -------------------------------------------------------------------------------- /hashes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | from PIL import Image 5 | import numpy as np 6 | 7 | def avhash(im): 8 | if not isinstance(im, Image.Image): 9 | im = Image.open(im) 10 | im = im.resize((8, 8), Image.ANTIALIAS).convert('1').convert('L') 11 | avg = reduce(lambda x, y: x + y, im.getdata()) / 64. 12 | return reduce(lambda x, (y, z): x | (z << y), 13 | enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())), 14 | 0) 15 | 16 | def hamming(h1, h2): 17 | h, d = 0, h1 ^ h2 18 | while d: 19 | h += 1 20 | d &= d - 1 21 | return h 22 | 23 | def phash_simmilarity(img1,img2): 24 | 25 | hash1 = avhash(img1) 26 | hash2 = avhash(img2) 27 | dist = hamming(hash1, hash2) 28 | simm = (64 - dist) * 100 / 64 29 | # print simm 30 | # if not isinstance (img1,Image.Image): 31 | # img1 = Image.open(img1) 32 | # if not isinstance(img2,Image.Image): 33 | # img2 = Image.open(img2) 34 | # hash1 = imagehash.phash(img1) 35 | # hash2 = imagehash.phash(img2) 36 | # dist = hamming(hash2,hash1) 37 | # simm = (64 - dist) * 100 / 64 38 | return simm 39 | 40 | if __name__ == '__main__': 41 | if len(sys.argv) != 3: 42 | print "Usage: %s img1 img2" % sys.argv[0] 43 | else: 44 | img1 = sys.argv[1] 45 | img2 = sys.argv[2] 46 | print "similarity = %d%%" % (phash_simmilarity(img1,img2)) -------------------------------------------------------------------------------- /knn.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import os 4 | import sys 5 | from copy import copy 6 | # Load the images 7 | 8 | formats = ['jpg','png','tif','jpeg'] #Allowed formats 9 | 10 | def knn(img1,images): 11 | # img =cv2.imread("main.jpg") 12 | img = cv2.imread(img1) 13 | imgg = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 14 | 15 | 16 | surf = cv2.SURF(128) # SURF keypoint extraction 17 | kp = surf.detect(imgg) 18 | kp, descritors = surf.compute(imgg,kp) 19 | # surf = cv2.SURF(1024) 20 | 21 | samples = np.array(descritors) # Setting up samples and responses for kNN 22 | responses = np.arange(len(kp),dtype = np.float32) 23 | 24 | knn = cv2.KNearest() # kNN training 25 | knn.train(samples,responses) 26 | 27 | # modelImages = ["main1.jpg", "main2.jpg","man1.png"]#, "grup4.jpg"] 28 | modelImages = images[:] 29 | 30 | for modelImage in modelImages: 31 | 32 | template = cv2.imread(modelImage) # loading a template image and searching for similar keypoints 33 | templateg= cv2.cvtColor(template,cv2.COLOR_BGR2GRAY) 34 | keys = surf.detect(templateg) 35 | 36 | keys,desc = surf.compute(templateg, keys) 37 | count = 0 38 | lent = len(desc) 39 | 40 | for h,des in enumerate(desc): 41 | # print h#,des #debug 42 | # print des.shape 43 | des = des.astype(np.float32).reshape((-1,128)) 44 | 45 | retval, results, neigh_resp, dists = knn.find_nearest(des,1) 46 | res,dist = int(results[0][0]),dists[0][0] 47 | 48 | 49 | if dist<0.1: # draw matched keypoints in red color 50 | # color = (0,0,255) 51 | count += 1 52 | sim = count*100/lent 53 | # else: # draw unmatched in blue color 54 | #print dist 55 | # color = (255,0,0) 56 | 57 | # x,y = kp[res].pt #Draw matched key points on original image 58 | # center = (int(x),int(y)) 59 | # cv2.circle(img,center,2,color,-1) 60 | # x,y = keys[h].pt #Draw matched key points on template image 61 | # center = (int(x),int(y)) 62 | # cv2.circle(template,center,2,color,-1) 63 | 64 | print img1,modelImage,sim 65 | if sim < 80: 66 | # print img1,modelImage 67 | del images[images.index(modelImage)] 68 | # else: #debug 69 | # print img1,modelImage,"sim =",sim 70 | # print "simmilarity =",((count)*100/lent) 71 | # cv2.imshow('img',img) #plot features 72 | # cv2.imshow('tm',template) 73 | # cv2.waitKey(0) 74 | # cv2.destroyAllWindows() 75 | return images 76 | 77 | 78 | if __name__ == "__main__": 79 | files = [] 80 | for fil in os.listdir(sys.argv[1]): 81 | if os.path.isfile(os.path.join(sys.argv[1],fil)) and fil.split('.')[-1].lower() in formats: 82 | files.append(os.path.join(sys.argv[1],fil)) 83 | files.sort() 84 | while files: 85 | img1 = files[0] #get first image from list 86 | # print files 87 | del files[0] #remove first image so it doesnt compare to itself 88 | imgs = knn(img1,files[:]) #get list of similar images 89 | # print ','.join(imgs)," are similar to ",img1 90 | for i in imgs: #remove all similar images from list and delete them from directory 91 | files.remove(i) 92 | os.remove(i) 93 | # files = [i for i in files if i not in imgs] 94 | # print files 95 | 96 | -------------------------------------------------------------------------------- /knnsingle.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import sys 4 | # Load the images 5 | 6 | if sys.argv > 2: 7 | img =cv2.imread(sys.argv[1]) 8 | 9 | # Convert them to grayscale 10 | imgg =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 11 | # imgg = cv2.fastNlMeansDenoising(imgg,None,10,10,20) 12 | 13 | # SURF extraction 14 | surf = cv2.SURF(128) 15 | kp = surf.detect(imgg) 16 | kp, descritors = surf.compute(imgg,kp) 17 | # surf = cv2.SURF(1024) 18 | 19 | # Setting up samples and responses for kNN 20 | samples = np.array(descritors) 21 | responses = np.arange(len(kp),dtype = np.float32) 22 | 23 | # kNN training 24 | knn = cv2.KNearest() 25 | knn.train(samples,responses) 26 | 27 | modelImages = sys.argv[2:] 28 | 29 | for modelImage in modelImages: 30 | 31 | template = cv2.imread(modelImage) #loading a template image and searching for similar keypoints 32 | templateg= cv2.cvtColor(template,cv2.COLOR_BGR2GRAY) 33 | # templateg = cv2.fastNlMeansDenoising(templateg,10,10,10,20) 34 | keys = surf.detect(templateg) 35 | 36 | keys,desc = surf.compute(templateg, keys) # get surf keypoints from template image 37 | count = 0 38 | lent = len(desc) 39 | for h,des in enumerate(desc): 40 | # print h#,des 41 | # print des.shape 42 | des = des.astype(np.float32).reshape((-1,128)) 43 | 44 | retval, results, neigh_resp, dists = knn.find_nearest(des,1) 45 | res,dist = int(results[0][0]),dists[0][0] 46 | 47 | 48 | if dist<0.1: # draw matched keypoints in red color 49 | color = (0,0,255) 50 | count += 1 51 | 52 | else: # draw unmatched in blue color 53 | #print dist 54 | color = (255,0,0) 55 | 56 | x,y = kp[res].pt # draw matched key points on original image 57 | center = (int(x),int(y)) 58 | cv2.circle(img,center,2,color,-1) 59 | 60 | x,y = keys[h].pt # draw matched key points on template image 61 | center = (int(x),int(y)) 62 | cv2.circle(template,center,2,color,-1) 63 | 64 | # print "" 65 | 66 | cv2.imshow('img similarity = %s'%(count*100/lent),img) #similarity = TP/P = count/lent 67 | cv2.imshow('tm',template) 68 | cv2.waitKey(0) 69 | cv2.destroyAllWindows() --------------------------------------------------------------------------------