特征点提取与匹配

特征点提取与匹配

转载自 SLAM入门之视觉里程计(1):特征点的匹配

特征点概述

  • 如何高效且准确的匹配出两个不同视角的图像中的同一个物体,是许多计算机视觉应用中的第一步。虽然图像在计算机中是以灰度矩阵的形式存在的,但是利用图像的灰度并不能准确的找出两幅图像中的同一个物体。这是由于灰度受光照的影响,并且当图像视角变化后,同一个物体的灰度值也会跟着变化。所以,就需要找出一种能够在相机进行移动和旋转(视角发生变化),仍然能够保持不变的特征,利用这些不变的特征来找出不同视角的图像中的同一个物体。

  • 为了能够更好的进行图像匹配,需要在图像中选择具有代表性的区域,例如:图像中的角点、边缘和一些区块,但在图像识别出角点是最容易,也就是说角点的辨识度是最高的。所以,在很多的计算机视觉处理中,都是提取交掉作为特征,对图像进行匹配,例如SFM,视觉SLAM等。

  • 例如:相机从远处得到的是角点,但是在近处就可能不是角点;或者,当相机旋转后,角点就发生了变化。为此,计算机视觉的研究者们设计了许多更为稳定的的特征点,这些特征点不会随着相机的移动,旋转或者光照的变化而变化。例如:SIFT,SURF,ORB等

  • 一个图像的特征点由两部分构成:关键点(Keypoint)和描述子(Descriptor)。

     关键点指的是该特征点在图像中的位置,有些还具有方向、尺度信息;描述子通常是一个向量,按照人为的设计的方式,描述关键点周围像素的信息。通常描述子是按照外观相似的特征应该有相似的描述子设计的。因此,在匹配的时候,只要两个特征点的描述子在向量空间的距离相近,就可以认为它们是同一个特征点。

  • 特征点的匹配通常需要以下三个步骤

    • 提取图像中的关键点,这部分是查找图像中具有某些特征(不同的算法有不同的)的像素
    • 根据得到的关键点位置,计算特征点的描述子
    • 根据特征点的描述子,进行匹配

特征点描述子

  • 一个好的描述子是准确匹配的基础
  • 从图像中提取到特征的关键点信息,通常只是其在图像的位置信息(有可能包含尺度和方向信息),仅仅利用这些信息无法很好的进行特征点的匹配 ,所以就需要更详细的信息,将特征区分开来,这就是特征描述子
  • 特征的描述子通常是一个精心设计的向量,描述了关键点及其周围像素的信息。
  • 为了能够更好的匹配,一个好的描述子通常要具有以下特性:
    • 不变性 指特征不会随着图像的放大缩小旋转而改变。
    • 鲁棒性 对噪声、光照或者其他一些小的形变不敏感
    • 可区分性 每一个特征描述子都是独特的,具有排他性,尽可能减少彼此间的相似性。
  • 特征点的不变性主要体现在两个方面:
    • 尺度不变性
    • 旋转不变性

常用的特征点算法

  • 图像的特征点包含两个部分
    • 特征点的提取,在图像检测到特征点的位置
    • 特征点的描述,也就是描述子。

 SIFT

SURF

FAST

OpenCV3中的特征图提取与匹配



int main() {

    Mat img1 = imread("F:\\test\\1.jpg");
    Mat img2 = imread("F:\\test\\2.jpg");

    // 1.初始化
    std::cout << "init" << std::endl;
    vector<KeyPoint> keypoints1, keypoint2;
    Mat descriptors1, descriptors2;

    Ptr<ORB> orb = ORB::create();

    // 2.提取特征点
    std::cout << "detect" << std::endl;
    orb->detect(img1, keypoints1);
    orb->detect(img2, keypoint2);

    // 3.计算特征描述符
    std::cout << "compute" << std::endl;
    orb->compute(img1, keypoints1, descriptors1);
    orb->compute(img2, keypoint2, descriptors2);

    // 4.对两幅图像的BRIEF描述符进行匹配,使用BFMatch,Hanming距离作为参考.
    std::cout << "match" << std::endl;
    vector<DMatch> matches;
    BFMatcher bfMatcher(NORM_HAMMING);
    bfMatcher.match(descriptors1, descriptors2, matches);

    //imshow("output", matches);


    std::cout << "draw matches" << std::endl;
    Mat image_matches;
    drawMatches(img1, keypoints1, img2, keypoint2, matches,
        image_matches, Scalar(0, 255, 0), Scalar::all(-1), vector<char>(), 0);

    imshow("matches", image_matches);

    waitKey(0);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qjh5606/article/details/82558854
今日推荐