删除重复的图像

时间:2008-10-22 10:47:21

标签: c# algorithm image-processing

我们收集了几百张演出的照片图片。大量的照片在视觉上是重复的,但具有不同的文件大小,分辨率,压缩等。

是否可以使用任何特定的图像处理方法来搜索并删除这些重复的图像?

15 个答案:

答案 0 :(得分:21)

我最近想要为PHP图片库完成此任务。我希望能够为上传的图像生成“模糊”指纹,并检查数据库中是否有任何具有相同指纹的图像,表明它们是相似的,然后更密切地比较它们以确定它们的相似程度。

我通过将上传的图像调整为150像素宽,将其缩小为灰度,将每种颜色的值四舍五入到最接近的16的倍数(在0到255之间给出17种可能的灰度阴影)来实现它,将它们标准化并且将它们存储在一个数组中,从而创建一个“模糊”的颜色直方图,然后创建一个md5sum的直方图,然后我可以在我的数据库中搜索。这对于缩小与上传文件在视觉上非常相似的图像非常有效。

然后将上传的文件与数据库中的每个“相似”图像进行比较,我拍摄了两张图像,将它们调整为16x16,然后逐像素地分析它们,并将每个像素的RGB值远离相应的值另一个图像中的像素,将所有值加在一起并除以像素数,得到平均颜色偏差。任何低于特定值的东西都被确定为重复。

整个过程都是使用GD模块用PHP编写的,每个上传文件与数千个图像的比较只需几百毫秒。

我的代码和方法在这里:http://www.catpa.ws/php-duplicate-image-finder/

答案 1 :(得分:5)

尝试使用PerceptualDiff来比较具有相同尺寸的2张图片。允许诸如考虑仅具有X个不同像素的图像的阈值在视觉上不可区分。

如果视觉副本由于缩放或不同的文件类型而可能具有不同的尺寸, 您可能想要制作标准格式进行比较。例如,我可能会使用ImageMagick 将所有图像缩放到100x100并将其保存为PNG文件。

答案 2 :(得分:5)

一个非常简单的方法如下:

  • 将图像转换为内存中的灰度,因此每个像素只是0(黑色)和255(白色)之间的数字。

  • 将图像缩放为固定大小。找到合适的尺寸很重要,你应该玩不同的尺码。例如。您可以将每个图像缩放到64x64像素,但使用更小或更大的图片可能会得到更好或更差的结果。

  • 一旦你为所有图像完成了这个(是的,这需要一段时间),总是在内存中加载两个图像并相互减去它们。即将图像A中的像素(0,0)的值减去图像B中的像素(0,0)的值,现在对两者中的(0,1)执行相同的操作,依此类推。结果值可能是正数或负数,您应该始终存储绝对值(因此5结果为5,-8结果为8)。

  • 现在您有第三张图像是图像A和B的“差异图像”(增量图像)。如果它们相同,则增量图像全部为黑色(所有值将减去零)。 “黑色越少”,图像越不相同。你需要找到一个好的阈值,因为即使图像实际上是相同的(对你的眼睛),通过缩放,改变亮度等,增量图像将不是完全黑色,但它将只有非常暗的灰色。因此,您需要一个阈值,表示“如果平均误差(增量图像亮度)低于某个值,那么它们仍然很可能是相同的,但是如果它高于该值,则很可能不是。找到正确的阈值与找到正确的缩放大小一样难。你总会有误报(图像被认为是相同的,尽管它们根本不相同)和假阴性(图像被认为是不相同的,尽管它们是相同的)。

这个算法超慢。实际上只创建灰度图像需要花费大量时间。然后你需要将每个GS图像相互比较一次,大量的时间。存储所有GS映像也需要大量磁盘空间。所以这个算法非常糟糕,但结果并不差,即使它那么简单。虽然结果并不令人惊讶,但它们比我原先想象的要好。

获得更好结果的唯一方法是使用高级图像处理,这里开始变得非常复杂。它涉及很多数学(很多数学);对于许多已实现这些功能的系统,有很好的应用程序(重复查找程序),因此除非您必须自己编程,否则最好使用其中一种解决方案。我读了很多关于这个主题的论文,但我担心大部分都超出了我的视野。即使是我可以根据这些论文实现的算法也超出了它;这意味着我明白需要做什么,但我不知道它为什么会起作用或它是如何工作的,这只是魔术; - )

答案 3 :(得分:5)

我实际上写了application来做这件事。

