我需要一种(最好是简单且快速的)图像哈希算法。哈希值用于查找表中,而不用于加密。
[有些图像是“计算机图形”-即纯色填充的矩形,光栅化的文本等,而还有“摄影”图像-包含丰富的色谱,大部分是平滑的,并且噪声幅度合理。
我还希望能够将散列算法应用于特定的图像部分。我的意思是,可以将图像划分为一个网格单元,每个单元的哈希函数应仅取决于该单元的内容。这样一来,如果两幅图像具有相同的区域(如果它们对齐正确,则可能会很快发现)。
注意:我只需要知道两个图像(或其部分)是否相同。也就是说,我不需要匹配相似的图像,也不需要特征识别,关联和其他DSP技术。
我想知道首选的哈希算法是什么。
对于“摄影”图像,只需对网格单元中的所有像素进行异或运算即可。对于不同的图像使用相同的哈希值的可能性非常低,尤其是因为(几乎是白色的)噪声的存在破坏了所有潜在的对称性。再加上这种哈希函数的频谱看起来不错(任何值都几乎可以以相同的概率实现)。
但是这种天真的算法可能无法与“人工”图形一起使用。相同的像素,重复的图案,几何偏移不变性对于此类图像非常常见。对具有偶数个相同像素的任何图像,所有像素进行异或运算将得到0。
使用CRT-32之类的工具看起来很有希望,但是我想更快地弄清楚一些事情。我考虑了迭代公式,每个新像素都会改变当前的哈希值,如下所示:
hashValue = (hashValue * /*something*/ | newPixelValue) % /* huge prime */
做模质数可能应该给出一个很好的色散,所以我倾向于这个选项。但是我想知道是否有更好的varians。
提前感谢。
如果要使其变得非常快,则应考虑随机抽取像素的一部分,以避免读取整个图像。接下来,在这些像素的值序列上计算哈希函数。应该由具有固定种子的确定性伪随机数生成器选择随机子集,以使相同的图像产生相同的子集,并因此产生相同的哈希值。
即使对于人造图像,这也应该工作得很好。但是,如果您的图像彼此之间相差很小,则将产生哈希冲突。迭代次数越多,可靠性越高。如果是这种情况,例如,如果您的图像集可能与一对不同的像素成对,则必须读取每个像素以计算哈希值。即使对于人造图像,采用带有伪随机系数的简单线性组合也已足够。
简单算法的伪代码
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
}
请参阅本教程有关用于查找紧密匹配的图像的phash算法http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html。
您可以xxHash。它已被NetFlix,Microsoft Azure等许多公司使用。它也支持多种语言。Go,Erlang,Pythin,Java等。https://cyan4973.github.io/xxHash/