图像指纹以比较许多图像的相似性


94

我需要创建许多图像的指纹(现有图像约100.000,每天新增1000,RGB,JPEG,最大尺寸800x800),以便将每个图像与其他每个图像进行快速比较。我不能使用二进制比较方法,因为还应该识别几乎相似的图像。

最好是现有的库,但是对现有算法的一些提示将对我有很大帮助。


1
图书馆应使用的语言?
本S

Answers:


57

常规哈希或CRC计算算法不适用于图像数据。必须考虑信息的维度性质。

如果您需要非常鲁棒的指纹识别,从而考虑了仿射变换(缩放,旋转,平移,翻转),则可以在图像源上使用Radon变换来生成图像数据的规范映射-将其与每个图像存储在一起,然后只比较指纹。这是一个复杂的算法,并不适合胆小的人。

可能有一些简单的解决方案:

  1. 为图像创建亮度直方图作为指纹
  2. 创建每个图像的缩小版本作为指纹
  3. 将技术(1)和(2)组合为混合方法以提高比较质量

亮度直方图(尤其是分成RGB分量的直方图)是图像的合理指纹-可以非常有效地实现。从另一个直方图中减去一个直方图将产生一个新的直方图,您可以对其进行处理以确定两个图像的相似程度。直方图,因为仅评估发光度/颜色信息的分布和发生,可以很好地处理仿射变换。如果将每个颜色分量的亮度信息量化为8位值,则768字节的存储空间足以容纳几乎任何合理大小的图像指纹。当操纵图像中的颜色信息时,亮度直方图会产生假阴性。如果您应用诸如对比度/亮度,后色调,色彩偏移,亮度信息更改之类的变换。

使用缩放图像是将图像的信息密度降低到易于比较的水平的另一种方法。缩小到原始图像尺寸的10%以下通常会丢失太多信息以致无法使用-因此800x800像素的图像可以缩小到80x80,并且仍然提供足够的信息来执行不错的指纹识别。与直方图数据不同,当源分辨率的宽高比变化时,必须对图像数据执行各向异性缩放。换句话说,将300x800的图像缩小为80x80的缩略图会导致图像变形,这样,与300x500的图像(非常相似)相比,会导致假阴性。当涉及仿射变换时,缩略图指纹通常还会产生假阴性。如果您翻转或旋转图像,

结合这两种技术是一种合理的方法来对冲您的赌注并减少误报和误报的发生。


关于CRC,同意。但是,如果要使用它,最好使用MD5散列而不是CRC32
mloskot 2010年

5
您不想使用MD5,因为它是一种加密哈希的方式。您需要使用一种哈希方法,该方法对于相似的输入将产生相似的结果,以便您可以直接比较哈希之间的差异。
AJ快速

34

与此处提出的按比例缩小的图像变体相比,临时方法要少得多,该变体保留了它们的一般风味,但是为正在发生的事情提供了更为严格的数学基础。

拍摄图像的Haar小波。从本质上讲,Haar小波是从较低分辨率图像到每个高分辨率图像的连续差分,但是由您在mipmap的“树”中的深度来加权。计算很简单。然后,一旦对Haar小波进行了适当的加权,则丢弃除k个最大系数(就绝对值而言)以外的所有系数,对向量进行归一化并保存。

如果您采用这些归一化向量中两个向量的点积,则可以得出相似性的度量,其中1几乎相同。我在这里发布了更多信息。


20

您绝对应该看看phash

为了进行图像比较,有一个php项目:https : //github.com/kennethrapp/phasher

而我的小JavaScript克隆:https : //redaktor.me/phasher/demo_js/index.html

不幸的是,这是基于“位计数”的,但是可以识别旋转的图像。Javascript中的另一种方法是借助画布来根据图像构建亮度直方图。您可以在画布上可视化多边形直方图,并在数据库中比较该多边形(例如,mySQL空间...)


这是npm吗?我正在寻找一种使用javascript比较两个图像之间相似度的方法
chovy

嗯,我认为这很便宜。实际上,这只是一个从头开始快速编写的演示。但是,随时可以对源进行任何操作。如果可以的话,我会在稍后进行研究,并将其推送到github github.com/redaktor ...
sebilasse

@SebastianLasse我刚刚签出了您的JS端口,这太棒了!我只希望您可以将图像URI传递给Compare()函数,而不必先下载图像。同样,根据我的测试,“非常相似的图像”的阈值应> 90%,而不是> 98%。
thdoan

12

很久以前,我在一个具有类似特征的系统上工作,这是我们遵循的算法的近似值:

  1. 将图片分成几个区域。在我们的案例中,我们处理的是4:3分辨率的视频,因此我们使用了12个区域。这样做会使源图像的分辨率脱离图片。
  2. 对于每个区域,计算总体颜色-该区域中所有像素的平均值
  3. 对于整个图像,计算整体颜色-所有区域的平均值

