Ask Your Question

Revision history [back]

Opencv Python - Similarity score from Feature matching + Homograpy

I have several fish images in my database , My Goal is to find similarity score between user input fish image and images in database. For that I am using opencv Feature matching + Homograpy from this link.

http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html#feature-homography

My current code is as followed.

query_image = '/home/zealous/Pictures/train_images/AbudefdufWhitleyiJER.jpg'
trained_image_folder = '/home/zealous/Pictures/train_images'

My current code is as followed.

def feature_matcher(query_image, image_folder):

    min_match_count = 10

    img1 = cv2.imread(query_image, 0)
    surf = cv2.xfeatures2d.SURF_create(800)
    kp1, des1 = surf.detectAndCompute(img1, None)

    bf = cv2.BFMatcher(cv2.NORM_L2)

    all_files = next(os.walk(image_folder))[2]

    for file_name_temp in all_files:
        try:
            train_image = image_folder + '/' + file_name_temp
            img2 = cv2.imread(train_image, 0)
            surf = cv2.xfeatures2d.SURF_create(800)
            kp2, des2 = surf.detectAndCompute(img2, None)

            matches = bf.knnMatch(des1, des2, k=2)

            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 = cv2.findHomography(src_pts, dst_pts, cv2.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 = cv2.perspectiveTransform(pts, M)

                if not M==None:
                    print "\n"
                    print "-"*2, file_name_temp
                    print "number of good matches", len(good)
                    print "*"*10, matchesMask

I am getting pretty good output which I am assuming by seeing number of good matches and matchesMask variable (which contains some 0's and 1's). If database contains same image as input image then there will be many good matches and all matchesMask elements will be 1.

My question is how to calculate similarity score based on this? should I assume that the more number of 1's (Inliers) are there in matchesMask, more both images are similar or should I take ratio between number of 1's(inliers) and 0's(outliers) and calculate similarity based on that.

I know this has been discussed in many questions , but all the suggestions and answers are in C++ language , so I cant figure out solution..

click to hide/show revision 2
retagged

updated 2015-04-22 04:35:05 -0600

berak gravatar image

Opencv Python - Similarity score from Feature matching + Homograpy

I have several fish images in my database , My Goal is to find similarity score between user input fish image and images in database. For that I am using opencv Feature matching + Homograpy from this link.

http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.html#feature-homography

My current code is as followed.

query_image = '/home/zealous/Pictures/train_images/AbudefdufWhitleyiJER.jpg'
trained_image_folder = '/home/zealous/Pictures/train_images'

My current code is as followed.

def feature_matcher(query_image, image_folder):

    min_match_count = 10

    img1 = cv2.imread(query_image, 0)
    surf = cv2.xfeatures2d.SURF_create(800)
    kp1, des1 = surf.detectAndCompute(img1, None)

    bf = cv2.BFMatcher(cv2.NORM_L2)

    all_files = next(os.walk(image_folder))[2]

    for file_name_temp in all_files:
        try:
            train_image = image_folder + '/' + file_name_temp
            img2 = cv2.imread(train_image, 0)
            surf = cv2.xfeatures2d.SURF_create(800)
            kp2, des2 = surf.detectAndCompute(img2, None)

            matches = bf.knnMatch(des1, des2, k=2)

            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 = cv2.findHomography(src_pts, dst_pts, cv2.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 = cv2.perspectiveTransform(pts, M)

                if not M==None:
                    print "\n"
                    print "-"*2, file_name_temp
                    print "number of good matches", len(good)
                    print "*"*10, matchesMask

I am getting pretty good output which I am assuming by seeing number of good matches and matchesMask variable (which contains some 0's and 1's). If database contains same image as input image then there will be many good matches and all matchesMask elements will be 1.

My question is how to calculate similarity score based on this? should I assume that the more number of 1's (Inliers) are there in matchesMask, more both images are similar or should I take ratio between number of 1's(inliers) and 0's(outliers) and calculate similarity based on that.

I know this has been discussed in many questions , but all the suggestions and answers are in C++ language , so I cant figure out solution..