【问题标题】:OpenCV filtering ORB matchesOpenCV 过滤 ORB 匹配
【发布时间】:2014-07-04 07:57:36
【问题描述】:

我正在使用 ORB 特征检测器来查找使用此代码的两个图像之间的匹配项:

    FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
    DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);;
    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);

    // First photo
    Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGB2GRAY);
    Mat descriptors1 = new Mat();
    MatOfKeyPoint keypoints1 = new MatOfKeyPoint();

    detector.detect(img1, keypoints1);
    descriptor.compute(img1, keypoints1, descriptors1);

    // Second photo
    Imgproc.cvtColor(img2, img2, Imgproc.COLOR_RGB2GRAY);
    Mat descriptors2 = new Mat();
    MatOfKeyPoint keypoints2 = new MatOfKeyPoint();

    detector.detect(img2, keypoints2);
    descriptor.compute(img2, keypoints2, descriptors2);

    // Matching

    MatOfDMatch matches = new MatOfDMatch();
    MatOfDMatch filteredMatches = new MatOfDMatch();
    matcher.match(descriptors1, descriptors2, matches);

    // Linking
    Scalar RED = new Scalar(255,0,0);
    Scalar GREEN = new Scalar(0,255,0);

    List<DMatch> matchesList = matches.toList();
    Double max_dist = 0.0;
    Double min_dist = 100.0;

    for(int i = 0;i < matchesList.size(); i++){
        Double dist = (double) matchesList.get(i).distance;
        if (dist < min_dist)
            min_dist = dist;
        if ( dist > max_dist)
            max_dist = dist;
    }



    LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
    for(int i = 0;i < matchesList.size(); i++){
        if (matchesList.get(i).distance <= (1.5 * min_dist))
            good_matches.addLast(matchesList.get(i));
    }



    // Printing
    MatOfDMatch goodMatches = new MatOfDMatch();
    goodMatches.fromList(good_matches);

    System.out.println(matches.size() + " " + goodMatches.size());

    Mat outputImg = new Mat();
    MatOfByte drawnMatches = new MatOfByte();
    Features2d.drawMatches(img1, keypoints1, img2, keypoints2, goodMatches, outputImg, GREEN, RED, drawnMatches, Features2d.NOT_DRAW_SINGLE_POINTS);

    Highgui.imwrite("matches.png", outputImg);

我的问题是我找不到过滤匹配项的方法,以便它们仅在照片中具有相似位置时才匹配。我总是会为一个关键点获得多个匹配项,即使它们在位置上非常遥远。

有没有办法更好地过滤它们?

【问题讨论】:

    标签: java opencv feature-detection orb


    【解决方案1】:

    为了获得更好的匹配结果,您应该按照给定的顺序包含这些过滤方法。

    1. 在两个方向上执行匹配,即针对第一张图像中的每个点 在第二张图片中找到最佳匹配,反之亦然。

    2. 执行比率测试(欧几里得距离的比率测试) 匹配以消除模棱两可的匹配。

    3. 执行 RANSAC 测试:这是一种模型拟合算法,可找到适合模型的最佳数据并去除异常值。
    4. 执行单应性:它是一种图像投影算法。

    您可以在计算机视觉应用程序编程食谱的第 9 章中获得上述方法的所有详细信息。它还具有用于实现这些过滤技术的示例代码。这很容易理解。 (注:本书中的代码是C++,但是一旦你理解了,它也可以很容易地用JAVA实现)

    【讨论】:

      【解决方案2】:

      读完 Rober Langaniere 的书。我才知道有办法。它是删除与更远距离的匹配。在java中是这样的

      Collections.sort(bestMatches,new Comparator<DMatch>() {
              @Override
              public int compare(DMatch o1, DMatch o2) {
                  if(o1.distance<o2.distance)
                      return -1;
                  if(o1.distance>o2.distance)
                      return 1;
                  return 0;
              }
          });
          if(bestMatches.size()>3){
              bestMatches = bestMatches.subList(0,3);
          }
      

      【讨论】:

      • 嗨,感谢您的回答,我也使用这种方式,从 .match(..,..,..) 方法获取原始匹配后,我将它们升序排序并选择前 10、30 或任何适合我的东西。我的问题是,从 .match(..,..,...) 方法返回的匹配项是否按升序排序可以代替阈值处理?因为正如我在许多示例中看​​到的那样,当使用阈值时,它似乎是获得最佳匹配的另一种方式,并且使用您发布的排序算法可能是替代品..请告知。
      • 我认为它更适合添加为阈值的附加组件,即从好的匹配中过滤掉最佳匹配。
      • 但是由于我的距离是按升序排列的,这意味着前 10 或 15 个将是其他距离中较小的距离,这意味着我选择了好的..请告知
      • 在他的书中,他没有使用阈值。但是对于细节,我还必须了解更多,因为我自己仍然不太了解该解决方案的“工作原理”部分。当我知道的更好时,我想成为你的帮助。
      【解决方案3】:

      通过取两个描述符之间的最短汉明距离来完成匹配。因此,您将始终得到检测到的特征之间的匹配。

      您应该修改 ORB 检测器的阈值。这样,您将减少从背景(即噪声)中检测到特征的可能性,因此您检测到的大部分特征将来自感兴趣的主题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-05
        • 1970-01-01
        • 2012-07-05
        • 2012-12-28
        • 2012-03-21
        相关资源
        最近更新 更多