美文网首页程序员码农的世界
SURF匹配点单应性提纯

SURF匹配点单应性提纯

作者: 丁俊杰_ | 来源:发表于2018-10-01 13:12 被阅读4次

    1、SURF简介

      Speeded Up Robust Features(SURF,加速稳健特征),是一种稳健的局部特征点检测和描述算法。最初由Herbert Bay发表在2006年的欧洲计算机视觉国际会议(Europen Conference on Computer Vision,ECCV)上,并在2008年正式发表在Computer Vision and Image Understanding期刊上。
      Surf是对David Lowe在1999年提出的Sift算法的改进,提升了算法的执行效率,为算法在实时计算机视觉系统中应用提供了可能。与Sift算法一样,Surf算法的基本路程可以分为三大部分:局部特征点的提取、特征点的描述、特征点的匹配。

    2、SURF匹配代码

    // 读入你所要匹配的图片
    Mat image1 = imread("D:/test2-1.jpg", 0);
    Mat image2 = imread("D:/test2-2.jpg", 0);
    if (!image1.data || !image2.data)
        return 0;
    
    // 声明两个vector变量存放两张图的关键点
    vector<KeyPoint> keypoints1;
    vector<KeyPoint> keypoints2;
    
    // 声明一个SURF特征检测器
    Ptr<SurfFeatureDetector> surf = SurfFeatureDetector::create(3000);
    
    // 检测 SURF 特征关键点
    surf->detect(image1, keypoints1);
    surf->detect(image2, keypoints2);
    
    if (keypoints1.size() == 0 || keypoints2.size() == 0) {
        return -1;
    } else {
        cout << "Number of SURF points (1): " << keypoints1.size() << endl;
        cout << "Number of SURF points (2): " << keypoints2.size() << endl;
    }
    
    // 声明一个SURF特征点描述子抽取器
    Ptr<SURF> surfDesc = SURF::create();
    
    // 抽取特征点描述子(以向量矩阵形式存入Mat中,用于匹配两特征点是否相似)
    Mat descriptors1, descriptors2;
    surfDesc->compute(image1, keypoints1, descriptors1);
    surfDesc->compute(image2, keypoints2, descriptors2);
    
    // 声明一个匹配器 
    Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce");
    
    // 匹配两图描述子(也即看特征向量像不像)
    vector<cv::DMatch> matches;
    matcher->match(descriptors1, descriptors2, matches);
    
    // 采用RANSAC计算单应矩阵,然后通过单应矩阵提纯得到好的特征点 
    vector<Point2f> object;
    vector<Point2f> scene;
    for (size_t i = 0; i < matches.size(); i++)
    {
        //从好的匹配中获取关键点: 匹配关系是两组关键点间具有的一一对应关系,可以根据此匹配关系获得关键点的索引  
        //这里的goodMatches[i].queryIdx和goodMatches[i].trainIdx是匹配中一对关键点的索引
        object.push_back(keypoints1[matches[i].queryIdx].pt);
        scene.push_back(keypoints2[matches[i].trainIdx].pt);
    }
    
    Mat H;
    float reprojectionThreshold = 3;
    vector<DMatch> inliers;
    vector<unsigned char> inliersMask(object.size());
    H = findHomography(object, scene, CV_RANSAC, reprojectionThreshold, inliersMask);
    for (size_t i = 0; i < inliersMask.size(); i++)
    {
        if (inliersMask[i])
            inliers.push_back(matches[i]);
    }
    matches.swap(inliers);
    

    其中,findHomography()我们单独拿出来解析,这个函数的参数中:

    • object和scene是好点在两张图中分别的坐标集合,且他们是一一对应的,其中既有正确的匹配,也有错误的匹配,正确的称为内点,错误的称为外点,RANSAC方法就是从这些包含错误匹配的数据中,分离出正确的匹配,并且求得单应矩阵(H就是我们要求的单应矩阵)。
    • reprojThreshold为阈值,当某一个匹配小于阈值时,则被认为是一个内点。
    • inliersMask即为掩膜,它的长度和object、scene一样长,当一个object和scene中的点为内点时,inliersMask的相应位置标记为1,反之为0,说白了,通过inliersMask我们最终可以知道序列中哪些是内点,哪些是外点。

    匹配效果示例:


    目标检测示例图

    后期我会将完整代码上传github,欢迎关注,github地址:https://github.com/JunJieDing666

    相关文章

      网友评论

        本文标题:SURF匹配点单应性提纯

        本文链接:https://www.haomeiwen.com/subject/umuznftx.html