如果只是百万级汉明不需要几天啊,我觉得#1 说得对,你是否每次都算一遍?
你应该缓存 hash 值的
然后建议分段,如果有分类别什么的,那将大大降低循环次数
windows 有个软件 Similar Images,32bit,可以缓存 hash,作者应该弃坑了,好几年没更新,百万级也就小时级别(不过一次跑百万可能会崩,只能分段)
我自己写的 python 也不用那么久,只是估计,没试过百万,不过我是 hash 和匹配分开(整理时顺便 hash 入库,目前约 50M 张),然后匹配是家常便饭,经常跑小量(千张到万张)匹配,主要是入库时做去重,已经整理入库的就不需要互相比较了
说说算法,常见的 hash 有这几种
cv2.img_hash_PHash
cv2.img_hash_AverageHash
cv2.img_hash_RadialVarianceHash
cv2.img_hash_MarrHildrethHash
cv2.img_hash_ColorMomentHash
cv2.img_hash_BlockMeanHash
cv2 就是 opencv,BlockMean 最快,但极其不准,基本弃了,RadialVariance/ColorMoment 较慢,但还是有点用,ahash/phash 速度适中,MarrHildrethHash 我很少用,主要是搞不清它什么场合更佳
我个人的经验是,aHahs/pHash 中其中一个匹配( OR ),ColorMomentHash/RadialVarianceHash 中其中一个匹配( OR ),这两组 AND 的话,基本就确定重复了 —— 指没有漏判,然后找出的结果中只有很少是错判,错判不到千分之一(分母是全体,包含不重复的)
不过临界值还是要自己调,aHash/pHash/ColorMomentHash 我都是用 3,RadialVarianceHash 我用 0.95 ,全部都比网上代码样例的建议值宽松很多,单独一个算法用这个临界值的话误判会更大,但我组合起来用误判就很小了,这样比单独一个 hash 使用更严格临界值结果还好 —— 原理是图片质量不高的话,应该宽松些,这样不会漏掉,但很多误判,然后用组合降低误判。如果图片质量很高,例如全部都是没有 PS 的摄影作品( raw 或近似 raw )的话,可以适当调高临界值,甚至只用一种算法也够了
还有一种模式匹配算法,不过只适合小图找大图(就是大图里面的一部分),或者有裁切的图找原图,不适合找相似的图,此处不详说了