你可以使用
n
随机投影将pHash空间划分为
2^n
个桶,然后相似的图像很可能来自同一个桶。你甚至可以将哈希与所有64个具有汉明重量1的可能整数进行异或运算,以便方便地检查相邻的桶,并确保你找到所有近似匹配。
这只有在你对几乎相同哈希(小汉明距离)的图像感兴趣时才有效率。如果你想容忍更大的汉明距离(例如8),那么要高效准确地查找所有匹配项就变得棘手了。我通过
GPU扫描整张表格获得了非常好的性能,即使是我三年前的笔记本电脑上的GT 650M也可以每秒检查700万个哈希值!
编辑 1:您可以将 64 位哈希视为 64 维立方体上的单个角落,如果您将角落坐标归一化到
-1
和
1
(这样其中心在原点),数学计算会更加简单。您可以将
m
张图像表示为大小为
m x 64
的矩阵
M
(一行/图像,一列/哈希的一位)。
将其分成
2^n
个不同的组最简单的方法是生成
n
个 64 维向量
v_0, v_1, ..., v_n
(从正态分布 N(0,1) 中选择每个向量元素),这可以表示为大小为
64 x n
的矩阵
V
(一个列/向量)。可能会执行正交性强制操作,如随机投影中所述,但我将在此处跳过。
现在通过计算
A = (M * V) > 0
,您将得到一个
m x n
矩阵(一行对应一张图像,一列对应一个投影)。接下来将每一行的二进制表示转换为一个数字,您将得到
2^n
种不同的可能性,类似的哈希很可能会被放入同一个桶中。
这种算法适用于数据的任何正交表示(例如
SURF 特征),不仅限于二进制字符串。我相信还有更简单(并且计算效率更高)的二进制哈希算法,但这是实现随机投影的一种方式。
我建议使用异或操作,因为如果图像的哈希值不相同,则不能保证它们最终会被放入同一个桶中。通过检查与原始哈希值的所有可能的小偏差,您可以看到哪些其他桶可能包含可能匹配的内容。
从某种意义上说,这类似于计算机游戏引擎如何将 2D 地图分割成大小为
x
的网格,然后要查找距离一个点
x
半径内的所有单位,您只需要检查 9 个单元格(包含点的单元格 + 周围 8 个单元格),即可得到 100% 准确的答案。