基于內(nèi)容的圖像檢索技術(shù)是采用某種算法來提取圖像中的特征,并將特征存儲起來,組成圖像特征數(shù)據(jù)庫。當需要檢索圖像時,采用相同的特征提取技術(shù)提取出待檢索圖像的特征,并根據(jù)某種相似性準則計算得到特征數(shù)據(jù)庫中圖像與待檢索圖像的相關(guān)度,最后通過由大到小排序,得到與待檢索圖像最相關(guān)的圖像,實現(xiàn)圖像檢索。圖像檢索的結(jié)果優(yōu)劣取決于圖像特征提取的好壞,在面對海量數(shù)據(jù)檢索環(huán)境中,我們還需要考慮到圖像比對(圖像相似性考量)的過程,采用高效的算法快速找到相似圖像也至關(guān)重要。
在構(gòu)建圖像特征庫的時候,通常不會使用原始的圖像特征,這是由于Raw Feature有很多冗余信息,而且維度過高在構(gòu)建特征數(shù)據(jù)庫和匹配的時候效率較低。所以,通常要對提取到的原始特征進行重新編碼。比較常用的三種編碼方式:
BoF , Bog of Feature 源于文本處理的詞袋模型(Bog,Bag of Words)
VLAD , Vector of Aggragate Locally Descriptor
FV , fisher vector
構(gòu)建圖像特征數(shù)據(jù)庫,通常有以下幾個步驟:
圖像預處理流程(增強,旋轉(zhuǎn),濾波,縮放等)
特征提?。ㄈ痔卣?,局部特征:SIFT,SURF,CNN等)
對每張圖片提取的原始特征重新編碼(BoF,VLAD,FV)形成圖像的特征庫
圖像的特征庫構(gòu)建完成后,在檢索階段,主要涉及到特征的相似性度量準則,排序,搜索
提取圖像的特征,
特征編碼
在圖像特征庫中進行檢索
返回相似性較高的結(jié)果
SIFT特征SIFT特征的講解已經(jīng)很多了,之前的博客也有過介紹。本文就借助vlfeat對SIFT特征的提取過程做一個總結(jié)。一個SIFT特征有兩部分組成:關(guān)鍵點(keypoint)和對應特征描述子(Descriptor)。使用SIFT detector 進行SIFT關(guān)鍵點的提取,然后使用SIFT descriptor計算關(guān)鍵點的描述子。也可以獨立的使用SIFT detector進行SIFT 關(guān)鍵點的提取,或者使用SIFT descriptor進行別的關(guān)鍵點描述子的計算。
一個SIFT keypoint是一塊圓形區(qū)域并且?guī)в蟹较?,使?個參數(shù)描述該區(qū)域的幾何結(jié)構(gòu):
keypoint的中心位置的坐標(x,y)
keypoint的scale(圓形區(qū)域的半徑r)
keypoint的方向(使用弧度表示的角度θ)
一個SIFT關(guān)鍵點由4個參數(shù)確定:
高斯尺度的組數(shù)o=log2min(m,n)?3=log2(512)?3=6
構(gòu)建第0組,將原圖像進行上采樣,寬和高增加一倍得到圖像I0。
第0層I0?G(x,y,σ0)
第1層I0?G(x,y,kσ0)
第2層I0?G(x,y,k2σ0)
構(gòu)建第1組,將I0進行降采樣,得到圖像I1
第0層I1?G(x,y,2σ0)
第1層I1?G(x,y,2kσ0)
第2層I1?G(x,y,2k2σ0)
...
構(gòu)建第o組,第s層 Io?G(x,y,2oksσ)
在Lowe的算法實現(xiàn)中\(zhòng)(\sigma_0 = 1.6,o_min = -1\)。\(o_min = -1\)表示金字塔的第0組是原圖像上采樣得到的,寬和高加一倍。
DoG 極值點檢測高斯圖像金字塔構(gòu)建完成后,將同一組的相鄰兩層相減就得到了\(DoG\)金字塔。
每組的層數(shù)\(S = 3\),也就是說每組可以得到兩層的\(DoG\)圖像,以第一組為例:其尺度為\(\sigma,k\sigma\),只有兩項是無法求取極值的,需要左右兩邊都有尺度。由于無法比較取得極值,那么我們就需要繼續(xù)對每組的圖像進行高斯模糊,使得尺度形成\(\sigma,k\sigma,k^2\sigma,k^3\sigma,k^4\sigma\)這樣就可以選擇中間的三項\(k\sigma,k^2\sigma,k^3\sigma\)
檢測關(guān)鍵點,就是在\(DoG\)的圖像空間中尋找極值點,每個像素點要和其圖像域(同一尺度空間)和尺度域(相鄰的尺度空間)的所有相鄰點進行比較,當其大于(或者小于)所有相鄰點時,改點就是極值點。如圖所示,中間的檢測點要和其所在圖像的\(3 \times 3\)鄰域8個像素點,以及其相鄰的上下兩層的\(3\times 3\)領域18個像素點,共26個像素點進行比較。
刪除不好的極值點
刪除兩類極值點
在對比度比較低低的區(qū)域檢測到的極值點
在圖像的邊緣部分檢測到的極值點
確定關(guān)鍵點的方向
統(tǒng)計關(guān)鍵點鄰域像素的梯度方向分布來確定關(guān)鍵點的方向。具體步驟如下:
計算以特征點為中心,以\(3 \times1.5 \sigma\)為半徑的區(qū)域圖像的幅角和幅值,每個像點\(L(x,y)\)的梯度的模\(m(x,y)\)以及方向\(\theta(x,y)\)可通過下面公式求得
統(tǒng)計像素點的幅角和幅值的直方圖,梯度方向的直方圖的橫軸是梯度方向的角度(梯度方向的范圍是0到360度,直方圖每36度一個柱共10個柱,或者沒45度一個柱共8個柱),縱軸是梯度方向?qū)荻确档睦奂?,在直方圖的峰值就是特征點的主方向。在梯度直方圖中,當存在一個相當于主峰值80%能量的柱值時,則可以將這個方向認為是該特征點輔助方向。所以,一個特征點可能檢測到多個方向(也可以理解為,一個特征點可能產(chǎn)生多個坐標、尺度相同,但是方向不同的特征點)。
得到特征點的主方向后,對于每個特征點可以得到三個信息\(k(x,y,r,\theta)\),即位置、尺度和方向。由此可以確定一個SIFT特征區(qū)域,一個SIFT特征區(qū)域由三個值表示,中心表示特征點位置,半徑表示關(guān)鍵點的尺度,箭頭表示主方向。具有多個方向的關(guān)鍵點可以被復制成多份,然后將方向值分別賦給復制后的特征點,一個特征點就產(chǎn)生了多個坐標、尺度相等,但是方向不同的特征點。
計算關(guān)鍵點描述子
在檢測部分已經(jīng)得到了SIFT關(guān)鍵點的位置,尺度和方向信息,生成關(guān)鍵點的描述子,就是使用一個向量來描述關(guān)鍵點及其鄰域像素的信息。由以下步驟生成描述子:
為了保證旋轉(zhuǎn)不變性,將關(guān)鍵點為中心的鄰域像素的坐標軸進行旋轉(zhuǎn),將\(x\)軸旋轉(zhuǎn)至關(guān)鍵點主方向,如下圖:
分塊計算鄰域內(nèi)像素的梯度方向直方圖,以關(guān)鍵點為中心的\(16\times16\)的區(qū)域內(nèi),劃分\(4\times4\)個塊,分別計算每個塊的梯度直方圖,如下圖:
每個塊的梯度直方方向直方圖的計算方式,和求關(guān)鍵點主方向時類似:此時每個區(qū)域的梯度直方圖在0-360之間劃分為8個方向區(qū)間,每個區(qū)間為45度,即每個種子點有8個方向的梯度強度信息,最后將得到的\(4\times4\times8=128\)維的特征向量。
為了去除光照變化的影響,需對上述生成的特征向量進行歸一化處理。在歸一化處理后,在128維的單位向量中,對大于0.2的要進行截斷處理,即大于0.2的值只取0.2,然后重新進行一次歸一化處理,其目的是為了提高鑒別性。0.2 是實驗得出的經(jīng)驗值。
vlfeat實現(xiàn)的sift特征提取vlfeat是一個開源的輕量級的計算機視覺庫,主要實現(xiàn)圖像局部特征的提取和匹配以及一些常用的聚類算法。其對sift特征提取的各個步驟進行了封裝,使用的方法如下:
1.調(diào)用vl_sift_new初始化VlSiftFilt,設置sift提取時參數(shù)信息,如:圖像的大小,Octave的個數(shù),每個Octave的中的層數(shù),起始的Octave的index. 各個參數(shù)的具體含義可以參考上面sift特征提取的方法。
2.設置剔除不穩(wěn)定關(guān)鍵點的閾值。在上面提到,sift在進行極值檢查后,要剔除兩類不穩(wěn)定的極值點:1.對比度較低區(qū)域的極值點;2.邊緣部分的極值點。 可以調(diào)用
vl_sift_set_peak_thresh設置接受極值點是一個關(guān)鍵點的最小對比度。 該值越小,提取到的關(guān)鍵點就越多。
y vl_sift_set_edge_thresh()設置一個極值點是在邊緣上的閾值。 該值越小,提取到的關(guān)鍵點就越多。
這兩個參數(shù)對最終提取到的特征點個數(shù)有很大的影響。
3.初始化工作完成后,可以循環(huán)的對尺度空間的每個Octave進行處理了
調(diào)用 vl_sift_process_first_octave()和vl_sift_process_next_octave()來計算下一個DoG尺度空間。
調(diào)用vl_sift_detect進行關(guān)鍵點提取
對每一個提取到的關(guān)鍵點
vl_sift_calc_keypoint_orientations計算關(guān)鍵點的方向,可能多于一個
l_sift_calc_keypoint_descriptor計算每個方向的特征描述子。
4.vl_sift_delete釋放資源。
具體代碼如下:
//?初始化 ????const?string?file?=?"../0.jpg"; ????Mat?img?=?imread(file,IMREAD_GRAYSCALE); ????Mat?color_img?=?imread(file); ????Mat?float_img; ????img.convertTo(float_img,CV_32F); ????int?rows?=?img.rows; ????int?cols?=?img.cols; ????VlSiftFilt*?vl_sift?=??vl_sift_new(cols,rows,4,3,0); ????vl_sift_set_peak_thresh(vl_sift,0.04); ????vl_sift_set_edge_thresh(vl_sift,10); ????vl_sift_pix?*data?=?(vl_sift_pix*)(float_img.data); ????vector?kpts; ????vector ?descriptors; ????vl_sift_extract(vl_sift,data,kpts,descriptors); ???? /* ????Extract?sift?using?vlfeat ????parameters: ????????vl_sfit,?VlSiftFilt*? ????????data?,?image?pixel?data?,to?be?convert?to?float ????????kpts,?keypoint?list ????????descriptors,?descriptor.?Need?to?free?the?memory?after?using. */ void?vl_sift_extract(VlSiftFilt?*vl_sift,?vl_sift_pix*?data, ????????????????????vector ?&kpts,vector ?&descriptors)?{ ???? ????//?Detect?keypoint?and?compute?descriptor?in?each?octave ????if(vl_sift_process_first_octave(vl_sift,data)?!=?VL_ERR_EOF){ ????????while(true){ ????????????vl_sift_detect(vl_sift); ????????????VlSiftKeypoint*?pKpts?=?vl_sift->keys; ????????????for(int?i?=?0;?i?nkeys;?i?++)?{ ????????????????double?angles[4]; ????????????????//?計算特征點的方向,包括主方向和輔方向,最多4個 ????????????????int?angleCount?=?vl_sift_calc_keypoint_orientations(vl_sift,angles,pKpts); ????????????????//?對于方向多于一個的特征點,每個方向分別計算特征描述符 ????????????????//?并且將特征點復制多個 ????????????????for(int?i?=?0?;?i? vlfeat中sift提取接受的是float類型的數(shù)據(jù),所以要先將讀到的數(shù)據(jù)圖像轉(zhuǎn)換為float。和OpenCV中的sift提取的對比結(jié)果如下:
vlfeat提取的特征點是用綠色畫出來的,共有1961個特征點。
OpenCV的是藍色,有4617個特征點。
Summary幾年前寫過一篇關(guān)于SIFT的文章,SIFT特征詳解 當時多是從理論上?,F(xiàn)在在做圖像檢索的時候,發(fā)現(xiàn)還是有很多東西理解的不是很清晰,比如:關(guān)鍵點的多個方向,不穩(wěn)定極值點的剔除以及梯度方向直方圖計算等等。
正在做一個圖像檢索的項目,陸續(xù)將項目的中學到一些知識總結(jié)下來,下一篇是關(guān)于均值聚類的,對提取到的圖像特征進行聚類生成視覺特征(Visul Feature)
到此這篇關(guān)于圖像檢索之基于vlfeat實現(xiàn)SIFT的文章就介紹到這了,更多相關(guān)圖像檢索vlfeat內(nèi)容請搜索好二三四以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好二三四!