使用OpenCV进行对象检测功能与阈值/相似度得分匹配 - Java / C ++ [英] Object detection with OpenCV Feature Matching with a threshold/similarity score - Java/C++

查看:161
本文介绍了使用OpenCV进行对象检测功能与阈值/相似度得分匹配 - Java / C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个小程序来检测大图像中的对象(小图像),我正在使用OpenCV java。
由于我必须考虑旋转和缩放,我使用了FeatureDetector.BRISK和DescriptorExtractor.BRISK。

I am in the process of creating a small program which detects objects(small image) in the large image and I am using OpenCV java. As I have to consider rotation and scaling I have used FeatureDetector.BRISK and DescriptorExtractor.BRISK.

以下方法用于过滤匹配结果以仅获得最佳匹配。

Following approach is used to filter the match results to get the best matches only.

我有两个问题


  1. 有没有办法在我使用的循环中找到下面的min_dist和max_dist?

  2. 最重要的问题 - 现在问题是我需要使用这些匹配来确定是否找到了对象(模板)。如果有人帮助我,那会很棒。

提前致谢。

    FeatureDetector  fd = FeatureDetector.create(FeatureDetector.BRISK); 
    final MatOfKeyPoint keyPointsLarge = new MatOfKeyPoint();
    final MatOfKeyPoint keyPointsSmall = new MatOfKeyPoint();

    fd.detect(largeImage, keyPointsLarge);
    fd.detect(smallImage, keyPointsSmall);

    System.out.println("keyPoints.size() : "+keyPointsLarge.size());
    System.out.println("keyPoints2.size() : "+keyPointsSmall.size());

    Mat descriptorsLarge = new Mat();
    Mat descriptorsSmall = new Mat();

    DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRISK);
    extractor.compute(largeImage, keyPointsLarge, descriptorsLarge);
    extractor.compute(smallImage, keyPointsSmall, descriptorsSmall);

    System.out.println("descriptorsA.size() : "+descriptorsLarge.size());
    System.out.println("descriptorsB.size() : "+descriptorsSmall.size());

    MatOfDMatch matches = new MatOfDMatch();

    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT);
    matcher.match(descriptorsLarge, descriptorsSmall, matches);

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

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

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

    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;
        System.out.println(String.format(i + " match distance best : %s", dist));
        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());






编辑



编辑我的代码如下。我知道仍然不是最好的方法来判断对象是否基于最佳匹配而找到。
所以请分享您的观点。


Edit

Edited my code as follows.I know still it's not the best way to come to a conclusion whether the object found or not based on no of best matches. So please share your views.

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

    if(min_dist > 50 )
    {
        System.out.println("No match found");
        System.out.println("Just return ");
        return false;
    }

    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");
        return true;
    }
    else
    {
        return false;
    }


推荐答案

您的编辑代码工作正常对我来说,并且工作得很好,

Your Edited code is working fine for me, and working perfectly,

以下是我在您的代码中为检测大图像中的对象(小图像)所做的更改:

Following are changes that i have done in your code for detecting objects(small image) in the large image :


  1. 使用SURF方法进行特征检测和特征提取。(SURF在Android和更早版本的opencv 4.1.1中可用,之后已经过从那里删除,所以在这里我使用opencv 4.1.1)

  1. using SURF method for feature detection as well as feature extraction.(SURF is available in opencv 4.1.1 for Android and earlier, after that it have been removed from that, so here i have used opencv 4.1.1)

在下一行中更改匹配与否的图像阈值从1到4

change threshold of image matched or not from 1 to 4, in following line

if(matchesFiltered.rows()> = 1)

if(matchesFiltered.rows() >= 1)

to

if(matchesFiltered.rows() >= 4)

只有这些变化对我来说非常有效,请确保对象/小图像具有丰富的纹理(至少应该具有可匹配的关键点)

only this changes have worked perfectly for me, make sure that object/small image have rich texture(atleast should have keypoints that can be matched)

这篇关于使用OpenCV进行对象检测功能与阈值/相似度得分匹配 - Java / C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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