欢迎光临
我们一直在努力

Python 图像哈希库 imagehash——从原理到实践


一、前言:为什么需要图像哈希?

在当下的互联网环境中,图像数据以爆炸式速度增长。从社交平台的图片分发,到电商平台的商品图采集,再到内容审核、重复图像检测、盗图追踪,如何高效比较两个图像是否相同或相似成为一个核心问题。

我们可以使用深度学习模型如 CNN、ViT 提取图像特征,但这需要 GPU,代价高、复杂度大。而传统图像处理领域提供了一个简单高效的解决方案。

图像感知哈希(Perceptual Hash, pHash)及其系列算法

Python 的 imagehash 库正是目前应用最广、最稳定的一套图像哈希计算工具。

它具有以下特点:

  • 速度极快(毫秒级)
  • 对缩放、旋转、亮度变化不敏感
  • 哈希值可用于相似度比较
  • 包含多个算法:aHash、pHash、dHash、wHash

无论你是做:内容去重、图像相似搜索、爬虫去重、图库管理、数字资产管理、图形数据库、以图搜图系统,imagehash 都能胜任。

接下来,我们将从安装、算法原理、使用方法、进阶技巧,逐步完整展开。


二、imagehash 库简介

imagehash 是基于 PIL(即 pillow)的图像感知哈希算法工具包。

安装方式非常简单:

pip install imagehash pillow

常用导入方式:

from PIL import Image
import imagehash

它支持四大经典图像哈希算法:

哈希算法全称优点使用场景
aHash average hash 简单快速 基础相似检测、轻量级应用
pHash perceptual hash 最稳健、常用 内容审查、重复图检测
dHash difference hash 相当稳定 图像去重、图像聚类
wHash wavelet hash 去噪效果强 细节损失较多场景

除此之外,它还支持 colorhash、crop-resistant hash 等进阶算法。


三、图像感知哈希的核心思想

传统哈希(如 MD5、SHA256)的特点是:

输入只要有一点点变化,输出就完全不同。

所以不能用来比较图像相似度。

感知哈希的思想正好相反:

当两张图片“看起来相似”时,它们的哈希应当相近。

因此,感知哈希的目标:

  • 忽略图像的噪声
  • 忽略尺寸变化
  • 忽略亮度变化
  • 忽略轻微裁剪
  • 保留整体结构和视觉内容

最终得到一个通常使用 64 bit(8×8)长度的哈希值:

例:

ff00aa55cc33ee99

两个哈希值之间的差异(Hamming Distance)即可判断图像相似度。

例如:

hash1 = imagehash.phash(Image.open("img1.jpg"))
hash2 = imagehash.phash(Image.open("img2.jpg"))

similarity = hash1 hash2 # 汉明距离

通常距离 <5 可以认为是同一张图片或极其相似。


四、四大常用哈希算法全面解析

接下来我们分别讲解算法原理、特点和代码使用。


1. aHash —— 平均哈希(Average Hash)

