Java 尽管具有良好的单应性内联线,opencv透视变换仍会产生不正确的变换

Java 尽管具有良好的单应性内联线,opencv透视变换仍会产生不正确的变换,java,opencv,Java,Opencv,我在尝试透视变换以产生我能理解的结果时遇到了问题 我正在写一个图像匹配应用程序。这些图像大多是绘画。我匹配的是整体,整体,部分,部分,甚至部分。决议将有所不同。由于这种关系,通常使用的对象场景术语不适用。因为对象实际上可以是场景,反之亦然。所以我使用查询图像和目标索引图像来描述查询和匹配的图像 我一直在遵循各种OpenCV教程,将一幅图像与另一幅图像进行匹配,然后使用透视变换在识别的图像上放置边界框……但我遇到了问题 在这张图片中,我们可以看到我有一个完整的部分关系。 图像已缩放至最大边缘100

我在尝试透视变换以产生我能理解的结果时遇到了问题

我正在写一个图像匹配应用程序。这些图像大多是绘画。我匹配的是整体,整体,部分,部分,甚至部分。决议将有所不同。由于这种关系,通常使用的对象场景术语不适用。因为对象实际上可以是场景,反之亦然。所以我使用查询图像和目标索引图像来描述查询和匹配的图像

我一直在遵循各种OpenCV教程,将一幅图像与另一幅图像进行匹配,然后使用透视变换在识别的图像上放置边界框……但我遇到了问题

在这张图片中,我们可以看到我有一个完整的部分关系。 图像已缩放至最大边缘1000,并作为进行此操作的SIFT过程的一部分转换为灰度

Query image dimensions x=1000, y=750  
Idx image dimensions x=667, y=1000  

Initial Flann matches: 501  
After Lowe's 2nd nn ratio: 48 matches  
RANSAC inliers: 37 matches  
代码

homography = Calib3d.findHomography(idxMatOfPoint2f, queryMatOfPoint2f, Calib3d.RANSAC, 5, mask, 2000, 0.995);
Mat query_corners = new Mat(4, 1, CvType.CV_32FC2);
Mat idx_corners = new Mat(4, 1, CvType.CV_32FC2);


query_corners.put(0, 0, new double[]{0, 0});
query_corners.put(1, 0, new double[]{queryImage.cols() - 1, 0});
query_corners.put(2, 0, new double[]{queryImage.cols() - 1, queryImage.rows() - 1});
query_corners.put(3, 0, new double[]{0, queryImage.rows() - 1});

Core.perspectiveTransform(query_corners, idx_corners, homography);
这段代码的结果给出了以下原始数据x,y:transformed x,y

Corners - Top-left  = 0.0,0.0 : 163.84683227539062,167.56898498535156  
Corners - Top-right = 999.0,0.0 : 478.38623046875,169.61349487304688  
Corners - Bot-right  = 999.0,749.0 : 491.45220947265625,411.24688720703125  
Corners - Bot-left  = 0.0,749.0 : 162.11233520507812,411.5089416503906  
现在很明显,绘制的点图像是错误的,但选择要绘制的点意味着我已经确定了这一点。然而,我发现奇怪的是,框是查询图像的整个大小,转换为第二个图像的空间。我没想到盒子的大小和形状会以一种似乎与第一张图片不匹配的方式缩小

变换后的x,y对我来说没有任何意义。有人能解释一下吗

查看图2,其中查询是目标idx图像给出的部分和整体:

Initial Flann matches: 500
After Lowe's 2nd nn ratio: 21
RANSAC inliers: 17

query image dimensions x=1000, y=750
idx   image dimensions x=1000, y=609

Corners - Top-left  = 0.0,0.0 : -1228.55224609375,-923.1514282226562
Corners - Top-right = 999.0,0.0 : 3561.064453125,-930.8649291992188
Corners - Bot-right  = 999.0,749.0 : 2768.0224609375,1934.417236328125
Corners - Bot-left  = 0.0,749.0 : -699.1375732421875,2089.652587890625
这对我来说也是毫无意义的-1228? 但这两个图像的宽度都只有1000,查询完全包含在目标idx图像中

最后一幅图显示了这种情况下的挫折感。 在这里,我们可以看到透视变换后的角点刚好相距很远——它实际上比匹配的图像小……看起来透视变换函数返回的结果几乎是随机的


谁能看出我做错了什么?我是否误解了透视变换?

多亏了米卡……透视变换中问题的答案是因为查询和预索引图像点在函数调用中被交换了。下面的调用为匹配的图像提供正确的结果

单应性=Calib3d.findHomographyqueryMatOfPoint2f,idxMatOfPoint2f,Calib3d.RANSAC,5,mask,2000,0.995

然而,单应性正在通过一组奇怪的匹配,这是不允许的。
透视变换现在解决后,我将发布一个新的Q。

你能试试单应=Calib3d.findHomographyqueryMatOfPoint2f,idxMatOfPoint2f,Calib3d.RANSAC,5,mask,2000,0.995;?不同的查询顺序/idxaha。说得好。奇怪的是,我是这样想的——我会试试另一种方法。不确定哪个顺序是正确的,但这是一个常见的错误源:Di可以看出为什么这会影响以后返回的分数。快速的尝试可以让大量不匹配的项目通过。一个问题是,查询对象中有多个点映射到单个点。邮票的图像或带有文字的图像(如发光的MS)可能会导致这些类型的匹配-这正是我试图通过单应性消除的。。。我将仔细检查我使用的点集,确保我没有交换东西。遗憾的是,我不能在评论中添加图片,所以如果这不能解决我的问题,我会更新主要问题。谢谢。是的,这解决了盒子的问题。然而,我现在对匹配的质量有问题-查询->idx中的单应包括虚假匹配,但是当图像确实相关时,它会得到正确的边界。我将发布另一个关于匹配问题的问题。非常感谢您发现了这样一个简单的错误!请注意,反向单应性检查实际上解决了伪匹配问题!尽管这可能不是最好的方法。