OpenCV-Java-使用描述符与2个相反的图像不匹配

OpenCV-Java-使用描述符与2个相反的图像不匹配,java,opencv,Java,Opencv,我试图用OpenCV的描述符匹配两个相反的图像,但运气不好。 这些图像是:(从左到右)和(从右到左) 我的代码很像我在StackOverflow和web中看到的许多示例,但我始终没有找到匹配的 String firstImageSourcePath = "RTL_IMAGE_PATH"; String secondImageSourcePath = "LTR_IMAGE_PATH"; Mat firstImageSrcImgMat = Highg

我试图用OpenCV的描述符匹配两个相反的图像,但运气不好。 这些图像是:(从左到右)和(从右到左)

我的代码很像我在StackOverflow和web中看到的许多示例,但我始终没有找到匹配的

        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");
        }
String firstImageSourcePath=“RTL\u IMAGE\u PATH”;
字符串secondImageSourcePath=“LTR\u IMAGE\u PATH”;
Mat firstImageSrcImgMat=Highgui.imread(firstImageSourcePath);
Mat secondImageSrcImgMat=Highgui.imread(firstImageSourcePath);
if(firstImageSrcImgMat.empty()| | secondImageSrcImgMat.empty()){
System.out.println(“加载图像失败”);
返回;
}
System.out.println(“在“+firstImageSourcePath+”和“+secondImageSourcePath”处加载的图像);
FeatureDetector FeatureDetector=FeatureDetector.create(FeatureDetector.BRISK);
MatOfKeyPoint firstImgMatOfKeyPoints=新的MatOfKeyPoint();
MatOfKeyPoint secondImgMatOfKeyPoints=新的MatOfKeyPoint();
特征检测器。检测(firstImageSrcImgMat、FirstImgMatoKeyPoints);
特征检测器。检测(第二个ImageSrcImgMat,第二个ImgMatoKeyPoints);
System.out.println(“在图像中检测到“+FirstImgMatoKeyPoints.size()+”和“+SecondImgMatoKeyPoints+”斑点”);
List firstImgKeyPoints=firstImgMatOfKeyPoints.toList();
List secondImgKeyPoints=secondImgMatOfKeyPoints.toList();
System.out.println(“第一个图像关键点:+firstImgKeyPoints”);
System.out.println(“第二个图像关键点:+secondImgKeyPoints”);
Mat firstImgDescriptors=新Mat();
Mat secondImgDescriptors=新Mat();
DescriptorExtractor提取器=DescriptorExtractor.create(DescriptorExtractor.BRISK);
compute(firstImageSrcImgMat、FirstImgMatoKeyPoints、firstImgDescriptors);
compute(secondImageSrcImgMat、secondImgMatOfKeyPoints、secondImgDescriptors);
System.out.println(“描述符rsa.size():”+firstImgDescriptors.size());
System.out.println(“descriptorsB.size():”+secondImgDescriptors.size());
MatOfDMatch matches=新的MatOfDMatch();
DescriptorMatcher matcher=DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT);//布鲁特福斯·哈明路德
matcher.match(第一个imgdescriptors,第二个imgdescriptors,matches);
System.out.println(“matches.size():”+matches.size());
System.out.println(“匹配项:+匹配项”);
MatOfDMatch matchesFiltered=新的MatOfDMatch();
List matchesList=matches.toList();
List bestMatches=new ArrayList();
双最大距离=0.0;
双最小距离=100.0;
对于(int i=0;i0)
System.out.println(“dist:+dist”);
如果(距离<最小距离和距离!=0){
最小距离=距离;
}
如果(距离>最大距离){
最大距离=距离;
}
}
系统输出打印项次(“最大距离:+最大距离”);
系统输出打印项次(“最小距离:+最小距离”);
如果(最小距离>50){
System.out.println(“未找到匹配项,最小值下的最小距离”);
返回;
}
双阈值=3*最小距离;
双阈值2=2*最小距离;
如果(阈值>75){
阈值=75;
}否则如果(阈值2>=最大距离){
阈值=最小距离*1.1;
}否则如果(阈值>=最大距离){
阈值=阈值2*1.4;
}
System.out.println(“阈值:+阈值”);
对于(int i=0;i=1){
System.out.println(“找到匹配项”);
}否则{
System.out.println(“未找到匹配项”);
}

有任何提示我做错了什么吗?

正如@Iwillnotexist idnotexist所说的,第一个问题是您应用的阈值。尝试使用一个阈值,该阈值不依赖于描述符之间的距离,因为有些描述符比其他描述符更具辨别力,因此性能不佳。我认为这会给你带来更好的结果。我建议您使用D.Lowe在SIFT论文中提出的比率测试。 请参阅第7.1节:

第二个问题是,您正在使用BRISK检测图像中的特征。这个OpenCV实现有bug(您可以在这里检查:),所以请尝试使用另一个FeatureDetector,如FAST、ORB等…(描述符很好,所以您可以继续使用它)

我最终在你的图片中进行了测试,并使用不同的检测器/描述符获得了一些结果: (不匹配的关键点->黄色)

快速检测器和描述符:

  • 左图像关键点:74
  • 右图像关键点:86
  • 火柴:3(即使探测器坏了,我也有火柴)
以BRISK作为描述符的ORB检测器:

  • 左图像关键点:499
  • 右图像关键点:500
  • 比赛:26场
ORB检测器和描述符

  • 左图像关键点:841
  • 右图像关键点:907
  • 比赛:43场
所有结果都是通过比率测试来消除错误匹配。 我希望这有帮助

编辑:

BruteForceMatcher匹配器;
向量<向量>匹配
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]);
    }
}
DescriptorMatcher descriptorMatcher;
descriptorMatcher=DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING );
MatOfDMatch good_matches;
good_matches = new MatOfDMatch();

LinkedList<MatOfDMatch> dmatchesListOfMat = new LinkedList<>();
descriptorMatcher.knnMatch(imgDescriptors1, imgDescriptors2, dmatchesListOfMat, 2);

LinkedList<DMatch> good_matchesList = new LinkedList<>();
for (int matchIndx = 0; matchIndx < dmatchesListOfMat.size() ; matchIndx++) {
    double ratio = 0.8;
    if (dmatchesListOfMat.get(matchIndx).toArray()[0].distance  < ratio * dmatchesListOfMat.get(matchIndx).toArray()[1].distance) {
        good_matchesList.addLast(dmatchesListOfMat.get(matchIndx).toArray()[0]);
    }
}
good_matches.fromList(good_matchesList);