如何使用 SIFT 算法计算两幅图像的相似程度?

Posted

技术标签:

【中文标题】如何使用 SIFT 算法计算两幅图像的相似程度?【英文标题】:How to use SIFT algorithm to compute how similar two images are? 【发布时间】:2010-12-02 19:09:08 【问题描述】:

我使用了Andrea VedaldiSIFT 实现,来计算两个相似图像的筛选描述符(第二个图像实际上是同一对象从不同角度放大的图片)。

现在我无法弄清楚如何比较描述符以判断图像的相似程度

我知道这个问题是无法回答的,除非你以前真的玩过这些东西,但是我认为以前做过这个的人可能知道这个,所以我发布了这个问题。

我为生成描述符所做的小事:

>> i=imread('p1.jpg');
>> j=imread('p2.jpg');
>> i=rgb2gray(i);
>> j=rgb2gray(j);
>> [a, b]=sift(i);  % a has the frames and b has the descriptors
>> [c, d]=sift(j);

【问题讨论】:

也检查SURF,Matlab 已经内置了对此的支持。 【参考方案1】:

尝试将第一张图像中的每个描述符与位于附近的第二张图像中的描述符进行比较(使用欧几里得距离)。因此,您可以根据第一张图像中的每个描述符与第二张图像中最相似的邻居描述符之间的相似度为每个描述符分配一个分数。所有这些分数的统计测量(总和、平均值、离散度、平均误差等)可以让您估计图像的相似程度。尝试附近大小和统计度量的不同组合,为您提供最佳答案。

【讨论】:

【参考方案2】:

首先,您不应该使用 vl_sift 而不是 sift 吗?

其次,您可以使用 SIFT 特征匹配来查找两个图像中的对应关系。这是一些示例代码:

    I = imread('p1.jpg');
    J = imread('p2.jpg');

    I = single(rgb2gray(I)); % Conversion to single is recommended
    J = single(rgb2gray(J)); % in the documentation

    [F1 D1] = vl_sift(I);
    [F2 D2] = vl_sift(J);

    % Where 1.5 = ratio between euclidean distance of NN2/NN1
    [matches score] = vl_ubcmatch(D1,D2,1.5); 

    subplot(1,2,1);
    imshow(uint8(I));
    hold on;
    plot(F1(1,matches(1,:)),F1(2,matches(1,:)),'b*');

    subplot(1,2,2);
    imshow(uint8(J));
    hold on;
    plot(F2(1,matches(2,:)),F2(2,matches(2,:)),'r*');

vl_ubcmatch() 本质上做了以下事情:

假设您在 F1 中有一个点 P,并且您想在 F2 中找到“最佳”匹配。一种方法是将 F1 中 P 的描述符与 D2 中的所有描述符进行比较。通过比较,我的意思是找到欧几里得距离(或两个描述符差异的 L2 范数)。

然后,我在 F2 中找到两个点,比如 U 和 V,它们分别与 P 的距离最小和次低(比如 Du 和 Dv)。

这是 Lowe 的建议:如果 Dv/Du >= 阈值(我在示例代码中使用了 1.5),那么这种匹配是可以接受的;否则,它会模棱两可地匹配并被拒绝为对应关系,并且我们不会将 F2 中的任何点与 P 匹配。本质上,如果最佳匹配和次佳匹配之间存在很大差异,则可以预期这是质量匹配。

这很重要,因为图像中有很多模糊匹配的范围:想象在湖泊或具有多个窗户的建筑物中的匹配点,描述符可能看起来非常相似,但对应关系显然是错误的。

您可以通过多种方式进行匹配。您可以使用 MATLAB 自己轻松完成匹配,也可以使用 KD-tree 或近似最近数搜索(如已实现的 FLANN)来加快匹配速度在OpenCV。

编辑:另外,有几个kd-tree implementations in MATLAB。

【讨论】:

这通常是通过sift识别物体的方法,但它是确定物体相似度的最有效方法吗?相似性与在 ll 之后识别并不完全相同。看了推荐的金字塔匹配内核论文后,我想答案是否定的。 @mugetsu:也许吧,但这不是重点;问题是关于从 VLFeat 工具箱中获取描述符。 从我对问题的解释来看,我的印象是 Lazer 询问如何确定两个图像是否相似,而不是获取描述符(他已经完成了)。对描述符进行比较并不意味着他必须限于 vlfeat 函数,他所需要的只是某种形式的算法来应用于这些描述符。在他的情况下,就像我的情况一样,vlfeat 没有我们需要进行相似性比较的东西。 VL_UBCMATCH 函数是否有 python (opencv) 实现?【参考方案3】:

您应该阅读 David Lowe 的 paper,其中谈到了如何做到这一点。如果您想比较完全相同对象的图像,这就足够了。如果您想匹配同一类别的不同物体(例如汽车或飞机)的图像,您可能需要查看 Grauman 和 Darrell 的 Pyramid Match Kernel。

【讨论】:

你有没有偶然使用过金字塔匹配内核?您对其性能有何看法? @mugetsu 我使用了一些已发布的代码(libpmk),但我没有太多使用它。不过,论文中的结果看起来令人印象深刻。【参考方案4】:

如果您只想将缩放和旋转的图像与已知的旋转中心进行比较,您可以使用对数极坐标中的相位相关性。通过峰值的清晰度和相位相关的直方图,您可以判断图像的接近程度。您还可以对傅立叶系数的绝对值使用欧几里得距离。

如果您想比较 SIFT 描述符,除了欧几里得距离之外,您还可以使用“漫反射距离” - 获取越来越粗略的描述符并将它们与原始描述符连接。这样,“大规模”特征相似性就会有更多的权重。

【讨论】:

【参考方案5】:

如果你想在图像之间进行匹配,你应该使用 vl_ubcmatch (以防你没有使用它)。您可以解释输出的“分数”以查看特征的接近程度。这表示两个匹配特征描述符之间的欧几里得距离的平方。您还可以更改最佳匹配和第二最佳匹配之间的阈值作为输入。

【讨论】:

以上是关于如何使用 SIFT 算法计算两幅图像的相似程度?的主要内容,如果未能解决你的问题,请参考以下文章

通过欧几里得距离(或任何其他距离计算技术)基于提取的 SIFT 描述符估计两幅图像的相似度得分

opencv如何计算两幅图像的相似度

基于特征点匹配的图像相似度算法之SIFT特征

基于特征点匹配的图像相似度算法之SIFT特征

基于特征点匹配的图像相似度算法之SIFT特征

opencv2.4.3中基于sift算法完成特征检测后,有没有图像融合的函数。直接把检测完的两幅图像拼接起来。