通过feature extraction
比较2张图片时,如何比较keypoint
距离,以便忽略明显不正确的距离?
我在将相似图像相互比较时发现,大多数情况下它可以相当准确,但有时它可以抛出完全分开的匹配。
所以我在查看两张图片中的两组keypoints
之后,确定匹配的keypoints
是否相对位于两者的相同位置。因为它知道keypoints
1,2和3在图像1上相距很远,所以在图像2上匹配的相应关键点应该具有相当远离彼此的距离。
我过去曾使用RANSAC
和minimum distance
支票但只是为了实现某些效果,它们似乎并不像我之后那样彻底。< / p>
(使用ORB
和BruteForce
)
修改
将&#34; x,y和z&#34; 更改为&#34; 1,2和3&#34;
编辑2 - 我将尝试使用快速绘制的示例进一步解释:
说我把它作为我的形象:
我给它这张图片进行比较:
它是原版的裁剪和压扁版本,但显然相似。
现在,假设您通过feature detection
运行了它,然后它返回了keypoints
这两张图片的结果:
两张图像上的keypoints
位于大致相同的区域,并且相互之间的距离相同。将keypoint
圈起来,我们称之为 &#34;图片1关键点1&#34; 。
我们可以看到它周围有5个keypoints
。它们与 &#34;图像1关键点1&#34; 之间的距离是我想要获得的,以便将它们与 &#34进行比较;图像2关键点1&#34; 及其5个环绕keypoints
位于同一区域(见下文),以便不仅仅将keypoint
与另一个{{1}进行比较},但要根据keypoint
的位置比较&#34;已知形状&#34; 。
-
这有意义吗?
答案 0 :(得分:5)
关键点匹配是几个维度的问题。这些维度是:
(x,y)
距离根据您的上下文,您不希望计算相同的距离,或者您希望将两者结合起来。以下是一些用例:
为了计算要素距离,您需要计算其外观的编码版本。此操作由DescriptorExtractor类执行。 然后,您可以计算描述输出之间的距离:如果两个描述之间的距离很小,那么原始关键点很可能对应于同一个场景点。
计算距离时要注意使用正确的距离函数:ORB,FREAK,BRISK依赖汉明距离,而SIFt和SURF使用更常见的L2距离。
匹配过滤
当您有单独匹配时,您可能希望执行匹配过滤,以拒绝可能由场景模糊引起的良好个别匹配。想想一个源自房屋窗户角落的关键点。然后它很可能与另一个房子里的另一个窗口匹配,但这可能不是好房子或好窗口。
你有几种方法可以做到:
similarity(query, best)/similarity(query, 2nd best)
。如果这个比例太低,那么第二好的也是比赛的一个很好的候选人,匹配的结果被称为含糊不清并被拒绝。因此,在您的情况下,您应该如何做到这一点很可能取决于您的确切应用。
您的具体案例
在您的情况下,您希望开发基于相邻关键点的备用要素描述符。 天空显然是这里的限制,但这里有一些我要遵循的步骤:
通过计算关键点的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);
(可选)对四叉树或kd树中的关键点进行排序,以便更快地进行空间索引
答案 1 :(得分:0)
你要做的是什么?需要更多信息才能给出一个好的答案。否则,它必须非常广泛,并且很可能对您的需求无益。
并使用您的陈述&#34;确定匹配的关键点是否相对位于两者的相同位置。你的意思是两个图像之间的相同x,y位置吗?
我会试用SURF算法。它适用于你上面描述的内容(虽然我发现它有点慢,除非你使用gpu加速,5fps对34fps)。
这是关于surf的教程,我个人认为它非常有用,但可执行文件仅适用于linux用户。但是,您可以简单地删除源代码中的特定于操作系统的绑定,并仅保留与opencv相关的绑定,并在linux上编译和运行它们。
https://code.google.com/p/find-object/#Tutorials
希望这有帮助!
答案 2 :(得分:0)
您可以对两个关键点之间的像素距离进行过滤。 假设匹配是你的匹配向量,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]);
}
}