首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python 實作感知哈希(dHash)偵測重複圖片

     編輯:更多程式設計知識

傳統加密雜湊(MD5、SHA)對微小像素變化極敏感,無法識別視覺相似圖片。本文介紹差異哈希(dHash)演算法,透過比較鄰近像素亮度梯度,產生具容錯力的圖片指紋。

dHash 四步驟

  1. 灰階化:將 RGB 三通道轉為單通道亮度值(0-255)。
  2. 縮放:重設為 9×8 像素(寬比高多 1),捨棄高頻細節。
  3. 比較鄰近像素:每列 9 個像素產生 8 個布林值(左大於右為 True)。共 8 列 × 8 = 64 bits。
  4. 轉十六進位:每 8 bits 組成一 byte,輸出 16 字元 hex 字串。

Python 完整實作

from PIL import Image

def dhash(image, hash_size=8):
    # 灰階 + 縮放
    image = image.convert('L').resize((hash_size + 1, hash_size), Image.ANTIALIAS)
    pixels = list(image.getdata())

    # 比較鄰近像素
    diff = []
    for row in range(hash_size):
        for col in range(hash_size):
            left = image.getpixel((col, row))
            right = image.getpixel((col + 1, row))
            diff.append(left > right)

    # 轉 hex
    hex_str = []
    dec_val = 0
    for idx, val in enumerate(diff):
        if val:
            dec_val += 2 ** (idx % 8)
        if (idx % 8) == 7:
            hex_str.append(hex(dec_val)[2:].rjust(2, '0'))
            dec_val = 0
    return ''.join(hex_str)

驗證效果

>>> orig = Image.open('cat_grumpy_orig.png')
>>> modif = Image.open('cat_grumpy_modif.png')  # 修改鼻子顏色
>>> dhash(orig)
'4c8e3366c275650f'
>>> dhash(modif)
'4c8e3366c275650f'
>>> dhash(orig) == dhash(modif)
True

輕微修改產生相同雜湊值,達到感知去重目的。

大量比對:漢明距離

當雜湊值不完全相同,計算漢明距離(不同 bit 數)判斷相似度:

def hamming_distance(h1, h2):
    return bin(int(h1, 16) ^ int(h2, 16)).count('1')

MySQL 可直接查詢:

SELECT pk, hash,
       BIT_COUNT(CONV(hash, 16, 10) ^ CONV('4c8e3366c275650f', 16, 10)) AS hamming_distance
FROM image_hashes
HAVING hamming_distance < 4
ORDER BY hamming_distance ASC;

應用場景

  • 圖床/素材站防盜圖、防重複上傳
  • 以圖搜圖、相似推薦系統
  • 內容審核輔助工具

dHash 演算法簡單高效,適合中小型圖片庫即時去重與相似度檢測。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved