相似图片检测

96

有什么快速的方法可以根据它们彼此的相似性来对给定的一组图像进行排序。

目前我有一个系统,该系统在两个图像之间进行直方图分析,但这是一种非常昂贵的操作,并且看起来太过于繁琐。

理想情况下,我正在寻找一种算法,可以为每个图像赋予一个分数(例如整数分数,例如RGB平均值),然后我可以按该分数进行排序。 相同的分数或相邻的分数可能是重复的。

0299393
0599483
0499994 <- possible dupe
0499999 <- possible dupe
1002039
4995994
6004994 

图像的RGB平均值不太好用,有类似的东西吗?


5
考虑到您写的内容以及Naaff提出的相关问题的一些答案,一个关键问题是您可能需要更清楚地定义“相似”是什么意思。一张图像如果完全相同但偏移了五个像素,是否算“相似”?从视觉上来看是的,但对于算法来说可能不是,除非您已经考虑到并在算法中加以考虑。您能否提供更多的细节信息?重复图像是精确重复还是只是“接近”?您是否正在查看可能因轻微角度测量而有所不同的扫描图像?亮度呢?这里有很多变量... - Beska
“重复项”有何不同?例如,它们是同一位置的图像,只是姿势/移动不同吗?你似乎想要一个与图像数量为O(nlog(n))的算法。有人知道这是否可行吗?看起来可能是可以的。 - Justin Scheiner
@The Unknown:如果您对当前的任何答案都不满意,能否给我们一些更多的指导?我们已经尽力回答您的问题,但是没有任何反馈,我们很难提供更好的解决方案。 - Naaff
这是计算机科学中目前尚未解决的重大问题之一。祝你好运,伙计。 - john k
12个回答

71

在图像搜索和相似度测量方面已经有了许多研究,但这并不是一个简单的问题。通常情况下,一个单独的int不足以确定图像是否非常相似,这会导致高错误率。

然而,由于已经开展了大量的研究,您可以看一些相关内容。例如,这篇论文(PDF)提供了一种紧凑的图像指纹算法,适用于快速查找重复图像且不需要存储大量数据。如果您想要具有鲁棒性的解决方案,这似乎是正确的方法。

如果您寻找更简单但明显更临时的解决方案,这个Stack Overflow问题提供了一些不错的想法。


4
这篇论文是2004年的,不确定它是否仍然是最佳答案? - Andrew

50

我建议考虑不仅使用RGB直方图。

如果您对图像进行2D Haar小波变换(这比听起来容易得多,只需要大量平均和一些平方根用于加权系数),并仅保留小波中k个最大的加权系数作为稀疏向量,将其归一化并保存以减小其大小,那么您可以获得更好的图像摘要。您应该先使用感知权重重新缩放R、G和B,或者我建议切换到YIQ(或YCoCg,以避免量化噪声),以便可以使用降低重要性的色度信息进行采样。

现在,您可以使用两个这些稀疏归一化向量的点积作为相似性度量。点积最大的图像对在结构上非常相似。这具有稍微抵抗调整大小、色调移位和水印的好处,并且实现简单而紧凑。

您可以通过增加或减少k来权衡存储和准确性。

对于这种分类问题,按单个数字分数排序是不可行的。如果您考虑一下,它要求图像只能沿一个轴“改变”,但它们不会。这就是为什么您需要一个特征向量的原因。在Haar小波情况下,它大约是图像中最尖锐不连续性的位置。您可以计算成对图像之间的距离,但由于您只有一个距离度量,线性排序无法表达三个距离相等的图像的“三角形”(即想象一下一个全绿色的图像,一个全红色的图像和一个全蓝色的图像)。

这意味着,任何解决您问题的真正方案都需要 O(n^2) 的操作次数,其中 n 是您拥有的图像数量。如果可以将度量线性化,那么您只需要 O(n log n) 或者如果度量适合于基数排序,则需要 O(n)。话虽如此,您不需要花费 O(n^2),因为在实践中,您不需要筛选整个集合,您只需要找到比某个阈值更接近的内容即可。因此,通过应用几种技术来分割您稀疏向量空间,您可以获得比朴素地将每个图像与每个图像进行比较更快的渐近速度,从而为您提供您可能需要的东西... 如果不是您精确要求的。