因此,对于每个图像,您要存储n + 1整数值,其中n是要跟踪的区域数。

为了进行比较,您还需要单独查看每个颜色通道。

  1. 对于整体图像,比较整体颜色的颜色通道以查看它们是否在某个阈值之内-例如10%
  2. 如果图像在阈值之内,则接下来比较每个区域。如果所有区域也都在阈值之内,则图像具有足够强的匹配度,您至少可以标记它们以进行进一步比较。

这样,您可以快速丢弃不匹配的图像。您还可以使用更多区域和/或递归地应用算法以获得更强的匹配置信度。


6

与IC的答案类似-您可以尝试比较多种分辨率的图像。因此,每个图像都保存为1x1、2x2、4x4 .. 800x800。如果最低分辨率不匹配(受阈值限制),则可以立即拒绝。如果匹配,则可以在下一个更高的分辨率下进行比较,依此类推。

另外-如果图像共享任何类似的结构,例如医学图像,则您可能能够将该结构提取到描述中,以便于比较/更快地进行比较。


我认为这映射到某种树搜索。这真有趣。
安德烈·拉兹洛

3

因此,您要进行与“图像匹配”完全不同的“指纹匹配”。在过去的20年中,对指纹的分析进行了深入研究,并且开发了一些有趣的算法来确保正确的检测率(相对于FARFRR措施- 错误接受率错误拒绝率))。

我建议您更好地使用LFA(本地特征分析)类检测技术,这些技术主要基于细节检查。细节是任何指纹的特定特征,并且已分为几类。实际上,大多数公共机构都会将光栅图像映射到细节图上,以提交犯罪分子或恐怖分子文件。

请参阅此处以获取更多参考


如果您具有给定生物识别系统分数的高斯分布,您是否知道如何计算错误接受率?
GobiasKoffi 2010年

OP希望“创建许多图像的指纹”。无法比较人类指纹图像。
纳文


3

截至2015年(回到未来...关于这个2009年的问题,现在在Google中排名很高),可以使用深度学习技术来计算图像相似度。称为自动编码器的算法家族可以创建可搜索相似性的矢量表示。有一个演示这里


是否可以从二进制数据生成指纹图像?
SwR

当然,有ANN可以完成此任务,但是您的答案似乎并没有真正回答任何问题。问题是:如何完成?链接的页面未公开任何信息,术语“自动编码器”也无济于事。
西蒙·斯坦伯格

原始问题并没有说“这是怎么做的?”,而是说“我对现有算法的一些提示会对我有很大帮助”。
Alex R

您没有将“提示”链接到算法,实际上链接的页面说:“它起作用,但是没人知道为什么。请不要对结果
抱有

deeplearning4j.org/deepautoencoder#use-cases提供了自动编码器如何能够被用来创建一个指纹,然后如何可以使用指纹基于顶点如何类似的发现在其他图像的相似性更加明确。
odyth

2

您可以执行此操作的一种方法是调整图像大小并大幅降低分辨率(可能降至200x200?),然后存储较小的(像素平均)版本进行比较。然后定义一个公差阈值并比较每个像素。如果所有像素的RGB都在公差范围内,那么您已经匹配。

最初的运行时间为O(n ^ 2),但如果对所有匹配项进行分类,则每个新图像都只是一个O(n)算法进行比较(您只需将其与每个先前插入的图像进行比较)。但是,随着要比较的图像列表变大,它最终将崩溃,但是我认为您暂时可以安全使用。

运行400天后,您将获得500,000张图像,这意味着(不考虑缩小图像尺寸的时间)200(H)*200(W)*500,000(images)*3(RGB)= 60,000,000,000比较。如果每个图像都完全匹配,那么您将会落后,但是事实可能并非如此,对吧?请记住,一旦单个比较超出您的阈值,您可以将图像作为匹配项打折。


2

您是否真的想将每个图像与其他图像进行比较?有什么用途?也许您只需要基于某些描述符的某种索引和图像检索?然后,例如,您可以查看“多媒体内容描述接口”的MPEG-7标准。然后,您可以比较不同的图像描述符,它们不是那么准确,但是速度要快得多。


也许要在详尽和有限之间做出选择
约翰尼,2009年

0

似乎专门的图像哈希算法是一个活跃的研究领域,但是图像字节的常规哈希计算也许可以解决问题。

您是否要查找字节相同的图像,而不是查找来自同一来源但可能具有不同格式或分辨率的图像(这使我感到相当棘手)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.