算法流程

  • 把图像缩小到 8×8
  • 转成灰度
  • 求平均值
  • 灰度 > 平均值 → 1,否则 → 0
  • 得到 64 bit 哈希
  • 特点

    • 速度最快
    • 简单,可用于海量图片快速预处理
    • 对亮度变换不敏感
    • 但对轻微变化敏感(裁剪、噪声)

    代码示例

    hash_val = imagehash.average_hash(Image.open('x.jpg'))
    print(hash_val)


    2. pHash —— 感知哈希(最经典)

    算法流程

  • 图像缩放为 32×32
  • 转灰度
  • 使用 DCT 变换(离散余弦变换)
  • 取左上角 8×8 低频区块
  • 比较低频分量与均值
  • 特点

    • 对缩放、亮度变化非常稳健
    • 效果最好、最常用
    • 比 aHash 略慢(仍然非常快)

    代码示例

    hash_val = imagehash.phash(Image.open('x.jpg'))
    print(hash_val)


    3. dHash —— 差值哈希

    算法流程

  • 缩放为 9×8
  • 比较相邻像素
  • 灰度左 > 右 → 1,否则 → 0
  • 特点

    • 对结构变化敏感
    • 比 pHash 快
    • 效果稳定,广泛用于图像去重

    代码

    hash_val = imagehash.dhash(Image.open('x.jpg'))


    4. wHash —— 小波变换哈希(Wavelet Hash)

    特点

    • 抗噪声能力最强
    • 对模糊图、压缩图也稳定
    • 稍微比 pHash 慢

    使用

    hash_val = imagehash.whash(Image.open('x.jpg'))


    五、哈希值比较:判断两图是否相似

    imagehash 的对象支持直接做减法:

    hash1 = imagehash.phash(Image.open('a.jpg'))
    hash2 = imagehash.phash(Image.open('b.jpg'))

    distance = hash1 hash2 # 汉明距离

    一般参考阈值:

    汉明距离相似度判断
    0 完全相同
    1-5 同一张图片、压缩尺寸不同
    6-10 内容相似(例如同一物体)
    10 以上 基本不相似

    可自定义阈值:

    if distance < 5:
    print("图片相似")


    六、在实战中使用 imagehash:10 个典型场景

    1. 大规模图片去重(电商、图库)

    适用于:

    • 商品图片采集
    • 抖音/小红书去重
    • 内容审核系统

    使用 pHash 或 dHash 最稳定。

    2. 内容审核(版权、盗图识别)

    可用于发现:

    • 相似照片
    • 水印图
    • 裁剪、调整过的图像

    3. 搜索引擎:以图搜图

    流程:

  • 给每个图库图片生成哈希
  • 用户上传图片计算哈希
  • 计算差值 <5 的返回
  • 4. 图形数据库(如 Elasticsearch + imagehash)

    将哈希存储为字符串即可快速检索。

    5. 图像聚类

    可用于:

    • 人像去重
    • 事件聚类
    • 相册管理

    借助 k-means/DBSCAN 可聚类哈希向量。

    6. 监控场景:帧相似度检测

    可判断:

    • 场景变化
    • 异常事件
    • 镜头切换

    7. 视频抽帧去重

    imagehash + ffmpeg:

    • 抽帧
    • 计算哈希
    • 剔除重复

    8. 防止重复提交(如合同照片)

    可根据哈希查重。

    9. 对抗恶搞图片(meme 分析)

    字符变换颜色后仍可检测相似。

    10. 软件安全与内容完整性验证

    判断图标、UI素材是否被篡改。


    七、进阶使用:colorhash、crop-resistant-hash 等

    imagehash 还提供高级功能:


    1. ColorHash(颜色直方图哈希)

    适合风景图、背景色分类。

    hash_val = imagehash.colorhash(Image.open('x.jpg'))


    2. Crop-Resistant Hash(最强算法)

    对裁剪、长宽变化非常稳健。

    适用于:

    • 社交平台裁剪图
    • 盗图识别

    八、与 OpenCV 和 deep learning 的对比

    1. 与 OpenCV 的 difference hash 对比

    OpenCV 也能写 dHash,但 imagehash 更完整。

    2. 与深度学习特征(CNN、CLIP)相比

    imagehash 优点:

    • 更快(毫秒级)
    • 无需 GPU
    • 部署简单
    • 结果可解释(哈希差)

    深度学习优点:

    • 支持复杂语义相似度
    • 更多场景(如动物、物体检测)

    结论:

    imagehash 适合结构相似检测,深度学习适合语义相似检测。

    在工程中常常两种结合使用。


    九、性能优化方案(适合海量数据)

    如果要处理百万级图片,可采取:

    1. 批处理哈希计算

    多线程:

    from concurrent.futures import ThreadPoolExecutor

    def calc(path):
    return imagehash.phash(Image.open(path))

    with ThreadPoolExecutor(20) as pool:
    results = list(pool.map(calc, images))

    2. 哈希存储结构优化

    存储为:

    • 64-bit int
    • binary bit array

    可加速比较。

    3. 使用 Annoy / FAISS 做哈希近似搜索

    imagehash 返回的是 64bit bit-array,可作为向量存入 FAISS。


    十、完整示例:构建一个图片重复检测系统

    以下代码展示一个从目录中自动检测重复图片的完整程序:

    from PIL import Image
    import imagehash
    import os

    def find_duplicates(folder, threshold=5):
    hash_dict = {}
    duplicates = []

    for fname in os.listdir(folder):
    if not fname.lower().endswith(('.jpg', '.png', '.jpeg')):
    continue

    path = os.path.join(folder, fname)
    img = Image.open(path)

    h = imagehash.phash(img)

    for oh, opath in hash_dict.values():
    if h oh < threshold:
    duplicates.append((path, opath))
    break

    hash_dict[fname] = (h, path)

    return duplicates

    dups = find_duplicates("images/")

    for a, b in dups:
    print("相似图片:", a, "<==>", b)


    十一、常见问题 FAQ

    Q1:不同算法的差异如何选择?

    建议:

    • 宽松去重:pHash
    • 快速去重:dHash
    • 抗噪声:wHash
    • 色彩特征:colorhash

    Q2:为什么同一图片的哈希值有时不同?

    可能原因:

    • EXIF 旋转信息不同
    • 图像压缩/分辨率变化
    • 使用了不同算法

    Q3:汉明距离阈值如何设定?

    经验值:

    • 0~5:同一张图
    • 5~10:内容相似
    • 10:不同


    十二、总结:imagehash 仍是图像相似性计算中最值得使用的工具

    即使在深度学习时代,imagehash 仍然是工程中最常用的图像相似工具之一,因为它:

    • 速度快
    • 精度稳定
    • 轻量级
    • 部署简单
    • 跨领域通用

    适合作为图像比对的第一道过滤器,再结合深度学习做更高精度分析。


    赞(0)
    未经允许不得转载:171主机测评 » Python 图像哈希库 imagehash——从原理到实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址