0

I am using canny for image comparison. I am getting correct results for matching and non matching objects after comparing using canny image edging. At times it is not giving the right result and for that I need to keep changing the MIN_MATCH_COUNT. Any solution to keep the MIN_MATCH_COUNT and canny should compare each and every edge of the image.

MIN_MATCH_COUNT = 20

img1 = canny.copy()
img2 = canny1.copy()


# Initiate SIFT detector
sift = cv.SIFT_create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
# store all the good matches as per Lowe's ratio test.
good = []
for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append(m)
if len(good)>MIN_MATCH_COUNT:
    src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
    dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
    M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC,5.0)
    matchesMask = mask.ravel().tolist()
    h,w = img1.shape
    pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
    dst = cv.perspectiveTransform(pts,M)
    img2 = cv.polylines(img2,[np.int32(dst)],True,255,3, cv.LINE_AA)
    print ("Both the images are matching")
else:
    print( "Not enough matches are found and hence images are not same - {}/{} and hence both the images are not matching".format(len(good), MIN_MATCH_COUNT) )
    matchesMask = None
draw_params = dict(matchColor = (0,255,0), # draw matches in green color 
                   singlePointColor = None,
                   matchesMask = matchesMask, # draw only inliers
                   flags = 2)
img3 = cv.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.imshow(img3, 'gray'),plt.show()   

Below is the image where I am getting result as not matching when MIN_MATCH_COUNT is 20 and if I change it to 9 then it will say images are matching. enter image description here

Similarly in below image also actual ridges of keys are not matching but its still giving the images are matching without considering the matching point.

enter image description here

Amaze_Rock
  • 163
  • 3
  • 16

1 Answers1

0

You could use a relative criteria, so instead of using an asbolute value for MIN_MATCH_COUNT you can use the percentage of matching keypoints over the total number of keypoints of your model. In this way you can set a threshold based on your specific test, let's say..30% (IDK, just an example). That's what I do in a similar issue. Something like:

matching = len(good)/len(kp1)*100

In this way 0<matching<100 and represent a percentage of similarity, so you can do:

min_threshold = 40

if matching > min_threshold:
...
rok
  • 2,574
  • 3
  • 23
  • 44
  • Can you share some example. – Amaze_Rock May 20 '21 at 07:25
  • edited, basically you go from an absolute value to a relative value for the threshold. You still have to experiment in order to find a value that works for you. – rok May 20 '21 at 07:44
  • OK...Thanks...Below code is working better for me but not able to identify the if condition to print the images are matching or not matching. img1 = cv.imread('Key1.png',cv.IMREAD_GRAYSCALE) # queryImage img2 = cv.imread('Key2.png',cv.IMREAD_GRAYSCALE) # trainImage # Initiate SIFT detector sift = cv.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) kp2, des2 = sift.detectAndCompute(img2,None) – Amaze_Rock May 20 '21 at 07:51
  • # FLANN parameters FLANN_INDEX_KDTREE = 1 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) search_params = dict(checks=50) # or pass empty dictionary flann = cv.FlannBasedMatcher(index_params,search_params) matches = flann.knnMatch(des1,des2,k=2) – Amaze_Rock May 20 '21 at 07:52
  • # Need to draw only good matches, so create a mask matchesMask = [[0,0] for i in range(len(matches))] # ratio test as per Lowe's paper for i,(m,n) in enumerate(matches): if m.distance < 0.7*n.distance: matchesMask[i]=[1,0] draw_params = dict(matchColor = (0,255,0), singlePointColor = (255,0,0), matchesMask = matchesMask, flags = cv.DrawMatchesFlags_DEFAULT) img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params) plt.imshow(img3,),plt.show() – Amaze_Rock May 20 '21 at 07:53
  • Please don't post code in comments.. please open a new question if this is solved. Code is totally unreadable in comments. – rok May 20 '21 at 08:01
  • Sure Posting new question. – Amaze_Rock May 20 '21 at 08:21
  • Hi added new question. https://stackoverflow.com/questions/67616711/how-to-add-if-else-for-print-in-flann-image-comparison – Amaze_Rock May 20 '21 at 08:28
  • matching = len(matches)/len(kp1)*100 min_threshold = 40 for i,(m,n) in enumerate(matches): if m.distance < 0.7*n.distance: matchesMask[i]=[1,0] draw_params = dict(matchColor = (0,255,0), singlePointColor = (255,0,0), matchesMask = matchesMask, flags = cv.DrawMatchesFlags_DEFAULT) img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params) plt.imshow(img3,),plt.show() if matching > min_threshold: print ("Images are same") else: print ("Images are different") – Amaze_Rock May 26 '21 at 12:14
  • I used Above code. When I check print matching then every time it is showing me value as 100 and thus I am getting 'Images are same' as matching is always greater than min threshold. Any suggestion? – Amaze_Rock May 26 '21 at 12:17