Ask Your Question
0

FlannBasedMatcher correct declaration

asked 2014-10-28 08:41:21 -0600

Doombot gravatar image

updated 2014-10-28 09:18:20 -0600

Is there something fundamentally wrong with this code (see EDIT)

// 2 images are previously loaded in objectImg and sceneImg //

cv::Ptr<cv::BRISK> ptrBrisk = cv::BRISK::create();
ptrBrisk->detect(objectImg, objectKeypoints);
ptrBrisk->compute(objectImg,objectKeypoints,objectDescriptors);

ptrBrisk->detect(sceneImg, sceneKeypoints);
ptrBrisk->compute(sceneImg,sceneKeypoints,sceneDescriptors);

int k =2;

FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( objectDescriptors, sceneDescriptors, matches );

On execution, the last line (matcher.match) fails: " Unsupported format or combination of formats (type = 0) in cv::flann:buildIndex_ "

I tried to use:

std::vector< DMatch > matches;
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("FlannBased");
matcher->match( objectDescriptors, sceneDescriptors, matches );

But it fails at execution, same error message.

EDIT : I added some code and it now works, but (look after code):

cv::Ptr<cv::BRISK> ptrBrisk = cv::BRISK::create();
ptrBrisk->detect(objectImg, objectKeypoints);
ptrBrisk->compute(objectImg,objectKeypoints,objectDescriptors);

ptrBrisk->detect(sceneImg, sceneKeypoints);
ptrBrisk->compute(sceneImg,sceneKeypoints,sceneDescriptors);

if(objectDescriptors.type() != CV_32F)
{
    cv::Mat temp;
    objectDescriptors.convertTo(temp, CV_32F);
    objectDescriptors = temp;
}

if(sceneDescriptors.type() != CV_32F)
{
    cv::Mat temp;
    sceneDescriptors.convertTo(temp, CV_32F);
    sceneDescriptors = temp;
}

int k =2;

std::vector< DMatch > matches;
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("FlannBased");
matcher->match( objectDescriptors, sceneDescriptors, matches );

Isn't using a float version of the descriptors defeating the purpose of using binary descriptors, aka speed? I will try test it with a BFMatcher and keep it updated here!

edit retag flag offensive close merge delete

Comments

1

I´m not exactly sure about this, but I believe that the descriptors from BRISK are integer which should be compared by Hamming Distance, when FlannMatcher expects floating point descriptors which are compared with L1/L2 distance.

R.Saracchini gravatar imageR.Saracchini ( 2014-10-28 09:12:52 -0600 )edit

Hmm you got it right! That's what I was doing when you were commenting. I will try to make it work with a BFMatcher with Hamming

Doombot gravatar imageDoombot ( 2014-10-28 09:20:16 -0600 )edit
1

Maybe the attribution that you doing within the "ifs" is not really copying the data from the temporary matrix which you created, just giving the reference, and the object points to unallocated memory after the "temp" variable is released. Note that type = 0 corresponds to unsigned integer , which is the constant equivalent to CV_8U (at least, in my platform) .

And yes, Converting binary descriptors to CV_32F is kind of wasteful, since it discards the potential advantages of the binary representation.

R.Saracchini gravatar imageR.Saracchini ( 2014-10-28 09:30:42 -0600 )edit

1 answer

Sort by » oldest newest most voted
3

answered 2014-10-28 09:34:19 -0600

Doombot gravatar image

updated 2014-10-28 10:37:10 -0600

As R. Saracchini pointed independently, if someone use a FLANN matcher, the descriptors must be in the CV_32F (float) format. For binary descriptors, a hamming matcher should be used, as in the following. Here is a working code for using BRISK in OpenCV 3 (Windows, Visual Studio 2012)

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/opencv.hpp>
#include <vector>    

#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;


int main( int argc, char** argv )
{

    Mat objectImg = imread("PATH_OF OBJECT_CHOOSE YOUR OWN", cv::IMREAD_GRAYSCALE);
    Mat sceneImg = imread("PATH_OF SCENE/QUERY_CHOOSE YOUR OWN", cv::IMREAD_GRAYSCALE);

    if( !objectImg.data || !sceneImg.data )
    {
        printf( " No image data \n " );
        return -1337;
    }

    std::vector<cv::KeyPoint> objectKeypoints;
    std::vector<cv::KeyPoint> sceneKeypoints;
    cv::Mat objectDescriptors;
    cv::Mat sceneDescriptors;

    //////////////////////////////////////
    // Object: keypoint descriptors computing

    cv::Ptr<cv::BRISK> ptrBrisk = cv::BRISK::create();
    ptrBrisk->detect(objectImg, objectKeypoints);
    ptrBrisk->compute(objectImg,objectKeypoints,objectDescriptors);


    //////////////////////////////////////
    // Scene: keypoint descriptors computing
    ptrBrisk->detect(sceneImg, sceneKeypoints);
    ptrBrisk->compute(sceneImg,sceneKeypoints,sceneDescriptors);


    std::vector< DMatch > matches;
    cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
    matcher->match( objectDescriptors, sceneDescriptors, matches );

    double max_dist = 0; double min_dist = 100;

    //-- Quick calculation of max and min distances between keypoints
    for( int i = 0; i < objectDescriptors.rows; i++ )
    { 
        double dist = matches[i].distance;
        if( dist < min_dist ) min_dist = dist;
        if( dist > max_dist ) max_dist = dist;
    }

    std::vector<cv::DMatch> good_matches;

    for( int i = 0; i < objectDescriptors.rows; i++ )
    { 
        if( matches[i].distance <= max(2*min_dist, 0.02) ) {
            good_matches.push_back( matches[i]); 
        }

    }

    Mat allmatchs;
    drawMatches(objectImg,objectKeypoints,sceneImg,sceneKeypoints,good_matches,allmatchs,Scalar::all(-1), Scalar::all(-1),vector<char>(),0);
    imshow( "Matchs",allmatchs);

    waitKey(0);

}
edit flag offensive delete link more

Comments

But it is a Brute Force one , what about if I want to use LSH or HCT?

SuperMan gravatar imageSuperMan ( 2015-12-17 02:09:50 -0600 )edit

Question Tools

Stats

Asked: 2014-10-28 08:41:21 -0600

Seen: 1,656 times

Last updated: Oct 28 '14