基于FlannBasedMatcher的SURF特征提取和关键点匹配

SURF Feature extraction and Keypoint match based on FlannBasedMatcher

本文关键字:关键点 特征提取 FlannBasedMatcher SURF 基于      更新时间:2023-10-16

以下是我的代码,它用于使用SURF提取特征,并使用flannBasedMatcher匹配点。

Mat object = imread("S6E0.bmp",  CV_LOAD_IMAGE_GRAYSCALE);
    if( !object.data )
    {
    // std::cout<< "Error reading object " << std::endl;
    return -2;
    }
    //Detect the keypoints using SURF Detector
    int minHessian = 500;
    SurfFeatureDetector detector( minHessian );
    std::vector<KeyPoint> kp_object;
    detector.detect( object, kp_object );
    //Calculate descriptors (feature vectors)
    SurfDescriptorExtractor extractor;
    Mat des_object;
    extractor.compute( object, kp_object, des_object );
    FlannBasedMatcher matcher;
    char key = 'a';
    //VideoCapture cap(0);
    namedWindow("Good Matches");
    std::vector<Point2f> obj_corners(4);
    //Get the corners from the object
    obj_corners[0] = cvPoint(0,0);
    obj_corners[1] = cvPoint( object.cols, 0 );
    obj_corners[2] = cvPoint( object.cols, object.rows );
    obj_corners[3] = cvPoint( 0, object.rows );
    Mat image = imread("S6E0.bmp", CV_LOAD_IMAGE_GRAYSCALE);
    Mat des_image, img_matches;
    std::vector<KeyPoint> kp_image;
    std::vector<vector<DMatch >> matches;
    std::vector<std::vector<cv::DMatch>> matches1;
    std::vector<std::vector<cv::DMatch>> matches2;
    std::vector<cv::DMatch> matches3;
    std::vector<DMatch > good_matches;
    std::vector<Point2f> obj;
    std::vector<Point2f> scene;
    std::vector<Point2f> scene_corners(4);
    Mat H;
    //cvtColor(frame, image, CV_RGB2GRAY);
    detector.detect( image, kp_image );
    extractor.compute( image, kp_image, des_image );

    matcher.knnMatch(des_object, des_image, matches, 2);

    for(int i = 0; i < min(des_image.rows-1,(int) matches.size()); i++) //THIS LOOP IS SENSITIVE TO SEGFAULTS
    {
        if((matches[i][0].distance < 0.6*(matches[i][1].distance)) && ((int) matches[i].size()<=2 && (int) matches[i].size()>0))
        {
            good_matches.push_back(matches[i][0]);
        }
    }
        //Draw only "good" matches
    drawMatches( object, kp_object, image, kp_image, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
    if (good_matches.size() >= 4)
    {
        printf("Images matching %d , %d", good_matches.size(), kp_object.size());
        //return 1;
        for( int i = 0; i < good_matches.size(); i++ )
        {
            //Get the keypoints from the good matches
            obj.push_back( kp_object[ good_matches[i].queryIdx ].pt );
            scene.push_back( kp_image[ good_matches[i].trainIdx ].pt );
        }
        //H = findHomography( obj, scene, CV_RANSAC );
        //printf("Size : %d", H.size());
        //perspectiveTransform( obj_corners, scene_corners, H);
        //printf("Size : %d --- %d --- %d", H.size(), scene_corners.size()); 
    }else{
        printf("Images matching %d , %d", good_matches.size(), kp_object.size());
    }
        //Show detected matches
    imshow( "Good Matches", img_matches );
    waitKey(0);
    return 0;

在这段代码中,我想知道通过这种方法到底发生了什么

matcher.knnMatch(des_object, des_image, matches, 2);

据我所知,我传递了匹配图像的两个描述符,并且匹配向量填充了 2 个最近邻。我想知道该方法中到底发生了什么,匹配方法是如何填充的,以及填充了哪些点。

在此代码段中

for(int i = 0; i < min(des_image.rows-1,(int) matches.size()); i++) //THIS LOOP IS SENSITIVE TO SEGFAULTS
    {
        if((matches[i][0].distance < 0.6*(matches[i][1].distance)) && ((int) matches[i].size()<=2 && (int) matches[i].size()>0))
        {
            good_matches.push_back(matches[i][0]);
        }
    }

IM 使用最近的邻距离比 (NNDR) 作为 0.6,我想知道good_matches是如何发现的以及 NNDR 值变化将如何影响。

如果我能解决这段代码,那将是一个很大的帮助。谢谢。

FlannBasedMatcher基于Muja等人撰写的论文;你可以在那里找到确切的算法以及他们是如何做到的。

关于good_matches,您刚刚在代码片段本身中看到它是基于标准(即nndr)的结果的最佳匹配项的集合。它基本上是一个阈值,用于决定在完全放弃匹配之前允许比赛的距离。阈值越高,考虑的点越多,正匹配的数量就越多(它们是否为真阳性将取决于您的数据集和设置 nndr 级别的方式)。

希望这有帮助。