phash具体的实现可以很多地方都有了,可以搜到很多差不多的内容,在这我也就简单的记录下,具体可以去谷歌或者百度搜下。
-
缩小尺寸 为了后边的步骤计算简单些
-
简化色彩 将图片转化成灰度图像,进一步简化计算量
-
计算DCT 计算图片的DCT变换,得到32*32的DCT系数矩阵。
-
缩小DCT 虽然DCT的结果是32*32大小的矩阵,但我们只要保留左上角的8*8的矩阵,这部分呈现了图片中的最低频率。
-
计算平均值 如同均值哈希一样,计算DCT的均值。
-
计算hash值 根据8*8的DCT矩阵,设置0或1的64位的hash值,大于等于DCT均值的设为”1”,小于DCT均值的设为“0”。组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。
找到的是一个纯c的,来自 phash.org (没错,就是这么官方)。安装啥的网站里边都有,附上一个python调用的脚本。
class pHash(object):
def __init__(self):
self._lib = ctypes.CDLL('/opt/local/lib/libpHash.dylib', use_errno=True)
def dct_imagehash(self, path):
phash = ctypes.c_uint64()
if self._lib.ph_dct_imagehash(path, ctypes.pointer(phash)):
errno_ = ctypes.get_errno()
err, err_msg = (errno.errorcode[errno_], os.strerror(errno_)) \
if errno_ else ('none', 'errno was set to 0')
print(('Failed to get image hash'
' ({!r}): [{}] {}').format(path, err, err_msg), file=sys.stderr)
return None
return phash.value
def hamming_distance(self, hash1, hash2):
return self._lib.ph_hamming_distance(
*map(ctypes.c_uint64, [hash1, hash2]))