9

我正在使用 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);

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

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

4

3 回答 3

9

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

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

  2. 在匹配之间执行比率测试(欧几里德距离的比率测试)以消除不明确的匹配。

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

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

于 2014-07-04T08:48:45.723 回答
1

在阅读了 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);
    }
于 2014-10-04T17:22:43.420 回答
0

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

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

于 2018-06-21T08:42:19.967 回答