在Java中将两个映像与OpenCV进行比较

2022-09-03 15:57:02

我正在尝试使用OpenCV库比较两个图像(确定它们是否相似)。我配置了java包装器,并找到了几个教程(主要是C / C++),我试图将其重写为Java。我正在使用特征检测方法。

问题在于我目前拥有的算法没有产生任何合理的结果(它声称两个相似的图像没有任何共同之处,并在完全不同的其他两个图像之间找到匹配项)。有人可以建议我应该如何使用openCV匹配器来产生一些合理的结果吗?

这是我用于图像比较的代码

private static void compareImages(String path1, String path2) {
    System.out.println(path1 + "-" + path2);

    FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
    DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);

    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);

    // first image
    Mat img1 = Imgcodecs.imread(path1, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
    Mat descriptors1 = new Mat();
    MatOfKeyPoint keypoints1 = new MatOfKeyPoint();

    detector.detect(img1, keypoints1);
    descriptor.compute(img1, keypoints1, descriptors1);

    // second image
    Mat img2 = Imgcodecs.imread(path2, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
    Mat descriptors2 = new Mat();
    MatOfKeyPoint keypoints2 = new MatOfKeyPoint();

    detector.detect(img2, keypoints2);
    descriptor.compute(img2, keypoints2, descriptors2);

    // match these two keypoints sets
    MatOfDMatch matches = new MatOfDMatch();
    matcher.match(descriptors1, descriptors2, matches);

    for (DMatch m : matches.toArray()) {
      // how to use these values to detect the similarity? They seem to be way off
      // all of these values are in range 50-80 which seems wrong to me
      System.out.println(m.distance);
    }
  }

不幸的是,像SURF和SIFT这样的算法在java包装器中不可用,所以我使用的是ORB。我对计算机视觉几乎没有经验,我只是试图让这个简单的比较算法工作产生一些合理的结果。我很乐意得到任何帮助!

编辑:我的用例是针对从不同角度拍摄的图像运行此算法。我更新了我的代码以更好地格式化。

要比较的示例图像:

enter image description here enter image description here


答案 1

只是我的两分钱:

  1. 在java中可以访问SURF和SIFT:openCV DescriptorExtractor Reference。三年前,我尝试了FREAK实现,发现当openCV将它们传递给Java时,二进制描述符会发生一些变化。可能是 ORB 也存在同样的问题。您是否将c或c ++的描述符的数据与Java端的描述符的数据进行了比较?

  2. 暴力破解匹配器从查询图像中每个特征的训练图像中查找最佳匹配特征。即使它看起来完全不同。你必须筛选比赛并放弃坏的比赛。有几种策略,一个简单的策略是只采取最好的20%的比赛(但这不会丢弃所有异常值)。渐进式样本共识在我的设置中表现非常好。

  3. 使用功能来比较图像相似性有它的陷阱。特征计数和质量随图片大小和内容而变化,这使得很难全局比较图像(如果您想知道两个图像中的哪一个图像比另一个更像参考)。您可以使用重叠区域的归一化像素差来估计从一个图像到另一个图像的变换,并使用其归一化像素差。Calib3d.findHomography(obj, scene, CV_RANSAC);

答案 2

本SO问题所述,最简单,最直接的方法是比较直方图。如果您的算法只需要适用于特定的数据集,请尝试使用不同的颜色通道来查看集合中的图像在哪些位置具有最大的相似性。

直方图方法可能看起来不切实际,但考虑到图像的颜色相似性,我相信这可能有些用处。

在Photoshop中比较两个图像的直方图后:

histogram comparison


推荐