OpenCV - Java - 使用DescriptorMatcher与2个相反的图像不匹配 [英] OpenCV - Java - No match with 2 opposite images using DescriptorMatcher

查看:719
本文介绍了OpenCV - Java - 使用DescriptorMatcher与2个相反的图像不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用OpenCV的DescriptorMatcher匹配2个相反的图像而没有运气。
图片为: http://i61.tinypic.com/28whu0g.jpg (从左至右)和 http://i61.tinypic.com/x35vte.jpg (从右到左)。

I'm trying to match 2 opposite images using OpenCV's DescriptorMatcher with no luck. The images are: http://i61.tinypic.com/28whu0g.jpg (left to right) and http://i61.tinypic.com/x35vte.jpg (right to left).

我的代码很像我在StackOverflow和网络上看到的很多例子,但我总是得不到匹配。

My code is pretty like alot of examples that I saw in StackOverflow and the web but still I always get no match.

        String firstImageSourcePath = "RTL_IMAGE_PATH";
        String secondImageSourcePath = "LTR_IMAGE_PATH";

        Mat firstImageSrcImgMat = Highgui.imread(firstImageSourcePath);
        Mat secondImageSrcImgMat = Highgui.imread(firstImageSourcePath);

        if (firstImageSrcImgMat.empty() || secondImageSrcImgMat.empty()) {
            System.out.println("Failed to load images");
            return;
        }

        System.out.println("Loaded image at " + firstImageSourcePath + " and " + secondImageSourcePath);

        FeatureDetector featureDetector = FeatureDetector.create(FeatureDetector.BRISK);

        MatOfKeyPoint firstImgMatOfKeyPoints = new MatOfKeyPoint();
        MatOfKeyPoint secondImgMatOfKeyPoints = new MatOfKeyPoint();

        featureDetector.detect(firstImageSrcImgMat, firstImgMatOfKeyPoints);
        featureDetector.detect(secondImageSrcImgMat, secondImgMatOfKeyPoints);

        System.out.println("Detected " + firstImgMatOfKeyPoints.size() + " and " + secondImgMatOfKeyPoints + " blobs in the images");

        List<KeyPoint> firstImgKeyPoints = firstImgMatOfKeyPoints.toList();
        List<KeyPoint> secondImgKeyPoints = secondImgMatOfKeyPoints.toList();

        System.out.println("First Image key points: " + firstImgKeyPoints);
        System.out.println("Second Image key points: " + secondImgKeyPoints);

        Mat firstImgDescriptors = new Mat();
        Mat secondImgDescriptors = new Mat();

        DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRISK); 
        extractor.compute(firstImageSrcImgMat, firstImgMatOfKeyPoints, firstImgDescriptors);
        extractor.compute(secondImageSrcImgMat, secondImgMatOfKeyPoints, secondImgDescriptors);

        System.out.println("descriptorsA.size() : " + firstImgDescriptors.size());
        System.out.println("descriptorsB.size() : " + secondImgDescriptors.size());

        MatOfDMatch matches = new MatOfDMatch();

        DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT); // BRUTEFORCE_HAMMINGLUT
        matcher.match(firstImgDescriptors, secondImgDescriptors, matches);

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

        MatOfDMatch matchesFiltered = new MatOfDMatch();

        List<DMatch> matchesList = matches.toList();
        List<DMatch> bestMatches = new ArrayList<DMatch>();

        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 > 0)
                System.out.println("dist : " + dist);

            if (dist < min_dist && dist != 0) {
                min_dist = dist;
            }

            if (dist > max_dist) {
                max_dist = dist;
            }

        }

        System.out.println("max_dist : " + max_dist);
        System.out.println("min_dist : " + min_dist);

        if (min_dist > 50) {
            System.out.println("No match found, min_dist under minimum value");
            return;
        }

        double threshold = 3 * min_dist;
        double threshold2 = 2 * min_dist;

        if (threshold > 75) {
            threshold = 75;
        } else if (threshold2 >= max_dist) {
            threshold = min_dist * 1.1;
        } else if (threshold >= max_dist) {
            threshold = threshold2 * 1.4;
        }

        System.out.println("Threshold : " + threshold);

        for (int i = 0; i < matchesList.size(); i++) {
            Double dist = (double) matchesList.get(i).distance;

            if (dist < threshold) {
                bestMatches.add(matches.toList().get(i));
                System.out.println(String.format(i + " best match added : %s", dist));
            }
        }

        matchesFiltered.fromList(bestMatches);

        System.out.println("matchesFiltered.size() : " + matchesFiltered.size());

        if (matchesFiltered.rows() >= 1) {
            System.out.println("match found");
        } else {
            System.out.println("match not found");
        }

任何暗示我做错了什么?

any hint what am I doing wrong?

推荐答案

正如@ Iwillnotexist-Idonotexist所述,第一个问题是你申请的门槛。尝试使用不依赖于描述符之间距离的阈值,因为某些描述符比其他描述符更具辨别力。我认为这会给你更好的结果。我建议你使用D. Lowe在SIFT论文中提出的比率测试。
请查看第7.1节: http://cs.ubc .ca / ~lowe / papers / ijcv04.pdf

As @Iwillnotexist-Idonotexist stated the first problem is the threshold you are applying. Try to use a threshold that does not depend on the distance between descriptors that does not perform well since some of the descriptors are much more discriminative than others. I think that will give you better results. I advise you to use the Ratio Test proposed by D. Lowe in SIFT’s paper. Please give a look at section 7.1: http://cs.ubc.ca/~lowe/papers/ijcv04.pdf

第二个问题是您使用BRISK来检测图像中的功能。这个OpenCV实现有bug(你可以在这里查看: http://code.opencv.org/issues/3976 )所以尝试使用另一个FeatureDetector,如FAST,ORB等...(描述符很好,所以你可以继续使用它)

The second problem is that you are using BRISK to detect features in your images. This OpenCV implementation has bugs (you can check here: http://code.opencv.org/issues/3976) so try using another FeatureDetector like FAST, ORB, etc … (descriptor is fine so you can keep using it)

我最终测试你的照片我设法用不同的探测器/描述符得到一些结果:
(没有匹配的关键点 - >黄色)

I ended up testing in your pictures and I managed to get some results with different detectors / descriptors: (keypoints with no match -> yellow)

BRISK探测器和描述符:


  • 左图关键点:74

  • 右图关键点:86

  • 匹配:3(即使检测器损坏我也得到了匹配)

带有BRISK作为描述符的ORB检测器:


  • 左图关键点:499

  • 右图关键点:500

  • 匹配:26

ORB检测器和描述符


  • 左图关键点: 841

  • 右图关键点:907

  • 匹配:43

使用比率测试获得所有结果以去除错误匹配。
我希望这会有所帮助!

All results were obtained using the ratio test to remove false matches. I hope this helps!

编辑:

BruteForceMatcher<Hamming> matcher;
vector< vector<DMatch> > matches;
vector <DMatch> goodMatches;
matcher.knnMatch(imgDescriptors1, imgDescriptors2, matches, 2);
// Ratio Test
for (unsigned int matchIdx = 0; matchIdx < matches.size(); ++matchIdx) 
{
    const float ratio = 0.8; // As in Lowe's paper (can be tuned)
    if (matches[matchIdx][0].distance < ratio * matches[matchIdx][1].distance)
    {
        goodMatches.push_back(matches[matchIdx][0]);
    }
}

这篇关于OpenCV - Java - 使用DescriptorMatcher与2个相反的图像不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