当前位置: 首页 > 面试题库 >

Java OpenCV-从knnMatch提取匹配项

苏振国
2023-03-14
问题内容

我正在尝试实现一个非常简单的程序来查找两个图像之间的相似性。

我正在为此任务使用ORB特征检测器和图像描述符,并且正在使用 knnMatch 识别匹配

FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);

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

// MATCHING
// match these two keypoints sets
List<MatOfDMatch> matches = new ArrayList<MatOfDMatch>();
matcher.knnMatch(descriptors1, descriptors2, matches, 5);

我能够按照以下方式绘制比赛:

// DRAWING OUTPUT
Mat outputImg = new Mat();
// this will draw all matches, works fine
Features2d.drawMatches2(img1, keypoints1, img2, keypoints2, matches, outputImg);

// save image
Imgcodecs.imwrite("result.jpg", outputImg);

问题是比赛太多,而且还包括相距遥远的比赛。我似乎找不到如何仅提取好的匹配项(超过某个阈值)?有人可以指出我正确的方向还是将我重定向到一些基本的工作示例?我已经花了几个小时,似乎迷路了。


问题答案:

如其他答案所述,有几种方法可以消除异常值和不良匹配项。我猜您找到了示例和教程,match而不是knnMatch利用其中的一些方法。

因此,您可能知道不同之处在于knnMatchdescriptor2针对中的每个描述符返回n个最佳匹配descriptor1。这意味着,您将获得匹配列表的列表,而不是匹配列表。我想这就是您遇到问题的原因。

使用的主要优点knnMatch是可以执行比率测试。因此,如果从一个描述符输入descriptor1到两个最佳描述符的descriptor2距离相似,则表明图像中存在重复的图案(例如,草丛前的栅栏尖端)。因此,此类匹配不可靠,应将​​其删除。(我不确定为什么要搜索五个最佳匹配-
knnMatch每个描述符将5传递给-。而是搜索两个。)

如果现在只想访问每个描述符的最佳匹配,则只需要访问“子列表”的第一个元素。在下面的示例中,您将找到使用RANSAC进行比率测试和单应性估计的示例(我在替换了所有内容knnMatch):

    // ratio test
    LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
    for (Iterator<MatOfDMatch> iterator = matches.iterator(); iterator.hasNext();) {
        MatOfDMatch matOfDMatch = (MatOfDMatch) iterator.next();
        if (matOfDMatch.toArray()[0].distance / matOfDMatch.toArray()[1].distance < 0.9) {
            good_matches.add(matOfDMatch.toArray()[0]);
        }
    }

    // get keypoint coordinates of good matches to find homography and remove outliers using ransac
    List<Point> pts1 = new ArrayList<Point>();
    List<Point> pts2 = new ArrayList<Point>();
    for(int i = 0; i<good_matches.size(); i++){
        pts1.add(keypoints1.toList().get(good_matches.get(i).queryIdx).pt);
        pts2.add(keypoints2.toList().get(good_matches.get(i).trainIdx).pt);
    }

    // convertion of data types - there is maybe a more beautiful way
    Mat outputMask = new Mat();
    MatOfPoint2f pts1Mat = new MatOfPoint2f();
    pts1Mat.fromList(pts1);
    MatOfPoint2f pts2Mat = new MatOfPoint2f();
    pts2Mat.fromList(pts2);

    // Find homography - here just used to perform match filtering with RANSAC, but could be used to e.g. stitch images
    // the smaller the allowed reprojection error (here 15), the more matches are filtered 
    Mat Homog = Calib3d.findHomography(pts1Mat, pts2Mat, Calib3d.RANSAC, 15, outputMask, 2000, 0.995);

    // outputMask contains zeros and ones indicating which matches are filtered
    LinkedList<DMatch> better_matches = new LinkedList<DMatch>();
    for (int i = 0; i < good_matches.size(); i++) {
        if (outputMask.get(i, 0)[0] != 0.0) {
            better_matches.add(good_matches.get(i));
        }
    }

    // DRAWING OUTPUT
    Mat outputImg = new Mat();
    // this will draw all matches, works fine
    MatOfDMatch better_matches_mat = new MatOfDMatch();
    better_matches_mat.fromList(better_matches);
    Features2d.drawMatches(img1, keypoints1, img2, keypoints2, better_matches_mat, outputImg);

    // save image
    Imgcodecs.imwrite("result.jpg", outputImg);

我希望这足以作为一个例子。可以类似地应用其他过滤方法。如果您还有其他问题,请随时询问。

编辑: 单应过滤仅在您的大多数关键点位于场景中的同一平面(例如墙等)上时才有效。



 类似资料:
  • 我想从与正则表达式模式匹配的字符串中提取子字符串。 所以我在寻找这样的东西: 这就是我所拥有的: 问题是,为我提供了一个数组,其中的类型为。 < code>NSRange与< code >范围不兼容 知道如何在没有太多代码行的情况下在 swift 中实现这个简单的事情吗?

  • 问题内容: 我正在尝试解析以下类型的字符串: 里面有任意键:“ val”对。我想获取键名和值。对于那些好奇的人,我试图解析任务战士的数据库格式。 这是我的测试字符串: 这是要强调的是,除了空格,冒号周围没有空格而且值始终用双引号引起来,键或值中的任何内容都可以位于键或值中。 在节点中,这是我的输出: 而且也符合这种模式。如何找回所有比赛? 问题答案: 继续循环调用以获取所有匹配项:

  • 我搜索了与Java正则表达式相关的问题,并找到了关于模式和匹配器类的信息,以获得关于reg-ex匹配条件的一组文本。 但是,我的要求不同,我希望提取正则表达式所表示的实际文本。 例: 使用Pattern和Matcher类(或Java中的任何其他方式),如何获得文本“22”?这是正则表达式所代表的文本。

  • 问题内容: 我想要一个正则表达式从HTML页面提取标题。目前我有这个: 是否有一个正则表达式仅提取 的内容,所以我不必删除标签? 问题答案: 用在正则表达式和python中检索捕获的字符串(将返回如果没有找到结果,所以 不要用直接):

  • 亲爱的社区:, 主要问题: 我有一个GeoDataFrame包含纽约-曼哈顿的街道网络(通过osmnx包获得),在那里我想从所有街道中提取坐标(lon/lat数据),这些街道存储为几何学下的LineStrings,就像这样: ** ** 我试图做的是提取每个行项目的几何体信息: 问题是输出格式为str: 这使得自动化和处理输出数据变得困难。有人知道如何提取它,使它已经是LineString(或任何

  • 本文向大家介绍Sfit特征提取和匹配的具体步骤?相关面试题,主要包含被问及Sfit特征提取和匹配的具体步骤?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 生成高斯差分金字塔, 尺度空间构建, 空间极值点检测, 稳定关键点的精确定位, 稳定关键点方向信息分配, 关键点描述, 特征点匹配。