快速简单的图像哈希算法

时间:2012-07-04 23:02:27

标签: image algorithm hash

我需要一个(最好是简单快速)图像散列算法。散列值用于查找表,而不是用于加密。

有些图像是“计算机图形” - 即纯色填充的光栅,光栅化文本等,而且还有“摄影”图像 - 包含丰富的色谱,大多是光滑的,具有合理的噪声幅度。

我也希望哈希算法能够应用于特定的图像部分。我的意思是,图像可以分为网格单元格,每个单元格的哈希函数应该仅取决于该单元格的内容。因此,如果两个图像具有共同区域(如果它们被正确对齐),则可以快速发现。

注意:我只需要知道两个图像(或其部分)是否相同。也就是说,我不需要匹配类似的图像,不需要特征识别,相关和其他DSP技术。

我想知道什么是首选的哈希算法。

对于“摄影”图像,只需对网格单元格内的所有像素进行异或运算即可。不同图像的相同散列值的概率非常低,特别是因为(几乎白色)噪声的存在破坏了所有潜在的对称性。此外,这种散列函数的频谱看起来很好(任何值都可能具有几乎相同的概率)。

但是这种天真的算法可能不会与“人工”图形一起使用。对于这样的图像,相同的像素,重复图案,几何偏移不变性是非常常见的。对于具有偶数个相同像素的任何图像,对所有像素进行异或将为0。

使用像CRT-32这样的东西看起来很有希望,但我想更快地找出一些东西。我想到了迭代公式,每个新像素都会改变当前的哈希值,如下所示:

hashValue = (hashValue * /*something*/ | newPixelValue) % /* huge prime */

做模数素数应该可以提供良好的分散,这样我就倾向于这个选项。但我想知道是否有更好的varians。

提前致谢。

2 个答案:

答案 0 :(得分:7)

如果你想让它非常快,你应该考虑采用像素的随机子集来避免读取整个图像。接下来,计算这些像素的值序列的散列函数。随机子集应该由具有固定种子的确定性伪随机数生成器选择,以便相同的图像产生相同的子集,从而产生相同的哈希值。

即使对于人工图像,这也应该相当好。但是,如果您的图像通过少量像素彼此不同,则会产生哈希冲突。更多迭代提供更好的可靠性。如果是这种情况,例如,如果您的图像集可能具有一个不同像素的对,则必须读取每个像素以计算哈希值。即使对于人工图像,采用伪随机系数的简单线性组合也是足够好的。

简单算法的伪代码

Random generator = new generator(2847)  // Initialized with fixed seed
int num_iterations = 100

int hash(Image image) {
    generator.reset()   //To ensure consistency on each evaluation
    int value = 0
    for num_iteration steps {
        int nextValue = image.getPixel(generator.nextInt()%image.getSize()).getValue()
        value = value + nextValue*generator.nextInt()
    }
    return value
}

答案 1 :(得分:6)

查看关于phash算法http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html的本教程,该算法用于查找紧密匹配的图像。