3

通过 比较 2 张图像时feature extraction,您如何比较keypoint距离以忽略那些明显不正确的距离?

我发现在比较相似的图像时,大多数时候它可以相当准确,但其他时候它可以抛出完全独立的匹配。

因此,我正在寻找一种方法来查看keypoints两张图像中的 2 组图像,并确定匹配的图像是否keypoints相对位于两者的相同位置。因为它知道keypoints图像 1 上的 1、2 和 3 相距很远,所以在图像 2 上匹配的相应关键点应该又彼此相距相当相似的距离。

我过去曾使用过RANSACminimum distance检查过,但只是起到了一些作用,它们似乎不像我所追求的那样彻底。

(使用ORBBruteForce

编辑

将“x、y 和 z”更改为“1、2 和 3”

编辑 2——我将尝试通过快速绘制示例进一步解释:

假设我有这个作为我的形象:

在此处输入图像描述

我给它这张图片来比较:

在此处输入图像描述

它是原始版本的裁剪和压扁版本,但显然相似。

现在,假设您运行它feature detection,它返回keypoints了两个图像的以下结果:

在此处输入图像描述在此处输入图像描述

两个图像上的keypoints区域大致相同,并且彼此之间的距离也成比例地相同。拿keypoint我圈出来的,我们称之为“Image 1 Keypoint 1”

在此处输入图像描述

我们可以看到它周围有5个keypoints。它与我想要获得的“图像 1 关键点 1”之间的这些距离,以便将它们与“图像 2 关键点 1”及其keypoints在同一区域的 5 个环绕(见下文)进行比较,以便不只是将 akeypoint与另一个进行比较keypoint,但根据keypoints.

在此处输入图像描述

--

那有意义吗?

4

3 回答 3

5

关键点匹配是一个多维度的问题。这些尺寸是:

  • 空间距离,即(x,y)从不同图像中两个关键点的位置测量的距离
  • 特征距离,即描述两个关键点相似程度的距离。

根据您的上下文,您不想计算相同的距离,或者您想将两者结合起来。以下是一些用例:

  • 光流,由 opencv 的稀疏 Lucas-Kanade 光流实现。在这种情况下,在每一帧中计算称为良好特征的关键点,然后在空间距离的基础上进行匹配。这是可行的,因为图像应该相对缓慢地变化(输入帧具有视频帧率);
  • 图像拼接,您可以从 opencv 的features2d(免费或非免费)实现。在这种情况下,由于您移动相机,图像会发生根本变化。然后,您的目标变成找到稳定点,即存在于两个或多个图像中的点,无论它们的位置是什么。在这种情况下,您将使用特征距离。当您拥有要在查询图像中查找的对象的模板图像时,这也成立。

为了计算特征距离,您需要计算其外观的编码版本。此操作由DescriptorExtractor类执行。然后,您可以计算描述输出之间的距离:如果两个描述之间的距离很小,那么原始关键点很可能对应于同一个场景点。

计算距离时要注意使用正确的距离函数:ORB、FREAK、BRISK 依赖于汉明距离,而 SIFt 和 SURF 使用更常见的 L2 距离。

匹配过滤

当您有单独的匹配时,您可能希望执行匹配过滤以拒绝可能由场景模糊引起的良好的单独匹配。例如,考虑一个源自房屋窗户角落的关键点。那么它很可能与另一所房子的另一扇窗户相匹配,但这可能不是好房子或好窗户。

你有几种方法可以做到:

  • RANSAC 对计算的匹配与当前解决方案估计执行一致性检查。基本上,它随机选择一些匹配项,计算问题的解决方案(通常是 2 个图像之间的几何变换),然后计算有多少匹配项与这个估计值一致。具有较高内点数的估计获胜;
  • David Lowe 在最初的 SIFT 论文中执行了另一种过滤。他保留了与给定查询关键点匹配的两个最佳候选,即具有最低距离(或最高相似性)的点。然后,他计算了比率similarity(query, best)/similarity(query, 2nd best)。如果这个比率太低,那么次优也是一个很好的匹配候选,匹配结果被称为模棱两可并被拒绝。

因此,在你的情况下你应该如何做很可能取决于你的确切应用。

您的具体情况

在您的情况下,您希望开发一个基于相邻关键点的替代特征描述符。天空显然是这里的极限,但这里有一些我会遵循的步骤:

  1. 通过计算关键点的PCA使您的描述符旋转和比例不变:

    // Form a matrix from KP locations in current image
    cv::Mat allKeyPointsMatrix = gatherAllKeypoints(keypoints); 
    
    // Compute PCA basis
    cv::PCA currentPCA(allKeyPointsMatrix, 2);
    
    // Reproject keypoints in new basis
    cv::Mat normalizedKeyPoints = currentPCA.project(allKeyPointsMatrix);
    
  2. (可选)对四叉树或 kd 树中的关键点进行排序以加快空间索引

  3. 为每个关键点计算一个描述符,该描述符是(例如)4 或 5 个最近关键点的归一化坐标中的偏移量
  4. 在查询图像中执行相同操作
  5. 根据这些新描述符匹配两个法师的关键点。
于 2015-04-09T07:01:50.243 回答
0

您可以对两个关键点之间的像素距离进行过滤。假设matches是你的匹配向量,kp_1是第一张图片上的关键点向量,第二张是kp_2。您可以使用上面的代码来消除明显不正确的匹配。您只需要修复一个阈值。

double threshold= YourValue;
vector<DMatch> good_matches;
for (int i = 0; i < matches.size(); i++)
{
    double dist_p = sqrt(pow(abs(kp_1[matches[i][0].queryIdx].pt.x - kp_2[matches[i][0].trainIdx].pt.x), 2) + pow(abs(kp_1[matches[i][0].queryIdx].pt.y - kp_2[matches[i][0].trainIdx].pt.y), 2));
    if (dist_p < threshold)
    {
        good_matches.push_back(matches[i][0]);
    }
}
于 2015-04-09T06:28:18.210 回答
0

你到底想做什么?需要更多信息才能给您一个好的答案。否则,它必须非常广泛,而且很可能对您的需求没有用处。

并且您的声明“确定匹配的关键点是否相对位于两者的相同位置”您的意思是在两个图像之间的相同 x,y 位置上吗?

我会尝试 SURF 算法。它非常适合您上面描述的内容(尽管我发现它有点慢,除非您使用 gpu 加速,5fps vs 34fps)。

这是 surf 的教程,我个人觉得它非常有用,但可执行文件仅适用于 linux 用户。但是,您可以简单地删除源代码中的操作系统特定绑定,只保留与 opencv 相关的绑定,并让它在 linux 上编译+运行。

https://code.google.com/p/find-object/#Tutorials

希望这有帮助!

于 2015-04-08T16:26:18.573 回答