Ask Your Question
0

pyopencv_from and pyopencv_to for KeyPoint class

asked 2014-09-30 08:54:42 -0600

Fe++ gravatar image

Since Bag of Words is not wrapped in Python, I need to do the work in Cpp function and pass the results through libboost interface. Still, I cannot figure out how a KeyPoint class is transformed to a PyObject* and viceversa. Is there any pyopencv_from and pyopencv_to method for that? Thanks.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
4

answered 2014-09-30 11:00:05 -0600

berak gravatar image

updated 2014-09-30 11:07:21 -0600

none of this should be nessecary, since BOW is wrapped to python in 2.4.9.

import cv2
import numpy as np

#
# based on :
#  http://gilscvblog.wordpress.com/2013/08/23/bag-of-words-models-for-visual-categorization/
#
# for this sample, we'll use the left/right checkerboard shots from samples/cpp.
#  admittedly, there's not much sense in training an svm on left vs right checkerboards, 
#  but it shows the general flow nicely.
#
# please modify !
datapath="e:/code/opencv/samples/cpp"
def path(cls,i): # "./left03.jpg"
    return "%s/%s%02d.jpg"  % (datapath,cls,i+1)


detect = cv2.FeatureDetector_create("SIFT")
extract = cv2.DescriptorExtractor_create("SIFT")

flann_params = dict(algorithm = 1, trees = 5)      # flann enums are missing, FLANN_INDEX_KDTREE=1
matcher = cv2.FlannBasedMatcher(flann_params, {})  # need to pass empty dict (#1329)


## 1.a setup BOW
bow_train   = cv2.BOWKMeansTrainer(8) # toy world, you want more.
bow_extract = cv2.BOWImgDescriptorExtractor( extract, matcher )

## try those, please!
#help(bow_train) 
#help(bow_extract)

## 1.b add positives and negatives to the bowtrainer, use SIFT DescriptorExtractor 
def feature_sift(fn):
    im = cv2.imread(fn,0)
    return extract.compute(im, detect.detect(im))[1]

for i in range(8):
    bow_train.add(feature_sift(path("left", i)))
    bow_train.add(feature_sift(path("right",i)))


## 1.c kmeans cluster descriptors to vocabulary
voc = bow_train.cluster()
bow_extract.setVocabulary( voc )
print "bow vocab", np.shape(voc)

## 2.a gather svm training data, use BOWImgDescriptorExtractor
def feature_bow(fn):
    im = cv2.imread(fn,0)
    return bow_extract.compute(im, detect.detect(im))

traindata, trainlabels = [],[]
for i in range(6): # save first 2 for testing
    traindata.extend(feature_bow(path("left", i+2))); trainlabels.append(-1)
    traindata.extend(feature_bow(path("right",i+2))); trainlabels.append(1)

print "svm items", len(traindata), len(traindata[0])

## 2.b create & train the svm
svm = cv2.SVM()
#params = dict( kernel_type=cv2.SVM_RBF, svm_type=cv2.SVM_C_SVC, C=1, gamma=0.5 )
svm.train(np.array(traindata), np.array(trainlabels))#,np.array(),np.array(),params)


## 2.c predict the remaining 2*2 images, use BOWImgDescriptorExtractor again
def predict(fn):
    f = feature_bow(fn);    
    p = svm.predict(f)
    print fn, "\t", p 

for i in range(2): #  testing
    predict( path("left",i) )
    predict( path("right",i) )


"""
bow vocab (8, 128)
svm items 12 8
e:/code/opencv/samples/cpp/left01.jpg   -1.0
e:/code/opencv/samples/cpp/right01.jpg  1.0
e:/code/opencv/samples/cpp/left02.jpg   -1.0
e:/code/opencv/samples/cpp/right02.jpg  1.0
"""
edit flag offensive delete link more

Comments

Thanks, really helpfull. Still, do you know how to manage the conversion of keypoint from cpp to python? I would like to exploit also GPU SIFT by using python, and I need the same conversion. What technology is used for generating python opencv wrapper?

Fe++ gravatar imageFe++ ( 2014-10-01 08:19:54 -0600 )edit

did you mean this ?

berak gravatar imageberak ( 2014-10-01 08:24:22 -0600 )edit

Yes, I have been working on it but still I cannot figure out few things. During compilation time some other c++ code is produced and contains certain functione, such as pyopencv_from and pyopencv_to for KeyPoint. I have managed to transform vector of KeyPoint from C++ to Python by using pyopencv_from generated in release/modules/python/pyopencv_generated_types.h. However, the KeyPoint object that I have wrapped in Python do not have any of its correct attribute. I have found out also where getter and setter method are implemented. However, it is like I am missing the declaration of the PyObject attributes, and I do not have a clue on how and where this is done in OpenCV wrapping process.

Fe++ gravatar imageFe++ ( 2014-10-01 08:58:08 -0600 )edit

the objects and wrapper functions are generated by gen2.py in the same folder (during the cmake process)

berak gravatar imageberak ( 2014-10-01 09:37:20 -0600 )edit

Thanks, I was looking through there since a while. I will try to figure out what I need for transforming a cv::KeyPoint to a cv2.KeyPoint, attributes included.

Fe++ gravatar imageFe++ ( 2014-10-01 10:07:08 -0600 )edit

@berak help on those objects shows nothing.

bad_keypoints gravatar imagebad_keypoints ( 2014-10-15 08:59:38 -0600 )edit

@bad_keypoints help on what ?

berak gravatar imageberak ( 2014-10-15 09:05:49 -0600 )edit

@berak help on bow_train and bow_extract objects.

bad_keypoints gravatar imagebad_keypoints ( 2014-10-15 09:17:45 -0600 )edit

@berak

Thanks for wrapping BOW in python.

I tried using the above code and the below line

svm.train(np.array(traindata), np.array(trainlabels))

Throws this error

   error: (-5) train data must be floating-point matrix in function cvCheckTrainData

here is what my train data (samples) look like (Apparently after doing some googling I did traindata = np.float32(traindata) and same for trainlabels)

>>> np.array(traindata)
array([[[ 0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.]],

       [[ 0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.]]], dtype=float32)

here is what my train labels (responses) look like

>>> np.array(trainlabels)
array([ 1., -1.], dtype=float32)

Am i missing something, please point out what am I doing wrong.

Prithivi gravatar imagePrithivi ( 2015-01-04 08:08:12 -0600 )edit

hmm, looks like there's one array too much around it. also your labels must be integer (else the svm thinks, you want a regression). i think, it should look like this:

array([[ 0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.]], dtype=float32)

(unfortunately , i can't test anything here, no more working 2.4 branch around, atm.)

berak gravatar imageberak ( 2015-01-04 08:31:21 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2014-09-30 08:54:42 -0600

Seen: 2,271 times

Last updated: Sep 30 '14