位置敏感哈希或pHash
Locality Sensitive Hash or pHash?
我正在尝试实现一个通用的指纹存储器:我们有一个可以通过智能指纹表达的文件(比如图像的pHash或音频的chromacrint),如果我们的无序(昂贵)函数已经在类似的文件上计算过,那么我们会返回相同的结果(避免昂贵的计算)。
对于代价高昂的多维空间中的近似近邻问题,局部敏感哈希(LSH)是一种流行且性能良好的解决方案。
pHash是一个很好的库,可以实现图像的感知哈希。
因此,pHash将多维输入(图像)转换为一维对象(哈希码),这与LSH(同样是LSH中的多维对象)有所不同。
所以我想知道我们如何为pHash哈希值实现一维LSH?或者简单地说:我们如何在垃圾箱中对类似的pHash值进行分组?它能替代传统的LSH方法吗(如果不能,为什么)?
您可以使用n
随机投影将pHash空间拆分为2^n
桶,然后很可能在同一桶中找到相似的图像。您甚至可以将哈希与所有64个可能的Hamming权重为1的整数进行异或,以方便地检查相邻的桶,并确保找到所有近似匹配。
只有当你对具有几乎相同散列(小汉明距离)的图像感兴趣时,这才是有效的。如果你想容忍更大的hamming距离(比如8),那么要高效准确地找到所有匹配就很难了。通过GPU扫描整个表格,我获得了非常好的性能,即使是我3岁的笔记本电脑的GT 650M也能每秒检查7亿个哈希!
编辑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
不同的可能性,并且类似的散列最有可能最终到达同一个bucket。
该算法适用于数据的任何正交表示(如SURF特征),而不仅仅是二进制字符串。我相信有更简单(计算效率更高)的二进制哈希算法,但这是实现随机投影的一种方法。
我建议XOR,因为如果图像没有相同的散列,那么它们就不能保证最终会在同一个桶中。通过检查与原始哈希的所有可能的小偏差,您可以看到哪些其他bin可能用于可能的匹配。
在某种程度上,这类似于计算机游戏引擎将2D地图拆分为大小为x
的单元格网格,然后要从一个点找到半径为x
的所有单元,只需要检查9个单元格(包含该点的单元格+8个周围单元格)即可获得100%准确的答案。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 使用Qt C++计算类似Git的SHA1哈希
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 用C++将哈希表写入文件并从文件中恢复
- c++找不到具有相同哈希的无序集合元素
- 哈希文件递归并保存到矢量Cryptopp中
- 对 pair<pair<int,int>pair<int,int unordered_map进行哈希处理>>
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 如何为字符串生成唯一但一致的 N 位哈希(小于 64 位)?
- 使用对象的基类部分模板专用化对对象进行哈希处理::哈希
- boost::包含提升单元的元组的哈希值
- 使用 Key 对 C++ 中的哈希映射进行排序. 无法排序
- C++中的并发哈希表
- 哈希映射使用 nullptr c++ 初始化节点的动态数组
- 在具有开放寻址的哈希表中插入节点 [优化逻辑]
- 与C++哈希表的基础知识混淆
- 如何为位集找到/实现一个好的哈希函数
- 对于短字符串来说,这是一个很好的哈希函数吗?
- 位置敏感哈希或pHash