圖片相似度計算

以下摘自百度百科:

DHA是一類比較哈希方法的統稱。圖片所包含的特徵被用來生成一組指紋(不過它不是唯一的),而這些指紋是可以進行比較的。

下面是簡單的步驟,來說明對圖像進行DHA的運算過程[1] :

第一步,縮小圖片。

最快速的去除高頻和細節,只保留結構明暗的方法就是縮小尺寸。

將圖片縮小到9x8的尺寸,總共72個像素。摒棄不同尺寸、比例帶來的圖片差異。

第二步,簡化色彩。

將縮小後的圖片,轉為64級灰度。也就是說,所有像素點總共只有64種顏色。

第三步,計算差異值。

對矩陣的每一行進行如下操作:相鄰的兩個元素進行相減(左邊元素減右邊元素),得出8個不同的差異值,這樣總共得到64個差異值。

第四步,對差異值進行處理,若為正數或0,則記得為1;若為負數,記為0。

第五步,將64個結果結合在一起就得到一個哈希值(每張圖像的64個值組合順序要一致),這就是圖像的「指紋」。

相比PHA,DHA的速度要快的多,相比AHA,DHA在效率幾乎相同的情況下的效果要更好,因為DHA是基於漸變實現的。

在國內找到的一篇文章感知哈希演算法之dHash的Python實現,通過Python列表的方式來實現的,效率較慢。後來在github上找到了通過numpy實現的輪子imagehash,這個輪子又是基於python-pillow/Pillow實現的,所以又去研究了pillow的源碼。最後結合國內文章、imagehash及pillow,做了一些改進和取捨,實現圖片相似度計算腳本如下:

# -*- coding: utf-8 -*-"""Created on Mon Mar 26 15:19:12 2018@author: Administrator"""import numpy as npfrom PIL import Imageimport repattern = re.compile(".(png|jpg|jpeg|bmp|gif$)")def is_image(filename): return filename.endswith((".png", ".jpg", ".jpeg", ".bmp", ".gif"))def d_hash(image, hash_size=8): if hash_size < 2: raise ValueError("Hash size must be greater than or equal to 2") pixels = np.asarray(image.resize((hash_size+1, hash_size)).convert("L")) # compute differences between columns diff = pixels[:, 1:] > pixels[:, :-1] return diff# 沒有endswith方法快def is_image_re(filename, pattern): return re.search(pattern, filename)# 沒有.convert("L")方法快def convert_L(mat): return mat[:,:,0] * 299 / 1000 + mat[:,:,1] * 587 / 1000 + mat[:,:,2] * 114 / 1000

推薦閱讀:

Leetcode每天兩題11-第27題和第28題
Leetcode之旅|還原二叉樹
時間複雜度和空間複雜度
刷題的日常Day1--重建二叉樹
Leetcode每天兩題4-第2題和第445題

TAG:演算法與數據結構 |