Boooil's BLOG.

图像特征匹配开发手记Vol_1

2021/01/22 Share

完整的跑出SIFT图像特征匹配基本流程


北创+毕设项目,工程目标是做出一个基于SIFT的图像特征匹配并识别建筑物的系统,与GPS坐标结合,整个工程都是基于Android Studio平台和OpenCV Java SDK。

参考了OpenCV SDK中的官方手册、教程文档以及网上的文章和博客。


一个简单的相对完整的SIFT的匹配流程,包括一下几步:图片的预处理,特征点检测(detect),特征点提取(extractor),特征点匹配(match)

  • 图片预处理

    图片在进行匹配之前的预处理,为此进行的是图片转为灰度图以及高斯模糊

    为什么要进行灰度化?

    ​ 最直接的原因就是减小计算量。包含色彩的图片,特征量,计算量会成指数倍数增加。比如一个点,灰度的话,就256个维度而已,但是如果算上RGB色彩的话,那就是1600万以上维度。

    1
    Imgproc.cvtColor(test1,test1_Gray,COLOR_BGR2GRAY);//转化为灰度图

    为什么要进行高斯模糊?

    ​ 减少图像噪声以及降低细节层次。

    1
    2
    Size Ksize = new Size(5,5);
    GaussianBlur(test1_Gray,test1_Blurred,Ksize,0);

    高斯核的大小选择了5X5,当然可以选择10X10,测试得到数值越大模糊程度越明显,至于如何选择,应该是一个先验后验的问题。

  • 特征点检测

    1
    2
    3
    FeatureDetector SIFTdter = FeatureDetector.create(FeatureDetector.SIFT);//创建特征监测
    MatOfKeyPoint kp1 = new MatOfKeyPoint();//特征点
    SIFTdter.detect(test1_Blurred,kp1);//检测特征点

    将特征点检测出来,放入KP1矩阵。这里特征点的检测方法有很多,比如常见的SIFT、SURF等等,这里我们选择经典的SIFT。

  • 特征点描述符提取

    1
    2
    DescriptorExtractor descriptorExtractor=DescriptorExtractor.create(DescriptorExtractor.SIFT);//描述子提取
    descriptorExtractor.compute(test1_Blurred,kp1,descriptors1);//计算描述子

    这里也选择SIFT的描述符提取方法,计算描述符。

  • 特征点匹配

    1
    2
    3
    DescriptorMatcher descriptorMatcher=DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);//描述子匹配
    MatOfDMatch matches=new MatOfDMatch();
    descriptorMatcher.match(descriptors1,descriptors2,matches);//进行匹配

    这里的匹配方法选择的是FLANNBASED(最近邻近似匹配),除了这个还有Brute Force匹配等等。


经过以上几步,我们会得到一个MatOfDMatch类型的变量matches,这个就是已经用SIFT匹配好的匹配矩阵。

1
Features2d.drawMatches(im1,key1,im2,key2,matches,out);

我们可以用drawmathches这个函数将两张图片匹配的点进行连线,直观的看出二者的匹配情况。

但是我们此时会发现一个问题,那就是好像匹配的点有点多?两张不相关的图片也有很多的匹配点?这就说明,仅仅依靠SIFT算法,是无法很好的得到我们想要的“图像识别”的效果的,所以我们在此基础上要对SIFT算法进行优化。