一、圖片相似度檢測算法原理
我們日常中處理的數據大多數是文本和圖片,既然文本有文本相似度,圖片肯定也有圖片相似度呀,是不是。下面介紹圖片相似度檢測的算法:檢查兩個圖片的相似度,一個簡單而快速的算法:感知哈希算法(Perceptual Hash),通過某種提取特徵的方式爲每個圖片計算一個指紋(哈希),這樣對比兩個圖片相似與否就變成了對比兩個指紋異同的問題。
二、應用
- 相似圖片搜索
- 圖片相似度比較
- 百度識圖
- 圖片比較
三、實現步驟和思路
Step1.縮小尺寸
將圖片縮小到8*8的大小,這樣做可以去除圖片的細節,只保留結構和明暗等基本信息,同時摒棄不同尺寸和比例帶來的圖片差異。
Step2.灰度處理
把縮小後的圖片轉化爲64級灰度圖(每個像素只有64種顏色)。
Step3.計算平均值
計算所有64個像素的灰度平均值。
Step4.計算哈希
這裏哈希的計算方法是:上面說的64個像素的灰度與平均值進行比較,大於或等於平均值記爲1,小於記爲0。
將每個像素的比較結果組合在一起成爲一個64位的二進制整數,這個整數就是此圖片的指紋。
Step5.對比哈希
不同圖片對比的方法,就是對比它們的64位哈希中,有多少位不一樣(漢明距離)。一般來說如果不同的位數不超過5,就說明兩張圖片很相似,如果大於10,就很可能是兩張不同的圖片。
# -*- coding:utf-8 -*-
from functools import reduce
from PIL import Image
# 計算圖片的局部哈希值--pHash
def phash(img):
"""
:param img: 圖片
:return: 返回圖片的局部hash值
"""
img = img.resize((8, 8), Image.ANTIALIAS).convert('L')
avg = reduce(lambda x, y: x + y, img.getdata()) / 64.
hash_value=reduce(lambda x, y: x | (y[1] << y[0]), enumerate(map(lambda i: 0 if i < avg else 1, img.getdata())), 0)
print(hash_value)
return hash_value
# 計算漢明距離:
def hamming_distance(a, b):
"""
:param a: 圖片1的hash值
:param b: 圖片2的hash值
:return: 返回兩個圖片hash值的漢明距離
"""
hm_distance=bin(a ^ b).count('1')
print(hm_distance)
return hm_distance
# 計算兩個圖片是否相似:
def is_imgs_similar(img1,img2):
"""
:param img1: 圖片1
:param img2: 圖片2
:return: True 圖片相似 False 圖片不相似
"""
return True if hamming_distance(phash(img1),phash(img2)) <= 5 else False
if __name__ == '__main__':
# 讀取圖片
sensitive_pic = Image.open("3.jpg")
target_pic = Image.open("4.jpg")
# 比較圖片相似度
result=is_imgs_similar(target_pic, sensitive_pic)
print(result)
兩張不同的圖片3和4運行結果:
15824809348783249859
18411139146200482779
24
False
Process finished with exit code 0
兩張一樣的圖片1和2運行結果:
14384397865107178495
14384397865107178495
0
True
Process finished with exit code 0