16

I'm trying to use OpenCV to extract SURF descriptors from an image. I'm using OpenCV 2.4 and Python 2.7, but am struggling to find any documentation that provides any information about how to use the functions. I've been able to use the following code to extract features, but I can't find any sensible way to extract descriptors:

import cv2

img = cv2.imread("im1.jpg")
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

surf = cv2.FeatureDetector_create('SURF')
detector = cv2.GridAdaptedFeatureDetector(surf, 50) # max number of features
fs = detector.detect(img2)

The code I tried for extracting descriptors is:

import cv2
img = cv2.imread("im3.jpg")
sd = cv2.FeatureDetector_create("SURF")
surf = cv2.DescriptorExtractor_create("SURF")
keypoints = []
fs = surf.compute(img, keypoints) # returns empty result
sd.detect(img) # segmentation faults

Does anyone have any sample code that does this kind of thing, or pointers to any documentation that provides samples?

Ben
  • 66,838
  • 37
  • 84
  • 108

4 Answers4

14

Here's an example of some code I've written for extracting SURF features using Python 2.7 and OpenCV 2.4.

im2 = cv2.imread(imgPath)
im = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)
surfDetector = cv2.FeatureDetector_create("SURF")
surfDescriptorExtractor = cv2.DescriptorExtractor_create("SURF")
keypoints = surfDetector.detect(im)
(keypoints, descriptors) = surfDescriptorExtractor.compute(im,keypoints)

This works and returns a set of descriptors. Unfortunately since cv2.SURF() doesn't work in 2.4, you have to go through this tedious process.

Kkov
  • 1,472
  • 2
  • 11
  • 20
  • That worked! Finally! Thank you. One small edit: you've got features.detect, but features isn't defined: I think you mean surfDetector.detect. That seems to work. Thanks! – Ben May 29 '12 at 21:56
  • Corrected the mistake. Glad I could help. – Kkov May 29 '12 at 23:09
6

Here is a simple bit of code I did for uni fairly recently. It captures the image from a camera and displays the detected keypoints on the output image in real-time. I hope it is of use to you.

There is some documentation here.

Code:

import cv2

#Create object to read images from camera 0
cam = cv2.VideoCapture(0)

#Initialize SURF object
surf = cv2.SURF(85)

#Set desired radius
rad = 2

while True:
    #Get image from webcam and convert to greyscale
    ret, img = cam.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    #Detect keypoints and descriptors in greyscale image
    keypoints, descriptors = surf.detect(gray, None, False)

    #Draw a small red circle with the desired radius
    #at the (x, y) location for each feature found
    for kp in keypoints:
        x = int(kp.pt[0])
        y = int(kp.pt[1])
        cv2.circle(img, (x, y), rad, (0, 0, 255))

    #Display colour image with detected features
    cv2.imshow("features", img)

    #Sleep infinite loop for ~10ms
    #Exit if user presses <Esc>
    if cv2.waitKey(10) == 27:
        break
Pep_8_Guardiola
  • 5,002
  • 1
  • 24
  • 35
  • Thanks! Strangely, although the documentation shows cv2.SURF for v2.4.0 of OpenCV, when I try it, it doesn't work: AttributeError: 'module' object has no attribute 'SURF' – Ben May 29 '12 at 13:31
  • @Ben Did you use my code exactly, or copy bits into yours? I know for sure it worked when I used it last, but that may have been on version 2.3.x. Unfortunately I'm at work and can't test it out here. – Pep_8_Guardiola May 29 '12 at 13:45
  • I tried your code exactly as is... It balks on the third code line (surf = cv2.SURF(85)) but it also looks like the surf.detect function has changed from the version you were using... Maybe I need to downgrade OpenCV to 2.3.x... – Ben May 29 '12 at 13:49
  • In the documentation I linked, it looks exactly the same: cv2.SURF(_hessianThreshold[, _nOctaves[, _nOctaveLayers[, _extended[, _upright]]]]) should return a SURF object. cv2.SURF.detect(img, mask[, useProvidedKeypoints]) then returns keypoints, descriptors. I'm not sure what the problem is, sorry. – Pep_8_Guardiola May 29 '12 at 14:01
  • @Ben I have just found [this answer](http://stackoverflow.com/questions/10709610/surf-missing-in-opencv-2-4-for-python). My code is fine, there is a problem with the latest release of OpenCV that will be fixed in the next release. There is an example of extracting the descriptors provided in that link. Hope this helps – Pep_8_Guardiola May 29 '12 at 14:32
  • Thanks for the help! Unfortunately, it does look as though v2.4 just doesn't support this stuff, or at least if it does then it's undocumented. I tried that code for extracting the descriptor, but then I don't know how to make use of them. I tried doing it as in your code, but it wants two arguments now instead of 3, and when I try passing in two arguments, it seg-faults: surf_detector.detect(im, None) – Ben May 29 '12 at 14:55
5

Using open cv 2.4.3, you can do the following:

import cv2
surf = cv2.SURF()
keypoints, descriptors = surf.detectAndCompute(img,None,useProvidedKeypoints = True)
lizzie
  • 1,506
  • 1
  • 18
  • 31
2

todofixthis I follow your code and I get this

import cv2
img = cv2.imread("im3.jpg")
sd = cv2.FeatureDetector_create("SURF")
surf = cv2.DescriptorExtractor_create("SURF")
keypoints = sd.detect(img) # segmentation faults
l,d = surf.compute(img, keypoints) # returns empty result

where

l = keypoints

d = descriptor

Andro Selva
  • 53,910
  • 52
  • 193
  • 240
Enu
  • 21
  • 1