0
votes

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?

2
What is train_imgs? The code works correcly for me if train_imgs is a vector<Mat>. Btw, your answer below is quite wrong.Miki
THX man. When train_imgs is an obj of Mat, it fails. After I change it into vector<Mat>, it works. Could you pls tell me what's the difference between vector< Mat > and OutputArrayOfArrays?Qi W.

2 Answers

2
votes

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.

0
votes

This code could work I guess:

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

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