我们在工作中经常这种情况,leader给你一堆数据,让你用这些没有清洗过的数据完成项目。痛苦的是,这批数据居然存在很多重复的样本。那如何删除这些冗余数据呢?imagehash库非常好用。
github地址:https://github.com/chinalu/imagedups
imagehash是通过度量两张图片的相似度,并根据相似度判断是否是相似数据,从而帮助我们查找删除冗余数据。Hash算法准确的说有三种,分别为平均哈希算法(aHash)、感知哈希算法你(pHash)和差异哈哈希算法(dHash)。github中使用的平均哈希,所以我们这里仅介绍aHash。
平均哈希算法(aHah)
1.算法步骤
平均哈希算法是三种Hash算法中最简单的一种,它通过下面几个步骤来获得图片的Hash值,这几个步骤分别是(1) 缩放图片;(2)转灰度图; (3) 算像素均值;(4)根据相似均值计算指纹。具体算法如下所示:
得到图片的ahash值后,比较两张图片ahash值的汉明距离,通常认为汉明距离小于10的一组图片为相似图片。当距离=0时即为重复数据。
2.示例展示
本文图片为Lena图来说明.
进过resize之后形成8x8尺寸的图片
之后,将图2灰度化,获得图3.
图3对应的数据矩阵如下
很容得到如上矩阵所有元素的均值a= 121.328125, 将上述矩阵中大于或等于a的元素置为1, 小于a的元素置为0,可得:
所以可得Lena图的aHash为
1011111010011110100111011010100110101011101000110000111000101100
将二进制形式ahash转十六进制hash为
be9e9da9aba30e2c
3.code
我们使用result_dict来寄存图片地址与图片hash值,其中key为hash值,value为图片地址,这样我们在遍历dict时,就可以根据hash值找到对应的图片地址,并删除冗余图片。为了效率,我们可以使用多进程来加速。
def async_hash(fpath, result_dict, result_lock):
try:
h = imagehash.average_hash(Image.open(fpath))
h = "%s" % h
sims = result_dict.get(h, [])
sims.append(fpath)
with result_lock:
result_dict[h] = sims
except Exception as e:
pass