我开始使用之前使用基本Levenshtein Distance算法来计算图像相似度的应用程序,但出于多种原因,该方法是不受欢迎的。毫无疑问,您将要找到的用于确定图像相似性的最快算法是mean squared errormean absolute error(两者的运行时间均为O(n),其中n是像素数图像,并且以多种不同的方式对任一算法的实现进行线程化也是微不足道的。 Mecki的帖子实际上只是一个平均绝对错误实现,我的应用程序可以执行(代码也可以为您的浏览乐趣,如果您愿意的话)。

无论如何,在我们的应用程序中,我们首先对图像进行下采样(例如,所有内容都缩放到32 * 32像素),然后转换为灰度,然后通过我们的比较算法运行生成的图像。我们还在研究一些更先进的预处理算法,以进一步规范化图像,但......还没有完全实现。

肯定有比MSE / MAE更好的算法(事实上,应用于视觉信息的这两种算法的问题已被充分记录),如SSIM,但它需要付出代价。其他人试图比较图像中的其他视觉质量,例如亮度,对比度,颜色直方图等,但与简单地测量误差信号相比,它们都是昂贵的。

我的应用可能工作,具体取决于这些文件夹中有多少图像。它是多线程的(我已经看到它完全加载了八个处理器核心进行比较),但我从未测试过大于几百个图像的图像数据库。几百张图像听起来非常大。 (简单地从磁盘中读取它们,下采样,转换为灰度级并存储在内存中 - 假设你有足够的内存来容纳所有东西,你可能没有 - 可能需要几个小时)。

答案 4 :(得分:4)

我相信这仍是一个研究领域。如果您有时间,一些相关的关键字是:

  • 图像复制检测
  • 基于内容的图像检索
  • 图片索引
  • 图片重复删除

基本上,处理(索引)每个图像以产生“图像签名”。类似的图像具有相似的签名。如果您的图像刚刚重新调整,那么它们的签名可能几乎相同,因此它们可以很好地聚类。一些流行的签名是MPEG-7描述符。为了聚类,我认为K-Means或其任何变体都可能就足够了。 但是,您可能需要处理数百万张图像,这可能是一个问题。

以下是维基百科主要条目的链接:
http://en.wikipedia.org/wiki/CBIR

希望这有帮助。

答案 5 :(得分:1)

快速解决这个问题就是编写一个程序来计算每个图像中平均像素的值,以灰度为单位,按此值排序,然后直观地比较它们。非常相似的图像应按排序顺序彼此靠近。

答案 6 :(得分:1)

图像相似性可能是图像处理/ AI的子领域。

如果您正在寻找一种出色的(即高效且可扩展的)解决方案,请准备好从论文中实施算法/公式。

如果你想要快速的东西,请搜索谷歌Image Similarity

Here's一个C#图像相似度应用程序可能会做你想要的。

基本上,所有算法都会提取和比较功能。他们如何定义“特征”取决于他们所基于的数学模型。

答案 7 :(得分:1)

您需要一个命令行工具来处理如此多的数据。

比较每一对可能的图像都不会缩放到如此大的图像集。 您需要根据某个指标对整个图像集进行排序,以便进一步 只需在相邻图像上进行比较。

简单度量的一个示例是图像中所有像素的平均值 作为单个灰度值。只有当重复项没有任何视觉变化时,这才有效。 使用有损文件格式也可能导致视觉变化。

答案 8 :(得分:1)

在框外思考,您可以使用图像元数据来缩小数据集范围。 例如,您的图像可能包含显示图像拍摄日期和时间的字段,直到最接近的秒。 重复项可能具有相同的值。 可以使用诸如exiv2之类的工具将此数据转储为更方便和可排序的文本格式(对批处理/ shell脚本有一点了解)。

甚至可以使用相机制造商和型号等字段来减少1,000,000张图像 说100套10000张图片,显着改善。

答案 9 :(得分:0)

gqview程序有一个查找重复项的选项,因此您可以尝试查找。然而,它并非万无一失,所以它只适合作为一种启发式方法来向人类提供重复,以供人工确认。

答案 10 :(得分:0)

最重要的部分是使文件具有可比性。

通用解决方案可能是将所有图像缩放到特定的固定大小和灰度。然后将生成的图像保存在具有相同名称的单独目录中,以供日后参考。然后可以按文件大小排序并直观地比较相邻条目。

可以通过某种方式量化得到的图像,以编程方式检测相似性(块,线等的平均值)。

答案 11 :(得分:0)

我认为最可扩展的方法是为每个图像存储指纹。然后,当添加新图像时,SELECT id FROM photos where id='uploaded_image_id'的一个简单情况是检查重复项(或对所有图像进行指纹识别,然后对重复进行查询

显然,由于实际内容不同,简单的文件哈希不起作用。

Acoustic fingerprinting / this paper可能是这个概念的良好开端,因为有很多实现。 Here是关于图像指纹识别的论文。

那就是说,你可以用更简单的东西逃脱。将图像大小调整为相等的宽度或高度,从image_a中减去image_b并对差异求和,这是基本的。如果总差异低于阈值,则图像重复。

这个问题是你需要将每个图像相互比较。所需时间将呈指数级增长。

答案 12 :(得分:0)

如果你能想出一种比较服从三角形不等式的图像的方法(例如,如果d(a,b)是图像a和b之间的差异,那么d(a,b)< d(a ,c)+ d(b,c)对于所有a,b,c),然后BK-Tree将是一种有效的索引图像的方式,这样你就可以在O(log n)时间内找到匹配而不是每张图片的时间为O(n)。

如果在不同的压缩/调整大小/等之后将匹配限制在同一图像,则转换为某些规范大小/颜色平衡/等并简单地将每个像素的差异平方相加可能是一个很好的指标,这遵循三角不等式,因此您可以使用BK树进行有效访问。

答案 13 :(得分:0)

如果您有一点钱可以花,可能一旦您运行第一个传递以确定哪些图像可能匹配,您可以为亚马逊的Mechanical Turk编写测试。

https://www.mturk.com/mturk/welcome

基本上,你将创建一个小小部件,AMT会向真正的人类用户展示,然后他们基本上只需回答“这两个图像是否相同?”的问题。或者你可以向他们展示5x5图像的网格并询问他们“这些图像中的哪一个匹配?”。然后,您将收集数据。

另一种方法是使用Luis Von Ahn(http://www.cs.cmu.edu/~biglou/)最着名的人类计算原理和reCaptcha,它使用Captcha答案来确定通过光学字符运行的不可读单词识别,从而有助于数字化书籍。您可以制作一个验证码,要求用户帮助优化图像。

答案 14 :(得分:-1)

这听起来像是程序问题而不是编程问题。谁上传照片?您还是客户?如果要上传照片,请将尺寸标准化为固定比例和文件格式。这样比较会更容易。但是,就目前情况而言,除非您有几天甚至几周的空闲时间,否则我建议您通过视觉比较图像,自己或您的团队手动删除重复图像。

也许您应该按位置对图像进行分组,因为它是旅游图像。