When we are comparing two images, we have to compute the similarity score between them. In this tutorial, we will compute its similarity score using python opencv sift.
How to use opencv SIFT?
In order to use sift in opencv, we have to use python opencv 3.4.2.16. Otherwise, you will get AttributeError: module ‘cv2’ has no attribute ‘xfeatures2d’ error.
Fix AttributeError: module ‘cv2’ has no attribute ‘xfeatures2d’ – Python OpenCV Tutorial
How to compute the similarity score between two images?
Here we will give you a full example code to compute.
import cv2 import matplotlib.pyplot as plt # Resize images to a similar dimension # This helps improve accuracy and decreases unnecessarily high number of keypoints def imageResizeTrain(image): maxD = 1024 height,width = image.shape aspectRatio = width/height if aspectRatio < 1: newSize = (int(maxD*aspectRatio),maxD) else: newSize = (maxD,int(maxD/aspectRatio)) image = cv2.resize(image,newSize) return image def imageResizeTest(image): maxD = 1024 height,width,channel = image.shape aspectRatio = width/height if aspectRatio < 1: newSize = (int(maxD*aspectRatio),maxD) else: newSize = (maxD,int(maxD/aspectRatio)) image = cv2.resize(image,newSize) return image def computeSIFT(image): sift = cv2.xfeatures2d.SIFT_create() return sift.detectAndCompute(image, None) def calculateResultsFor(image_1,image_2): image_1_data = imageResizeTrain(cv2.imread(image_1,0)) image_2_data = imageResizeTrain(cv2.imread(image_2, 0)) keypoint1, descriptor1 = computeSIFT(image_1_data) keypoint2, descriptor2 = computeSIFT(image_2_data) matches = calculateMatches(descriptor1, descriptor2) score = calculateScore(len(matches),len(keypoint1),len(keypoint2)) plot = getPlotFor(image_1,image_2,keypoint1,keypoint2,matches) #print(len(matches),len(keypoint1),len(keypoint2),len(descriptor1),len(descriptor2)) #print(score) # 结果 plt.imshow(plot),plt.show() return score def getPlotFor(image1,image2,keypoint1,keypoint2,matches): image1 = imageResizeTest(cv2.imread(image1)) image2 = imageResizeTest(cv2.imread(image2)) return getPlot(image1,image2,keypoint1,keypoint2,matches) def calculateScore(matches,keypoint1,keypoint2): return 100 * (matches/min(keypoint1,keypoint2)) def calculateMatches(des1, des2): bf = cv2.BFMatcher() matches = bf.knnMatch(des1, des2, k=2) topResults1 = [] for m, n in matches: if m.distance < 0.7 * n.distance: topResults1.append([m]) matches = bf.knnMatch(des2, des1, k=2) topResults2 = [] for m, n in matches: if m.distance < 0.7 * n.distance: topResults2.append([m]) topResults = [] for match1 in topResults1: match1QueryIndex = match1[0].queryIdx match1TrainIndex = match1[0].trainIdx for match2 in topResults2: match2QueryIndex = match2[0].queryIdx match2TrainIndex = match2[0].trainIdx if (match1QueryIndex == match2TrainIndex) and (match1TrainIndex == match2QueryIndex): topResults.append(match1) return topResults def getPlot(image1,image2,keypoint1,keypoint2,matches): image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB) image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2RGB) matchPlot = cv2.drawMatchesKnn(image1,keypoint1,image2,keypoint2,matches,None,[255,255,255],flags=2) return matchPlot #-- imageList = [ r"C:\Users\yuzhilun\Desktop\book_cover\1.png", r"C:\Users\yuzhilun\Desktop\book_cover\2.png", r"C:\Users\yuzhilun\Desktop\book_cover\3.png", r"C:\Users\yuzhilun\Desktop\book_cover\4.png"] lx = len(imageList) -1 for i in range(lx): score = calculateResultsFor(imageList[i],imageList[i+1]) print(imageList[i],imageList[i+1],score)
In this example, we will use calculateResultsFor() function to compute the similarity score between two image. This function will receive two images and return their similarity score.
Run this code, we will see:
C:\Users\yuzhilun\Desktop\book_cover\1.png C:\Users\yuzhilun\Desktop\book_cover\2.png 0.125 C:\Users\yuzhilun\Desktop\book_cover\2.png C:\Users\yuzhilun\Desktop\book_cover\3.png 0.1875 C:\Users\yuzhilun\Desktop\book_cover\3.png C:\Users\yuzhilun\Desktop\book_cover\4.png 0.1405152224824356
From the result, we can find:if the score is low, these two images are different.