Reputation: 344
I got an issue with: cv::FlannBasedMatcher More precisely with the knnMatch method. My program take as input and IplImage* and detect a face then it cut the faces and compare the face founded with an image stored on my computer. If i got more than 10 good match it writes on standard output Matched.
The images loaded aren't grayscale. Is that important?
My problem is that it works but for a random amount of time which vary from 1 minute to 3 minutes more or less.
The error messages always appears on the knnMatch methods. Here they are (Note that there is only one of them each time):
OpenCV Error: Assertion failed ((globalDescIdx>=0) && (globalDescIdx < size())) in getLocalIdx, file /opt/local/var/macports/build/_opt_mports_dports_graphics_opencv/opencv/work/opencv- 2.4.9/modules/features2d/src/matchers.cpp, line 163
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /opt/local/var/macports/build/_opt_mports_dports_graphics_opencv/opencv/work/opencv-2.4.9/modules/features2d/src/matchers.cpp:163: error: (-215) (globalDescIdx>=0) && (globalDescIdx < size()) in function getLocalIdx
I don't get why this exception is thrown...
Here is my code:
int DroneCV::matchFaces()
{
std::vector<cv::KeyPoint> keypointsO;
std::vector<cv::KeyPoint> keypointsS;
cv::Mat descriptors_object, descriptors_scene;
cv::Mat foundFaces(this->_faceCut);
cv::FlannBasedMatcher matcher;
std::vector<std::vector<cv::DMatch>> matches;
std::vector<cv::DMatch> good_matches;
cv::SurfDescriptorExtractor extractor;
cv::SurfFeatureDetector surf(this->_minHessian);
surf.detect(foundFaces,keypointsS);
surf.detect(this->_faceToRecognize,keypointsO);
if (!this->_faceToRecognize.data || !foundFaces.data)
{
this->log("Fail to init data in DronceCV::matchFaces");
return (0);
}
extractor.compute(foundFaces, keypointsS, descriptors_scene);
extractor.compute(this->_faceToRecognize, keypointsO, descriptors_object);
if(descriptors_scene.empty())//descriptors_scene.type()!=CV_32F)
{
this->log("Descriptor got wrong type");
descriptors_scene.convertTo(descriptors_scene, CV_32F);
return 0;
}
if(descriptors_object.type()!=CV_32F || descriptors_scene.type()!=CV_32F)
{
this->log("TYPE OBJECT " + std::to_string(descriptors_object.type()));
this->log("TYPE SCENE " + std::to_string(descriptors_scene.type()));
return (0);
}
//Both image must be in grayscale ???
try {
matcher.knnMatch( descriptors_object, descriptors_scene, matches, 5 ); // find the 2 nearest neighbors
} catch (cv::Exception e) {
this->log(e.err);
}
good_matches.reserve(matches.size());
for (size_t i = 0; i < matches.size(); ++i)
{
if (matches[i].size() < 2)
continue;
const cv::DMatch &m1 = matches[i][0];
const cv::DMatch &m2 = matches[i][1];
if(m1.distance <= this->_nndrRatio * m2.distance)
good_matches.push_back(m1);
}
this->log("Number of good matches" + std::to_string(good_matches.size()));
foundFaces.release();
if (good_matches.size() > 8)
return (1);
else
return (0);
}
void DroneCV::analyzeFrame(IplImage *img)
{
if (!img)
{
this->log("Frame empty");
return;
}
if (this->detectFaces(img) == 1)
{
if (this->matchFaces() == 1)
{
this->log("Matched");
cvReleaseImage(&this->_faceCut);
}
}
}
Thanks in advance for your help
Upvotes: 3
Views: 8243
Reputation: 154
I got stuck with this too and it took me almost 3-4 hours to figure this out. When you apply knn match , make sure that number of features in both test and query image is greater than or equal to number of nearest neighbors in knn match.
say for example, we have this code:
Mat img1,img2,desc1,desc2;
vector<KeyPoint> kpt1,kpt2;
FAST(img1,kpt1,30,true) ;
FAST(img2,kpt1,30,true) ;
SurfDescriptorExtractor sfdesc1,sfdesc2;
sfdesc1.compute(img1,kpt1,desc1);
sfdesc2.compute(img2,kpt2,desc2);
FlannBasedMatcher matcher;
vector< vector<DMatch> > matches1,matches2;
matcher.knnMatch(desc1,desc2,matches1,2);
this code will return exception as in the post, just modify the code as show below:
if(kpt1.size()>=2 && kpt2.size()>=2)
matcher.knnMatch(desc1,desc2,matches1,2);
this method worked for me ..!!
Upvotes: 13