Why does cv::DescriptorExtractor::compute return empty descriptors for a std::vector<cv::Mat>?
First, I already asked this question on Stackoverflow but I did not find a solution so far or it might be a bug. Therefor I repeat my question here: The problem is the behaviour of feature extractors in openCV if one wants to extract descriptors of several images at the same time. The cv::DescriptorExtractor offers two interfaces for that:
void DescriptorExtractor::compute(const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors) const
void DescriptorExtractor::compute(const vector<Mat>& images, vector<vector<KeyPoint>>& keypoints, vector<Mat>& descriptors) const
I am talking about the second signature which allows to pass a sequence of images. I tested the behaviour with the following minimal example:
#include"opencv2\opencv.hpp"
#include "opencv2\xfeatures2d\nonfree.hpp"
int main(){
//Read image
cv::Mat img = cv::imread("./sample.png");
//Create vector of images
std::vector<cv::Mat> imageSequence(10, img);
//Create SIFT detector and extractor
cv::FeatureDetector* detector = new cv::xfeatures2d::SiftFeatureDetector();
cv::DescriptorExtractor* extractor = new cv::xfeatures2d::SiftDescriptorExtractor();
//Keypoints
std::vector<std::vector<cv::KeyPoint>> keypoints;
//Compute keypoints
detector->detect(imageSequence, keypoints);
//This vector should contain all descriptors
std::vector<cv::Mat> allDescriptors;
//Version 1: Using a for loop and the single image signature of DescriptorExtractor::compute works.
for (int i = 0; i < imageSequence.size(); ++i){
cv::Mat descriptors;
//This compute(...) works
extractor->compute(imageSequence.at(i), keypoints.at(i), descriptors);
allDescriptors.push_back(descriptors);
}
allDescriptors.clear();
//Version 2: Using the interface for the computation of descriptors for std::vector<cv::Mat> fails
extractor->compute(imageSequence, keypoints, allDescriptors);
return 0;
}
While Version 1 in the example above returns the descriptors for all images correctly, the Version 2 does not - the variable allDescriptors is empty. However, when I step into the compute function I can observe that it calls the compute function with the single image signature in a for loop but the original variable allDescriptors is unaffected. I am working with the latest 3.0 version of opencv from the git repository. It seems that the computed descriptors are computed but not stored in allDescriptors and the result is lost after return.
Be careful, you do not delete the pointers... Better use cv::Ptr<>;
this looks like a bug. std::vector<Mat> descCollection gets destroyed after leaving DescriptorExtractor::compute( InputArrayOfArrays _imageCollection,...)
@berak: Thanks for testing and confirming the behaviour. @thdrksdfthmn: Thanks for pointing out. In my project I use QSharedPoitners but I changed to simple pointers for the minimal working example and forgot to add the delete.