【重複圖識別】在茫茫圖海中,怎麼找到相同的它?

背景

在一些圖像相關的項目中,重複圖識別是很重要的。就好比熱圖排行榜(須要識別出重複圖);涉及圖像深度學習的項目(訓練數據須要剔除重複圖);圖片原創&視頻原創(須要識別出重複圖)等等。html

什麼是相同圖片

什麼是相同圖片?相信在不一樣場景下,這個答案是不同。有些場景把肉眼看起來同樣的圖片看成相同圖片,有些場景把用濾鏡處理過的圖片也看成相同圖片,而有些場景下只把原圖看成相同圖片。
這裏按照相同程度劃分,相同程度從高到低,其實能夠分爲3個等級:python

  • 絕對原圖
  • 肉眼相同
  • 抄襲原圖

接下來咱們逐一詳細介紹下這3類。算法

絕對原圖

這個等級,圖片相同的程度是最高的,就以下面2張圖片,1.png經過直接copy的方式產生的2.png
學習

它們從圖片內容已經沒法判斷是不是原圖,只能從文件的角度識別,通常來講都是直接md5判斷2個圖片,以下所示:
3d

它屬於用圖片文件進行hash處理。code

PS:通常來講,全部場景都會先用md5來過濾一邊,由於它算法複雜度很低,根本不用理解圖片視頻

肉眼相同

這個等級的場景最多,好比圖片訓練數據去重,熱圖排行榜等等。
就以下圖所示,1.png通過壓縮、resize、轉碼等圖片處理的方式產生的3.jpg:
htm

它們肉眼看起來是相同,可是絕對不是原圖,md5沒法識別這種狀況,只能圖像的感知hash處理。感知hash主要有3種(AHash、DHash、PHash),它們都是用圖片內容進行hash處理,只是hash方式不一樣,下面逐一介紹一波:blog

AHash

這種感知hash最簡單,算法複雜度也最低,它只須要處理2步 預處理 + 二值化遊戲

  • 具體流程圖以下所示:

它的二值化方式比較簡單,只是比較了像素點跟均值,因此效果通常般。

  • python源碼以下:
def ahash(image, hash_size=8):
     image = image.convert("L").resize((hash_size, hash_size), Image.ANTIALIAS)// 一、【預處理】轉灰度圖,resize
     pixels = numpy.asarray(image)
     avg = np.mean(pixels)//二、計算均值,這裏也能夠用中值
     diff = pixels > avg // 三、【二值化】大於均值爲1,小於等於均值爲0
     return diff

DHash

這種感知hash的複雜度也很低,重點是它比AHash的效果好,主要緣由它二值化方式考慮上了相鄰像素的差值,算法更加魯棒。(固然這只是一種思想,咱們也能夠比較固定的2個像素點的大小,每一個像素點都有一個與之對應的像素點)。
算法流程圖以下(跟AHash差很少,差異在於二值化方式不同):

  • python源碼以下:
def dhash(image, hash_size=8):
     image = image.convert("L").resize((hash_size + 1, hash_size), Image.ANTIALIAS)// 一、【預處理】轉灰度圖,resize
     pixels = numpy.asarray(image)
     diff = pixels[:, 1:] > pixels[:, :-1] //二、【二值化】相鄰2個元素對比,右邊大於左邊爲1,右邊小於等於左邊爲0。(也能夠改爲上下2個元素的對比,或者固定2個元素之間的對比)
     return diff

Phash

Phash是目前效果最好,它引入了DCT變換,去除圖片中的高頻信息,把注意力集中在低頻信息中,這是因爲人眼對於細節信息不是很敏感。具體算法原理見下一篇
phash有不少種改版,下面只給出效果最好的一種,它的算法流程圖以下:

  • python 源碼以下:
def phash(image, hash_size=8, highfreq_factor=4):
     import scipy.fftpack
     img_size = hash_size * highfreq_factor
     image = image.convert("L").resize((img_size, img_size), Image.ANTIALIAS)// 一、【預處理】轉灰度圖,resize
     pixels = numpy.asarray(image)
     dct = scipy.fftpack.dct(scipy.fftpack.dct(pixels, axis=0), axis=1) //DCT變換
     dctlowfreq = dct[:hash_size, :hash_size] //二、只留下直流&&低頻變量
     med = numpy.median(dctlowfreq) //取中值
     diff = dctlowfreq > med //三、【二值化】大於中值爲1,小於等於中值爲0
     return diff

抄襲原圖

這種場景也挺多的,並且其中每一個場景都有本身獨特的要求。就好比一個視頻平臺,它的視頻原創項目,把加濾鏡、換音頻、裁剪等方式也斷定爲相同圖片的話,感知hash已經不適用,必須用上圖像深度學習了。
通常來講也不須要很強的模型,可是必須針對性的訓練特定場景,就好比濾鏡,logo,黑邊等場景。
濾鏡就以下圖所示,1.png通過一個濾鏡產生了4.png:

還有一種場景是遊戲領域的視頻去重,因爲遊戲背景都同樣,只有小小的一塊人物或者名字不一樣,也是須要針對性的加數據訓練的。

這裏的話,深度學習 MoCo 可能會合適一些。

總結

重複圖在圖像相關的項目中基本都會用到,不一樣的場景用不一樣的算法。

複雜度 適用場景
MD5 超級低 絕對原圖
感知Hash 肉眼相同
深度學習 特定場景相同
相關文章
相關標籤/搜索