類似圖片搜索的原理

Google把"類似圖片搜索"正式放上了首頁。php

你能夠用一張圖片,搜索互聯網上全部與它類似的圖片。點擊搜索框中照相機的圖標。html

一個對話框會出現。python

你輸入網片的網址,或者直接上傳圖片,Google就會找出與其類似的圖片。下面這張圖片是美國女演員Alyson Hannigan。算法

上傳後,Google返回以下結果:ide

相似的"類似圖片搜索引擎"還有很多,TinEye甚至能夠找出照片的拍攝背景。網站

==========================================================搜索引擎

這種技術的原理是什麼?計算機怎麼知道兩張圖片類似呢?google

根據Neal Krawetz博士的解釋,原理很是簡單易懂。咱們能夠用一個快速算法,就達到基本的效果。orm

這裏的關鍵技術叫作"感知哈希算法"(Perceptual hash algorithm),它的做用是對每張圖片生成一個"指紋"(fingerprint)字符串,而後比較不一樣圖片的指紋。結果越接近,就說明圖片越類似。htm

下面是一個最簡單的實現:

第一步,縮小尺寸。

將圖片縮小到8x8的尺寸,總共64個像素。這一步的做用是去除圖片的細節,只保留結構、明暗等基本信息,摒棄不一樣尺寸、比例帶來的圖片差別。

 

第二步,簡化色彩。

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

第三步,計算平均值。

計算全部64個像素的灰度平均值。

第四步,比較像素的灰度。

將每一個像素的灰度,與平均值進行比較。大於或等於平均值,記爲1;小於平均值,記爲0。

第五步,計算哈希值。

將上一步的比較結果,組合在一塊兒,就構成了一個64位的整數,這就是這張圖片的指紋。組合的次序並不重要,只要保證全部圖片都採用一樣次序就好了。

 =  = 8f373714acfcf4d0

獲得指紋之後,就能夠對比不一樣的圖片,看看64位中有多少位是不同的。在理論上,這等同於計算"漢明距離"(Hamming distance)。若是不相同的數據位不超過5,就說明兩張圖片很類似;若是大於10,就說明這是兩張不一樣的圖片。

具體的代碼實現,能夠參見Wote用python語言寫的imgHash.py。代碼很短,只有53行。使用的時候,第一個參數是基準圖片,第二個參數是用來比較的其餘圖片所在的目錄,返回結果是兩張圖片之間不相同的數據位數量(漢明距離)。

這種算法的優勢是簡單快速,不受圖片大小縮放的影響,缺點是圖片的內容不能變動。若是在圖片上加幾個文字,它就認不出來了。因此,它的最佳用途是根據縮略圖,找出原圖。

實際應用中,每每採用更強大的pHash算法和SIFT算法,它們可以識別圖片的變形。只要變形程度不超過25%,它們就能匹配原圖。這些算法雖然更復雜,可是原理與上面的簡便算法是同樣的,就是先將圖片轉化成Hash字符串,而後再進行比較。

           

isnowfy的網站看到,還有其餘兩種方法也很簡單,這裏作一些筆記。

1、顏色分佈法

每張圖片均可以生成顏色分佈的直方圖(color histogram)。若是兩張圖片的直方圖很接近,就能夠認爲它們很類似。

任何一種顏色都是由紅綠藍三原色(RGB)構成的,因此上圖共有4張直方圖(三原色直方圖 + 最後合成的直方圖)。

若是每種原色均可以取256個值,那麼整個顏色空間共有1600萬種顏色(256的三次方)。針對這1600萬種顏色比較直方圖,計算量實在太大了,所以須要採用簡化方法。能夠將0~255分紅四個區:0~63爲第0區,64~127爲第1區,128~191爲第2區,192~255爲第3區。這意味着紅綠藍分別有4個區,總共能夠構成64種組合(4的3次方)。

任何一種顏色必然屬於這64種組合中的一種,這樣就能夠統計每一種組合包含的像素數量。

上圖是某張圖片的顏色分佈表,將表中最後一欄提取出來,組成一個64維向量(7414, 230, 0, 0, 8, ..., 109, 0, 0, 3415, 53929)。這個向量就是這張圖片的特徵值或者叫"指紋"。

因而,尋找類似圖片就變成了找出與其最類似的向量。這能夠用皮爾遜相關係數或者餘弦類似度算出。

2、內容特徵法

除了顏色構成,還能夠從比較圖片內容的類似性入手。

首先,將原圖轉成一張較小的灰度圖片,假定爲50x50像素。而後,肯定一個閾值,將灰度圖片轉成黑白圖片。

  

若是兩張圖片很類似,它們的黑白輪廓應該是相近的。因而,問題就變成了,第一步如何肯定一個合理的閾值,正確呈現照片中的輪廓?

顯然,前景色與背景色反差越大,輪廓就越明顯。這意味着,若是咱們找到一個值,可使得前景色和背景色各自的"類內差別最小"(minimizing the intra-class variance),或者"類間差別最大"(maximizing the inter-class variance),那麼這個值就是理想的閾值。

1979年,日本學者大津展之證實了,"類內差別最小"與"類間差別最大"是同一件事,即對應同一個閾值。他提出一種簡單的算法,能夠求出這個閾值,這被稱爲"大津法"(Otsu's method)。下面就是他的計算方法。

假定一張圖片共有n個像素,其中灰度值小於閾值的像素爲 n1 個,大於等於閾值的像素爲 n2 個( n1 + n2 = n )。w1 和 w2 表示這兩種像素各自的比重。

  w1 = n1 / n

  w2 = n2 / n

再假定,全部灰度值小於閾值的像素的平均值和方差分別爲 μ1 和 σ1,全部灰度值大於等於閾值的像素的平均值和方差分別爲 μ2 和 σ2。因而,能夠獲得

  類內差別 = w1(σ1的平方) + w2(σ2的平方)

  類間差別 = w1w2(μ1-μ2)^2

能夠證實,這兩個式子是等價的:獲得"類內差別"的最小值,等同於獲得"類間差別"的最大值。不過,從計算難度看,後者的計算要容易一些。

下一步用"窮舉法",將閾值從灰度的最低值到最高值,依次取一遍,分別代入上面的算式。使得"類內差別最小"或"類間差別最大"的那個值,就是最終的閾值。具體的實例和Java算法,請看這裏

有了50x50像素的黑白縮略圖,就等於有了一個50x50的0-1矩陣。矩陣的每一個值對應原圖的一個像素,0表示黑色,1表示白色。這個矩陣就是一張圖片的特徵矩陣。

兩個特徵矩陣的不一樣之處越少,就表明兩張圖片越類似。這能夠用"異或運算"實現(即兩個值之中只有一個爲1,則運算結果爲1,不然運算結果爲0)。對不一樣圖片的特徵矩陣進行"異或運算",結果中的1越少,就是越類似的圖片。

相關文章
相關標籤/搜索