9

このコードを使用して、ORB 特徴検出器を使用して 2 つの画像間の一致を見つけています。

    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);

私の問題は、一致をフィルター処理して、写真内の位置が似ている場合にのみ一致するようにする方法が見つからないことです。位置的に非常に離れていても、1 つのキーポイントに対して常に複数の一致が得られます。

それらをより適切にフィルタリングする方法はありますか?

4

3 に答える 3

9

より良い一致結果を得るには、これらのフィルタリング方法を指定された順序で含める必要があります。

  1. 2 つの方向でマッチングを実行します。つまり、最初の画像の各ポイントに対して、2 番目の画像で最適な一致を見つけます。逆も同様です。

  2. あいまいな一致を排除するために、一致間で比率検定 (ユークリッド距離の比率検定) を実行します。

  3. RANSAC テストを実行します。これは、モデルに適合する最良のデータを見つけて外れ値を取り除くモデル適合アルゴリズムです。
  4. ホモグラフィを実行します。これは画像投影アルゴリズムです。

上記のメソッドの詳細はすべて、コンピューター ビジョン アプリケーション プログラミング クックブックの第 9 章で確認できます。また、これらのフィルタリング手法を実装するためのサンプル コードも含まれています。とても分かりやすいです。(注: この本のコードは C++ で書かれていますが、理解すれば Java でも簡単に実装できます)

于 2014-07-04T08:48:45.723 に答える
1

ローバー・ランガニエールの本を読んだ後。方法があることを知りました。それ以上の距離で一致を削除することです。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 に答える