这里有很多东西。
为了知道两个图像(几乎)相等,您必须找到这两个图像的单应投影,以便投影导致投影特征位置之间的误差最小。暴力破解是可能的,但效率不高,所以一个技巧是假设相似的图像也倾向于在同一位置具有特征位置(给予或接受一点)。例如,在拼接图像时,要拼接的图像通常仅从稍微不同的角度和/或位置拍摄;即使没有,距离也可能会随着方向的不同而增长(“成比例地”)。
这意味着您可以 - 作为一个广泛的阶段 - 通过在所有图像对之间找到k
具有最小空间距离(k
最近邻)的点对来选择候选图像,并仅对这些点执行单应性。只有这样,您才能比较投影的点对空间距离并按所述距离对图像进行排序;最短距离意味着最好的匹配(考虑到情况)。
如果我没记错的话,描述符的方向是角度直方图中最强的角度。Theat 意味着您也可以决定直接采用 64 或 128 维特征描述符的欧几里德 (L2) 距离,以获得两个给定特征的实际特征空间相似度,并对最佳k
候选者执行单应性。(不过,您不会比较找到描述符的尺度,因为这会破坏尺度不变性的目的。)
这两种选择都非常耗时,并且直接取决于图像和特征的数量;换句话说:愚蠢的想法。
近似最近邻
一个巧妙的技巧是根本不使用实际距离,而是使用近似距离。换句话说,您需要一个近似的最近邻算法,而FLANN(尽管不适用于 .NET)就是其中之一。
这里的一个关键点是投影搜索算法。它的工作原理是这样的:假设您要比较 64 维特征空间中的描述符。您生成一个随机的 64 维向量并对其进行归一化,从而在特征空间中生成一个任意单位向量;让我们称之为A
。现在(在索引期间)您针对该向量形成每个描述符的点积。这会将每个 64 维向量投影到 上A
,从而得到一个实数a_n
。(此值表示描述符相对于的原点a_n
的距离。)A
A
我从这个关于 PCA 的 CrossValidated 的答案中借来的这张图片直观地展示了它;将旋转视为 的不同随机选择的结果A
,其中红点对应于投影(因此,标量a_n
)。红线显示了您使用该方法所犯的错误,这就是使搜索近似的原因。

您将A
再次需要搜索,因此您将其存储。您还可以跟踪每个投影值a_n
及其来自的描述符;此外,您将每个a_n
(带有指向其描述符的链接)排列在一个列表中,按a_n
.
为了澄清使用此处的另一张图像,我们对沿轴的投影点的位置感兴趣A
:

a_0 .. a_3
图像中 4 个投影点的值大约sqrt(0.5²+2²)=1.58
为 、和sqrt(0.4²+1.1²)=1.17
,对应于它们到的原点的距离。-0.84
-0.95
A
如果您现在想要找到相似的图像,您也可以这样做:将每个描述符投影到 上A
,从而产生一个标量q
(查询)。现在您转到q
列表中的位置并获取k
周围的条目。这些是您的近似最近邻居。现在取这些k
值的特征空间距离并按最低距离排序 - 顶部是您的最佳候选者。
回到最后一张图片,假设最上面的点是我们的查询。它的投影是1.58
,它的近似最近邻居(四个投影点)是1.17
. 它们在特征空间上并不是很接近,但鉴于我们只使用两个值比较了两个 64 维向量,它也没有那么糟糕。
您会看到那里的限制,并且类似的预测根本不需要接近原始值,这当然会导致相当有创意的匹配。为了适应这一点,您只需生成更多的基本向量B
,C
等等 - 比如说n
它们 - 并为每个单独的列表跟踪。对所有这些进行最佳匹配,根据它们与查询向量的欧几里德距离对 64 维向量k
列表进行排序,对最好的向量执行单应性并选择具有最低投影误差的向量。k*n
关于这一点的巧妙之处在于,如果您有n
(随机的、标准化的)投影轴并且想要在 64 维空间中搜索,您只需将每个描述符与一个n x 64
矩阵相乘,从而得到n
标量。