FLANN matcher not work properly

asked 2020-10-19 07:51:41 -0600

palladin gravatar image

updated 2020-10-19 08:01:11 -0600

My FLANN-matcher doesn't work properly. It finds incorrect points, even though the source object and scene are of good quality, and objects very simple.

using namespace cv;
using namespace std;

Mat g_Obj1Image;
Mat g_Obj1Descriptors;
std::vector< KeyPoint > g_Obj1Keypoints;


Mat g_Obj2Image;
Mat g_Obj2Descriptors;
std::vector< KeyPoint > g_Obj2Keypoints;

Mat g_Obj3Image;
Mat g_Obj3Descriptors;
std::vector< KeyPoint > g_Obj3Keypoints;

cv::Ptr<xfeatures2d::SURF> detector;
//cv::Ptr<cv::ORB> detector;

void PrepareObjects(const std::string& obj1, const std::string& obj2, const std::string& obj3)
{
    detector = cv::xfeatures2d::SURF::create();
    //detector = cv::ORB::create();
    detector->setExtended(true);

    g_Obj1Image = imread(obj1, IMREAD_GRAYSCALE );
    if (g_Obj1Image.data == nullptr)
    {
        throw std::runtime_error("cannot read image");
    }

    detector->detectAndCompute( g_Obj1Image,  noArray(), g_Obj1Keypoints, g_Obj1Descriptors );


    g_Obj2Image = imread(obj2, IMREAD_GRAYSCALE );
    if (g_Obj2Image.data == NULL)
    {
        throw std::runtime_error("cannot read image");
    }

    detector->detectAndCompute( g_Obj2Image,  noArray(), g_Obj2Keypoints, g_Obj2Descriptors );

    g_Obj3Image = imread(obj3, IMREAD_GRAYSCALE );
    if (g_Obj3Image.data == NULL)
    {
        throw std::runtime_error("cannot read image");
    }

    detector->detectAndCompute( g_Obj3Image,  noArray(), g_Obj3Keypoints, g_Obj3Descriptors );
}

void flann_test(Mat& frame, Mat& img, Mat& descrs, std::vector< KeyPoint >& keypoints)
{
    Mat& obj_image = img;
    Mat& obj_descriptors = descrs;
    std::vector< KeyPoint >& obj_keypoints = keypoints;

    Mat blured;
    GaussianBlur(frame, blured, Size(3, 3), 0);

    Mat sceneImage;
    cvtColor(blured, sceneImage, COLOR_RGB2GRAY);

    std::vector< KeyPoint > sceneKeypoints;
    Mat sceneDescriptors;
    detector->detectAndCompute( sceneImage, noArray(), sceneKeypoints, sceneDescriptors);

    //cv::FlannBasedMatcher matcher(cv::makePtr<cv::flann::LshIndexParams>(20, 10, 2));
    cv::FlannBasedMatcher matcher;
    std::vector<DMatch> matches;
    matcher.match( obj_descriptors, sceneDescriptors, matches);

    double max_dist = 0;
    double min_dist = 100;

    for( int i = 0; i < obj_descriptors.rows; i++ ) {
        double dist = matches[i].distance;
        if( dist < min_dist ) {
            min_dist = dist;
        }
        if( dist > max_dist ) {
            max_dist = dist;
        }
    }

    std::vector< DMatch > good_matches;

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

    if (good_matches.size() > 3)
    {
        try {
            Mat imgMatches;
            drawMatches( obj_image, obj_keypoints, sceneImage, sceneKeypoints,
                         good_matches, imgMatches, Scalar::all( -1 ), Scalar::all( -1 ),
                         std::vector< char >(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

            imshow( "Good Matches & Object detection", imgMatches);


            /*std::vector< Point2f > obj;
            std::vector< Point2f > scene;

            for( size_t i = 0; i < good_matches.size(); i++ ) {
                obj.push_back( obj_keypoints[ good_matches[ i ].queryIdx ].pt );
                scene.push_back( sceneKeypoints[ good_matches[ i ].trainIdx ].pt );
            }

            Mat H = findHomography( obj, scene, RANSAC );

            std::vector< Point2f > objCorners( 4 );
            objCorners[ 0 ] = Point( 0, 0 );
            objCorners[ 1 ] = Point( obj_image.cols, 0 );
            objCorners[ 2 ] = Point( obj_image.cols, obj_image.rows );
            objCorners[ 3 ] = Point( 0, obj_image.rows );

            std::vector< Point2f > sceneCorners( 4 );
            perspectiveTransform( objCorners, sceneCorners, H );

            line( imgMatches, sceneCorners[ 0 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 1 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );
            line( imgMatches, sceneCorners[ 1 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 2 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );
            line( imgMatches, sceneCorners[ 2 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 3 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );
            line( imgMatches, sceneCorners[ 3 ] + Point2f( obj_image.cols, 0 ), sceneCorners[ 0 ] + Point2f( obj_image.cols, 0 ), Scalar( 0, 255, 0 ), 4 );

            imshow( "Good Matches & Object detection", imgMatches);*/
        }  catch (const std::exception& ex)
        {
            std::cout << "EXCEPTION: "<<ex.what() <<std::endl;
        }
    }

}


int main ( int , char ** )
{
    PrepareObjects("/home/zafyrchi/misc/a1.png", "/home/zafyrchi/misc ...
(more)
edit retag flag offensive close merge delete

Comments

and objects very simple

maybe too simple (not enough "texture")

berak gravatar imageberak ( 2020-10-19 08:06:15 -0600 )edit