检查两个图像文件是否相同,应该使用校验和还是哈希值?

8

我正在进行一些图像处理代码,在其中我从URL下载一些图像(作为BufferedImage),并将其传递给图像处理器。

我希望避免将同一图像多次传递给图像处理器(因为图像处理操作成本很高)。如果图像的URL端点相同,则可以通过URL来防止这种情况。因此,我计划执行校验和或哈希以确定代码是否再次遇到相同的图像。

对于md5,我尝试了Fast MD5,它为图像(一些样本)生成了一个20K+字符长度的十六进制校验和值。显然,当涉及到数据库存储时,存储这个20K+字符哈希将是一个问题。因此,我尝试了CRC32(来自java.util.zip.CRC32)。它确实生成比哈希更小的校验和长度。

我确实理解校验和和哈希是用于不同目的的。对于上述目的,我是否可以只使用CRC32?它能解决问题吗,还是我需要尝试比这两个更多的东西?

谢谢, 阿比


1
校验和和哈希值是相同的。实际上,它们只是使用了不同的算法。 - Andreas Dolk
1
128位的MD5哈希对于您的目的应该足够了。 - Thor
5
顺便提一句,MD5应该生成128位哈希值,而crc32只有32位...你是如何生成长度超过20k的十六进制校验和的? - Andreas Dolk
我相信这将取决于要处理多少图像。随着图像数量的增加,碰撞概率也会增加。毕竟,32位(CRC32)或128位(MD5)只能做到这么多。 - Vineet Reynolds
2
也许可以分阶段比较;首先,检查尺寸和文件大小。如果没有匹配,就将其传递给处理器。其次,获取前两行像素或前1K的哈希值等(存储在数据库中;因为它只是图像的子集,所以要小得多)。如果这两个测试相等,那么并且只有在原始文件和新文件的哈希值相同时才进行完整图像哈希。这应该能够在实际对整个图像进行哈希之前消除大部分集合。 - AC2MO
显示剩余3条评论
2个回答

5
CRC和MD5的区别在于,与匹配“目标”校验和相比,更难篡改文件以匹配MD5。由于这似乎不是你的程序的问题,所以你使用哪种方法并不重要。也许MD5可能会更加CPU密集,但我不知道这种差异是否重要。
主要问题应该是摘要的字节数。
如果您在整数中进行校验和,这意味着对于2K大小的文件,您正在将2 ^ 2048个组合适合于2 ^ 32个组合--->对于每个CRC值,您将拥有2 ^ 64个可能的匹配文件。如果您有128位的MD5,则有2 ^ 16个可能的碰撞。
计算的代码越大,可能的冲突就越少(假设计算的代码均匀分布),因此比较更安全。
无论如何,为了最小化可能的错误,我认为第一分类应该使用文件大小...先比较文件大小,如果它们匹配,则比较校验和/哈希。

2
一个校验和和哈希基本上是相同的。你应该能够计算任何类型的哈希值。通常情况下,普通的MD5就足够了。如果你想的话,你可以存储大小和MD5哈希值(我认为是16字节)。
如果两个文件的大小不同,它们就是不同的文件。你甚至不需要对数据进行哈希计算。如果你不太可能有许多重复的文件,并且文件比较大(比如用相机拍摄的JPG图片),这种优化可能会节省你很多时间。
如果两个或更多文件的大小相同,则可以计算哈希值并进行比较。
如果两个哈希值相同,你可以比较实际数据以查看这是否真的不同。虽然理论上很少见,但这是非常非常不可能的。你的哈希值越大(md5是16字节,而CR32只有4字节),两个不同的文件具有相同哈希值的可能性就越小。尽管如此,进行这个额外检查只需要10分钟的编程时间,所以我建议:宁愿安全也不要冒险。 :)
为了进一步优化,如果恰好有两个文件的大小相同,你可以直接比较它们的数据。无论如何,你都需要读取文件来计算它们的哈希值,所以为什么不直接比较它们呢?

1
也许在存储已处理的文件以与新文件进行比较时会出现问题。校验和或哈希需要更少的空间。 - SJuan76
1
这是真的。我从来没有打算在数据库中存储整个文件以进行比较。只是说对于单次运行,根本不需要计算哈希值。如果您确实存储数据以检查新添加的文件,则存储哈希值是有意义的,或者您可以选择仅存储文件大小,并且仅在两个文件大小匹配时计算(和存储)哈希值。这将节省空间并节省磁盘IO。 - GolezTrol

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