SURF匹配点单应性提纯

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值