SIFT Feature Extraction Using OpenCV in Python

Posted in /  

SIFT Feature Extraction Using OpenCV in Python

Vinay Khatri
Last updated on June 10, 2022

    SIFT is among the most popular feature detection algorithms. Continue reading below to know how to accomplish SIFT feature extraction using OpenCV in Python. So what are the features in an image?

    Although there is no exact or universal definition of the features in an image, simply put, the features in an image are the information that defines the image.

    Let's say, we have an image of the book cover of " The Alchemist. "

    And if we talk about its features, everything in the image is the features of the image. All the letters, edges, pyramids, objects, space between the letters, blobs, ridges, etc. are the features of the image.

    To detect these features from an image we use the feature detection algorithms. There are various feature detection algorithms, such as SIFT, SURF, GLOH , and HOG .

    For this Python tutorial, we will be using SIFT Feature Extraction Algorithm Using the OpenCV library and extract features of an image. There are many applications of image feature detection and comparing two images is one of the most important applications.

    So here in this Python tutorial, first, we will write Python code to detect or extract features in an image using the Scale Invariant Feature Transform (SIFT) algorithm and OpenCV. Then we will compare the two images based on the extracted features. Before we jump to the Python code, let's install the dependencies.

    Installing Dependencies

    Install Python OpenCV Contribution Library

    Unfortunately, the OpenCV library does not come with the implementation of SIFT algorithms. Thus, we will be installing the community contribution OpenCV library, which supports all the features provided by the standard OpenCV library and many more. To install the community contribution version of Python OpenCV, run the following pip command on your terminal or command prompt:

    pip install opencv-contrib-python

    This command will install the opencv-contrib-python library for your Python environment. To install numpy, run the following pip command:

    pip install numpy

    Image

    For this tutorial, we will be using the following image "book.jpg."

    We would suggest you save the image file in the same directory of your Python script, so you can easily load the image with a relative path. Now we are all done with the dependencies.

    So, let's open your favorite Python IDE or Text editor and start coding.

    How to Perform SIFT Feature Extraction Using OpenCV in Python?

    Let's start with importing the module with the following command:

    import cv2 as cv

    After importing the module, load the image using the OpenCV cv.imread() method as shown below:

    #load image
    image = cv.imread("book.jpg")

    After loading the image, convert the image into a GrayScale image because we do not want to perform the feature extraction on the default Blue, Green, and Red (BGR) image. Doing so will have no effect on extracting features. To convert a BGR image to GrayScale, we use the OpenCV cv.cvtColor() method as shown below:

     #convert to grayscale image
    gray_scale = cv.cvtColor(image, cv.COLOR_BGR2GRAY)

    Now, let's load the SIFT algorithm by initializing its object. To initialize the SIFT object we can use the cv.xfeatures2d.SIFT_create() method:

    #initialize SIFT object
    sift = cv.xfeatures2d.SIFT_create()

    Now with the help of the sift object, let's  detect all the features in the image. And this can be performed with the help of sift detectAndCompute() method:

    #detect keypoints
    keypoints, _= sift.detectAndCompute(image, None)

    Here, we are detecting the keypoints in the image, and the None is the attribute value for the mask . Because here we are finding all the keypoints and features of the image, that's why the value of the mask is None.

    The value of the mask can be provided when we are looking for the keypoints or features for a specific portion. The detectAndCompute(image, None) method returns two values, keypoints and descriptors.

    For this program, we do not require descriptors and that's why we use the underscore _ there. After detecting the features let's draw all the key points on the gray_scale image. To draw all the key points on an image we can use the cv.drawKeypoints() method.

    #draw keypoints
    sift_image = cv.drawKeypoints(gray_scale, keypoints, None)

    Now let's see the sift_image with the cv.imshow() method:

    #show image
    cv.imshow("Features Image", sift_image)
    
    #hold the window
    cv.waitKey(0)

    Now put all the code together and execute.

    #Python Program to Extract Features from an image using SIFT Feature Extraction

    import cv2 as cv
    
    #load image
    image = cv.imread("book.jpg")
    
    #convert to grayscale image
    gray_scale = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    
    #initialize SIFT object
    sift = cv.xfeatures2d.SIFT_create()
    
    #detect keypoints
    keypoints, _= sift.detectAndCompute(image, None)
    
    #draw keypoints
    sift_image = cv.drawKeypoints(gray_scale, keypoints, None)
    
    cv.imshow("Features Image", sift_image)
    cv.waitKey(0)

    Output

    When you execute the above program you will see a similar output like this:

    From the above image, you can see that the OpenCV SIFT algorithm put all the key points on the image.

    Match Two Images in OpenCV Using the SIFT Extraction Feature

    Now that you know how to extract features in an image, let's try something. With the help of the extracted features, we can compare 2 images and look for the common features in them.

    Let's say we have two images of a book. The first image, image1 , is the front cover of the book as shown below:

    And the second image image2 is the front and back cover of the same book: Now, if we want to compare both the images and look for the common components then we have to first extract features from individual images and compare them. To extract the features from both the images we will use the SIFT algorithm and match the features with Brute Force Matcher.

    Let's start coding. First, import the OpenCV module and load both the images:

    import cv2 as cv
    
    #load images
    image1 = cv.imread("image1.jpg")
    image2 = cv.imread("image2.jpg")
    Next, convert both the images into GrayScale images:
    
    #convert to grayscale image
    gray_scale1 = cv.cvtColor(image1, cv.COLOR_BGR2GRAY)
    gray_scale2 = cv.cvtColor(image2, cv.COLOR_BGR2GRAY)

    Initialize the SIFT object and detect keypoints and descriptors( des1, des2 ) from both the images image1 and image2 with the help of the sift.detectAndCompute() method:

    #initialize SIFT object
    sift = cv.xfeatures2d.SIFT_create()
    
    keypoints1, des1= sift.detectAndCompute(image1, None)
    keypoints2, des2= sift.detectAndCompute(image2, None)

    Note : The Descriptors define the features independent of the properties of the image. As we have Descriptors for both the images, now we can use the Brute Force Matcher to match the descriptors. The Brute Force Matcher will compare the descriptor and match the closest ones. To use the Brute Force Matcher in OpenCV first we need to initialize its object using the BFMatcher() class as shown below:

    # initialize Brute force matching
    bf = cv.BFMatcher(cv.NORM_L1, crossCheck=True)

    Now match the descriptors des1 and des2 with the bf.match() method:

    matches = bf.match(des1,des2)

    The bf.match() method matches both the descriptors and returns a list of matched objects . And each matched object contains some information, including distance. The smaller the distance, the better is the match. So, let's sort all the matches based on the distance of individual matched objects:

     #sort the matches 
    matches = sorted(matches, key= lambda match : match.distance)

    Now we need to draw all the matches with the help of cv.drawMatches() :

    matched_imge = cv.drawMatches(image1, keypoints1, image2, keypoints2, matches[:30], None)

    Here we are only drawing the best 30 matches with the matches[:30] parameter. Let's show all the matched images (matched_image) with the imshow() method:

    cv.imshow("Matching Images", matched_imge)
    cv.waitKey(0)

    Now put all code together and execute.

    #Python program to compare two Images with SIFT Feature Extraction

    import cv2 as cv
    
    #load images
    image1 = cv.imread("image1.jpg")
    image2 = cv.imread("image2.jpg")
    
    #convert to grayscale image
    gray_scale1 = cv.cvtColor(image1, cv.COLOR_BGR2GRAY)
    gray_scale2 = cv.cvtColor(image2, cv.COLOR_BGR2GRAY)
    
    #initialize SIFT object
    sift = cv.xfeatures2d.SIFT_create()
    
    keypoints1, des1= sift.detectAndCompute(image1, None)
    keypoints2, des2= sift.detectAndCompute(image2, None)
    
    # initialize Brute force matching
    bf = cv.BFMatcher(cv.NORM_L1, crossCheck=True)
    
    matches = bf.match(des1,des2)
    
    #sort the matches 
    matches = sorted(matches, key= lambda match : match.distance)
    
    matched_imge = cv.drawMatches(image1, keypoints1, image2, keypoints2, matches[:30], None)
    
    cv.imshow("Matching Images", matched_imge)
    cv.waitKey(0)

    Output

    Conclusion

    In this Python tutorial, we learned how to detect features in an image using the OpenCV SIFT algorithm. The Standard OpenCV library does not provide SIFT algorithm implementation that's why here we have used its contribution version, which contains more features than the standard OpenCV module.

    Here, you also learned how to compare two images using the SIFT algorithm.

    People are also reading:

    Leave a Comment on this Post

    0 Comments