无论如何,我几年前个人使用过这个方法,以有效地尝试最小化我存储的不同纹理数量,但在这个领域也有很多研究噪音,显示了它的功效(并在这种情况下将其与更复杂的直方图分类形式进行比较):

http://www.cs.princeton.edu/cass/papers/spam_ceas07.pdf

如果您需要更准确的检测,可以使用minHash和tf-idf算法与Haar小波(或直方图)一起使用来更加稳健地处理编辑:

http://cmp.felk.cvut.cz/~chum/papers/chum_bmvc08.pdf

最后,斯坦福大学拥有一种基于更多特征提取的小波变换的图像搜索方法,以查找旋转或缩放的图像部分等,但这可能远远超出您想要做的工作量。

http://wang14.ist.psu.edu/cgi-bin/zwang/regionsearch_show.cgi


看起来你在间接地描述kd树等用于搜索潜在候选空间的算法。值得注意一下。 - Boojum
1
我没有详细说明技术原因是kd树在空间具有相对较少的维度时表现良好。在这里,您可能有~128或更多的维度,这些维度是稀疏的。由于它们是稀疏的,大多数值将为零,因此在跨维度进行循环以像kd样式一样进行分区实际上几乎是无用的。同样,R树会崩溃, leaving most likely as your best bet: X-trees。不幸的是,面对这么多的维度时它们也接近其性能极限。 - Edward Kmett
仅保留小波中最大的k个加权系数作为稀疏向量,是针对每一行还是整个小波进行保留? - ivan.ukr
你应该至少先使用感知权重对 R、G 和 B 进行重新缩放,或者我建议切换到 YIQ(或 YCoCg,以避免量化噪声),这样你就可以使用降低的重要性对色度信息进行采样。接下来呢?只对 Y 进行小波变换还是对所有通道都进行?如果对所有通道进行,如何测量具有多个通道的图像的相似性?将每个通道的点积相加并将其视为相似度测量,还是应该进行一些加权求和? - ivan.ukr

15
我为此实现了一个非常可靠的算法,称为快速多分辨率图像查询。我(古老且未维护的)代码在这里
快速多分辨率图像查询的作用是根据YIQ颜色空间(比RGB更适合匹配差异)将图像分成3个部分。然后,使用小波算法对图像进行压缩,直到只剩下每个颜色空间中最显著的特征。这些点被存储在一个数据结构中。查询图像经过相同的过程,将查询图像中的显著特征与存储的数据库中的特征进行匹配。匹配越多,图像越相似的可能性就越大。
该算法通常用于“按草图查询”功能。我的软件只允许通过URL输入查询图像,因此没有用户界面。然而,我发现它非常适用于将缩略图与大尺寸图像进行匹配。

它仍然能识别旋转的图像吗? - endolith
我怀疑这样做效果不会很好。你可能需要对每个旋转的图像进行编码,以最大化相关匹配。 - Luke Francl
Retrievr的链接似乎无法访问 - 是否有任何存档的地方? - mmigdol

10

一张图片有许多特征,因此除非你将自己局限于像平均亮度这样的一个特征,否则你就是在处理一个n维问题空间。

如果我要求你为世界各城市分配一个单独的整数,以便告诉我哪些城市比较接近,结果可能不会太好。例如,你可以选择时区作为你的单个整数,并与某些城市获得良好的结果。然而,靠近北极的城市和靠近南极的城市也可能在同一时区,尽管它们位于地球的两端。如果我让你使用两个整数,你可以通过纬度和经度获得非常好的结果。图像相似性的问题也是如此。

