Open In App

Python OpenCV – FlannBasedMatcher() Function

Last Updated : 15 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Flann stands for Fast Library for Approximate Nearest Neighbors. It is actually used for the system to choose the best algorithm and optimum parameters depending on the dataset. FlannBasedMatcher is also used to match or search for the features of one image to another image. this function is available in the OpenCV library.  It uses Nearest Neighbors Approach and usually runs faster than BruteForceMatcher for various datasets. It also works great with large datasets. Here the feature descriptors searched for the nearest numerical values for feature match and its neighbor’s distance computation is easy and done fastly. For FlannBasedMatcher we need to pass dictionaries which are index_params and search params. 

This library uses a set of techniques to achieve its speed, including approximate k-d trees and randomized kd-trees. These data structures are used to organize the data in such a way that the search for nearest neighbors can be done more quickly when compared to other traditional methods. In general, FLANN works by first building an index of the data set using one of the supported indexing methods. Once the index is built, the user can perform nearest-neighbor searches by querying the index with a new point. The index returns the nearest neighbors to the query point, along with their distances. Both Randomized k-d Tree and Priority-based K-Means are efficient approximate nearest neighbor search algorithms that can be used in FLANN, the choice of algorithm depends on the specific requirements of the application.

Example: 

In this example, the sub-image and the main image are loaded using the cv2.imread() function. The SIFT detector is then used to detect key points and compute descriptors in the query and train images using the sift.detectAndCompute() function. The FLANN object is then created using the cv2.FlannBasedMatcher() class. The knnMatch() function is used to perform a k-nearest neighbor search to find the two nearest neighbors. The matches are then filtered using a distance ratio test. The good matches are then drawn using the cv2.drawMatches() function and the result is displayed using the plt.imshow() function.

This is a basic example of how to use FLANN and SIFT together in OpenCV for object detection. You can also experiment with different parameters, such as the number of nearest neighbors to search for, the algorithm used in FLANN, and the threshold value used in the distance ratio test to get the best results for specific use case. for more precision you need to use different parameters according to need.

Input: 

main_image :

geeks-half -Geeksforgeeks

main image

sub_image

sub_image

Code Explanations

  1. Flanned_Matcher(main_image,sub_image).
  2.  Find index_params and search param.
  3. Pass to FlannBasedMatcher(index_params,search_params) function.
  4. Matches all the features which are similar.
  5. After matching all the features store it in another variable.
  6. Returns the stored image.

Python3




import cv2 as cv
import matplotlib.pyplot as plt
 
#Function returns the feature matched image
def Flanned_Matcher(main_image,sub_image):
   
    # Initiating the SIFT detector
    sift = cv.SIFT_create()
 
    #Find the keypoints and descriptors with SIFT.
    key_point1, descr1 = sift.detectAndCompute(main_image,None)
    key_point2, descr2 = sift.detectAndCompute(sub_image,None)
 
    # FLANN parameters.
    FLANN_INDEX_KDTREE = 0
    index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    search_params = dict(checks=50)
 
    # FLANN based matcher with implementation of k nearest neighbour.
    flann = cv.FlannBasedMatcher(index_params,search_params)
    matches = flann.knnMatch(descr1,descr2,k=2)
 
    # selecting only good matches.
    matchesMask = [[0,0] for i in range(len(matches))]
 
    # ratio test.
    for i,(m,n) in enumerate(matches):
        if( m.distance < 0.1*n.distance):
            matchesMask[i]=[1,0]
    draw_params = dict(matchColor = (0,255,0),
                       singlePointColor = (255,0,0),
                       matchesMask = matchesMask,flags = 0)
     
    # drawing nearest neighbours
    img = cv.drawMatchesKnn(main_image,
                            key_point1,
                            sub_image,
                            key_point2,
                            matches,
                            None,
                            **draw_params)
    return img
 
# reading two input images
main_image = cv.imread('geeks-full.png')
sub_image = cv.imread('geeks-half.jpg')
 
#Passing two input images
output=Flanned_Matcher(main_image,sub_image)
 
# Save the image
cv2.imwrite('Match.jpg', output)


Output:

True
FlannBasedMatcher -Geeksforgeeks

FlannBasedMatcher Output

The output is True representing that matched output image is saved with the name Match.jpg in the local folder

Example 2:

Code Explanations

  1. Cv2.imread() is to read the image file for both images.
  2. Initialize the SIFT detector with cv2.SIFT_create()
  3. Use SIFT detector to detect the key points and descriptors from both images.
  4.  Find index_params and search param for the KNN algorithm.
  5. Initialize the FlannBasedMatcher by using cv2.FlannBasedMatcher(index_params,search_params) function.
  6. Matches all the features which are similar by FlannBasedMatcher between both the descriptors.
  7. After matching all the features store it in another variable and filtered the good matches only if distance is less than 0.5 (Here we change as per our requirements)
  8. Draw the matches between both images using cv2.drawMatchesKnn()
  9. Save the matched image to the local folder.

Python3




import numpy as np
import cv2
 
# load the images
image1 = cv2.imread('Bhagavad-Gita.jpg')
image2 = cv2.imread('Geeta.jpg')
 
#img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
#img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
 
# Initiate SIFT detector
sift = cv2.SIFT_create()
 
# find the keypoints and descriptors with SIFT
keypoint1, descriptors1 = sift.detectAndCompute(image1, None)
keypoint2, descriptors2 = sift.detectAndCompute(image2, None)
 
# finding nearest match with KNN algorithm
index_params = dict(algorithm=0, trees=20)
search_params = dict(checks=150)   # or pass empty dictionary
 
# Initialize the FlannBasedMatcher
flann = cv2.FlannBasedMatcher(index_params, search_params)
 
Matches = flann.knnMatch(descriptors1, descriptors2, k=2)
 
# Need to draw only good matches, so create a mask
good_matches = [[0, 0] for i in range(len(Matches))]
 
# Ratio Test
for i, (m, n) in enumerate(Matches):
    if m.distance < 0.5*n.distance:
        good_matches[i] = [1, 0]
 
# Draw the matches using drawMatchesKnn()
Matched = cv2.drawMatchesKnn(image1,
                             keypoint1,
                             image2,
                             keypoint2,
                             Matches,
                             outImg=None,
                             matchColor=(0, 155, 0),
                             singlePointColor=(0, 255, 255),
                             matchesMask=good_matches,
                             flags=0
                             )
 
# Displaying the image 
cv2.imwrite('Match.jpg', Matched)


Output:

True
FlannBasedMatcher -Geeksforgeeks

FlannBasedMatcher Output Image

The output is True representing that matched output image is saved with the name Match.jpg in the local folder

Applications:

  • Pattern Recognition.
  • Selection of best algorithm and parameters.
  • Feature Matching.
  • Data Compression.
  • Cluster Analysis.
  • DBMS.
  • Computational Geometry.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads