Search code examples
opencvc++11opencv3.0sift

OpenCV3, SIFT compute with vector<vector<KeyPoint>>


According to the document, SIFT object could use the function below to compute descriptors for multiple images:

virtual void compute (InputArrayOfArrays images, std::vector< std::vector< KeyPoint > > &keypoints, OutputArrayOfArrays descriptors)

I'm trying to compute the SIFT descriptors for multiple images with the code below:

Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
vector<vector<KeyPoint>> train_keypoints;
f2d->detect(train_imgs, train_keypoints);

vector<Mat> train_descriptors;
f2d->compute(train_imgs, train_keypoints, train_descriptors);

It could be compiled under Mac OS 10.10.5 with opencv3, while it might terminate during execution with error:

libc++abi.dylib: terminating with uncaught exception of type std::length_error: vector

Or I could change the type of train_descriptors into Mat (instead of vector< Mat >), it'll still fail during execution with another error:

OpenCV Error: Assertion failed (_descriptors.kind() == _InputArray::STD_VECTOR_MAT) in compute, file /tmp/opencv320151228-32931-2p5ggk/opencv-3.1.0/modules/features2d/src/feature2d.cpp, line 126 libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /tmp/opencv320151228-32931-2p5ggk/opencv-3.1.0/modules/features2d/src/feature2d.cpp:126: error: (-215) _descriptors.kind() == _InputArray::STD_VECTOR_MAT in function compute

What type of train_descriptors should I use to make this code compile and run correctly?


Could anyone told me what's the difference between vector< Mat > and OutputArrayOfArrays?


Solution

  • Your code

    Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
    vector<vector<KeyPoint>> train_keypoints;
    f2d->detect(train_imgs, train_keypoints);
    
    vector<Mat> train_descriptors;
    f2d->compute(train_imgs, train_keypoints, train_descriptors);
    

    works well if train_imgs is a vector<Mat>.


    You don't need to create a vector of 50000 elements, simply use vector<Mat> train_descriptors;.


    OutputArrayOfArrays, like InputArray, OutputArray and the like, are an abstraction layer that OpenCV uses to allow to pass to a function both cv::Mat and std::vector. You should never use these classes explicitly. From OpenCV doc:

    The class is designed solely for passing parameters. That is, normally you should not declare class members, local and global variables of this type.

    Also, note that OutputArrayOfArrays is just a typedef of OutputArray.