背景
檢查兩個圖片的相似度,一個簡單而快速的演算法:感知雜湊演算法(Perceptual Hash),通過某種提取特徵的方式為每個圖片計算一個指紋(雜湊),這樣對比兩個圖片相似與否就變成了對比兩個指紋異同的問題。
實現
Step1.縮小尺寸
將圖片縮小到8*8的大小,這樣做可以去除圖片的細節,只保留結構和明暗等基本資訊,同時摒棄不同尺寸和比例帶來的圖片差異。
Step2.灰度處理
把縮小後的圖片轉化為64級灰度圖(每個畫素只有64種顏色)。
Step3.計算平均值
計算所有64個畫素的灰度平均值。
Step4.計算雜湊
這裡雜湊的計算方法是:上面說的64個畫素的灰度與平均值進行比較,大於或等於平均值記為1,小於記為0。
將每個畫素的比較結果組合在一起成為一個64位的二進位制整數,這個整數就是此圖片的指紋。
Step5.對比雜湊
不同圖片對比的方法,就是對比它們的64位雜湊中,有多少位不一樣(漢明距離)。一般來說如果不同的位數不超過5,就說明兩張圖片很相似,如果大於10,就很可能是兩張不同的圖片。
程式碼(Python)
計算pHash(只需要三行):
def phash(img):
img = img.resize((8, 8), Image.ANTIALIAS).convert('L')
avg = reduce(lambda x, y: x + y, img.getdata()) / 64.
return reduce(
lambda x, (y, z): x | (z << y),
enumerate(map(lambda i: 0 if i < avg else 1, img.getdata())),
0
)
複製程式碼
計算漢明距離:
def hamming_distance(a, b):
return bin(a^b).count('1')
複製程式碼
計算兩個圖片是否相似:
def is_imgs_similar(img1,img2):
return True if hamming_distance(phash(img1),phash(img2)) <= 5 else False
複製程式碼
其中計算部分用到了lambda表示式和reduce,可參考此文:廖雪峰:map和reduce