尽管如此,还是有一些算法试图将相似的图像聚集在一起,这实际上就是你所要求的。这就是当你在Picasa中进行人脸检测时发生的事情。甚至在识别任何面部之前,它就将相似的面孔聚类在一起,以便轻松地查看一组相似的面孔并给大多数面孔赋予相同的名称。

还有一种叫做主成分分析的技术,它可以将n维数据降低到任意较小的维数。因此,具有n个特征的图片可以被降至只有一个特征。然而,这仍然不是比较图像的最佳方法。


1
这是一个无用的论点,但如果例如特征x = 2,特征y = 3,特征z = 5和特征aa = 7等,则可以使用单个整数表示任意数量的特征组合。那个质数基数被提高到的幂次在因式分解形式中,就是该特定图像的特征值。再说一遍,这是一个无用的论点,因为数字的大小是荒谬的。虽然这个大小可以进一步减小...我们只是讨论结构化数据。 - argyle
正确。但真正重要的是按照数字的顺序排列,使得相似的图像在数值上彼此靠近。尽管我之前说过的话,这是可能的。简而言之,您可以解决旅行推销员问题,以找到通过 n 维空间中的图像的最小(或接近最小)路径(其中 n 是您想要使用比较图像的特征数)。但这是昂贵的。 - Neil

8

有一个C库(“libphash”-http://phash.org/),它可以计算图像的“感知哈希”,并允许您通过比较哈希来检测相似的图像(因此您不必直接将每个图像与其他每个图像进行比较),但不幸的是,当我尝试使用它时,它似乎不太准确。


5

你需要决定什么是“相似的”。对比?色调?

一张照片倒过来和同样的照片是否“相似”?

我敢打赌,通过将图像分成4x4的小块,并为每个网格单元获取平均颜色,您可以找到许多“接近”的情况。每个图像会有十六个得分。为了判断相似性,您只需对图像之间的差异进行平方和。

我认为单个哈希值没有意义,除非针对单个概念,如色调、亮度或对比度。

这是你的想法:

0299393
0599483
0499994 <- possible dupe
0499999 <- possible dupe
1002039
4995994
6004994

首先,我假设这些是十进制数,即 R*(2^16)+G*(2^8)+B 或类似的形式。显然,这不好,因为红色的权重过大。
移至 HSV 空间会更好,您可以将 HSV 的位展开到哈希中,或者只单独解决 H、S 或 V,或者每个图像有三个哈希。

还有一件事。如果你要权衡R、G和B的权重,应该优先考虑绿色,其次是红色,最后是蓝色,以匹配人类视觉敏感度。


5

3
Tineye背后的代码似乎正是提问者需要的,但我认为作为网络服务它并不十分有用,因为没有(明显的)方法可以上传两张图片并询问“这些是相同的吗?”-第二张图片必须放在一个网页上,并由Tineye索引。 - dbr
1
也许他们为商业用户提供API?应该与他们联系了解详情。 - zproxy
1
有一种商业API可以提供这个功能,网址是https://services.tineye.com/MatchEngine。 - Gajus

2

1

我假设其他重复图像搜索软件对图像执行FFT,并将不同频率的值存储为向量:

Image1 = (u1, u2, u3, ..., un)
Image2 = (v1, v2, v3, ..., vn)

然后,您可以通过计算两个图像的权重向量之间的距离来比较它们的相等性:

distance = Sqrt(
     (u1-v1)^2 +
     (u2-v2)^2 +
     (u2-v3)^2 +
     ...
     (un-vn)^2);

2
大多数自然图像具有非常相似的频率内容,因此我怀疑这不是一个非常好的度量标准。 - Hannes Ovrén

1

现代大多数检测近似重复图像的方法都使用有趣点检测和描述符来描述这些点周围的区域。通常使用SIFT。然后,您可以对描述符进行量化,并使用聚类作为视觉词汇。

因此,如果我们看到两个图像的公共视觉单词与这些图像的所有视觉单词的比率,您可以估计图像之间的相似性。有很多有趣的文章。其中之一是近似重复图像检测:minHash和tf-idf加权


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接