CV筆記11:HOG特徵


一、寫在前面

圖像描述子,簡單來說就是包含了一張圖像主要信息的數據集,它是對圖像的簡化表示,僅僅含有了圖像的重要信息。就如對一篇繁長的文章做了一次簡寫或概述一樣。專業一點,圖像描述子,也就是我們常提到的“提取圖像特徵”中的圖像特徵,這些特徵能夠更好地讓機器理解圖象,直白地說就是該特徵能夠更好的讓決策模性進行分類等決策。圖像描述子可以分爲人工設計的特徵和模性學習到的特徵。在本篇中主要講講人工設計的HOG圖像描述子,重點放在描述子的求解和原理上面,而實現都可以通過opencv等工具包直接實現。

二、HOG(Histogram of Oriented Gradient)特徵

Hog特徵,中文就是帶方向的梯度直方圖,是通過計算圖像中某一區域的不同梯度方向上的梯度幅值的累加而得到的直方圖(當然還有其他的求解方式)。

2.1 Hog特徵的求取步驟

  • 圖像預處理
  • 計算每個像素的梯度(幅值M和方向)
  • 將圖像分成小的cells(如8×8的cells)
  • 統計每個cell的方向梯度直方圖,每個cell得到一個使用直方圖向量描述圖像的特徵(描述子)
  • 將每n×n個cell組成一個block,讓每個cell的描述子拼接起來,得到該block的描述子
  • 將每一個block的描述子拼接起來,並進行歸一化,便得到了整個圖像的描述子

我們可以根據以上的流程,先放一個圖片進行理解一下,這個圖還會在下面過程詳細介紹。
在這裏插入圖片描述

2.2.1 圖像預處理

圖像預處理一般包括圖形的灰度化、伽馬矯正(伽馬歸一化)、降噪、resize等操作。灰度化就是將圖像轉化爲灰度圖像以方便計算圖像梯度,其實彩色圖像也可以直接處理,不過是分別對三個通道的顏色值進行梯度計算,最後選擇最大的梯度。伽馬矯正是爲了減少光照對圖像的影響。
除了上面的操作,我們還一般還會對圖像的輸入尺寸做限定。根據《圖像學習-HOG特徵》一文中,在計算Hog特徵時,輸入圖像可以爲一張圖像的一個區塊(Patch),也可以是一整張圖像。下面都以一個Patch爲輸入圖像。Patch可以是任意的尺寸,但是有一個固定的比列,比如當patch寬高比1:2,那patch大小可以是100×200, 128×256或者1000×2000但不可以是101×205。比如,我們設定Patch寬高比設置爲1:2,這時輸入圖像大小最好是64×128,這是因爲我們可以將輸入圖像分成8×8和16×16的cell來提取特徵,在具有指定的大小(64×128)的情況下將使我們的所有計算相當簡單,同時多個cell又可以組成block。當然,圖像的Patch、cell和block可以根據自己的需求自行定義,在原始論文中使用的Patch寬高比爲1:2,cell爲8×8。
具體講講Gamma變換:
伽馬矯正,調節圖像對比度,減少光照對圖像的影響(包括光照不均和局部陰影),使過曝或者欠曝的圖像恢復正常,更接近人眼看到的圖像。
伽馬矯正公式:

f(I)=Iγf(I)=I^\gamma

II表示圖像,γ\gamma表示冪指數。

如圖,當γ\gamma取不同的值時對應的輸入輸出曲線( γ=1\gamma=1時輸入輸出保持一致) :
1) 當γ<1\gamma<1時,輸入圖像的低灰度值區域動態範圍變大,進而圖像低灰度值區域對比度得以增強;在高灰度值區域,動態範圍變小,進而圖像高灰度值區域對比度得以降低。 最終,圖像整體的灰度變亮。

2) 當γ>1\gamma>1時,輸入圖像的高灰度值區域動態範圍變小,進而圖像低灰度值區域對比度得以降低;在高灰度值區域,動態範圍變大,進而圖像高灰度值區域對比度得以增強。 最終,圖像整體的灰度變暗。
在這裏插入圖片描述

2.2.2 計算每個像素梯度和方向

爲了方便得到梯度直方圖,我們預先計算每個像素的梯度(幅值M和方向)。一般使用特定的卷積覈對圖像濾波實現,可選用的卷積模板有:soble算子、Prewitt算子、Roberts模板等等。具體的梯度計算講解可以參照文章《CV筆記6:圖像邊緣檢測之一階微分算子、二階微分算子、Canny邊緣檢測(基於python-opencv實現)》的第二節。

2.2.3 將圖像分割成小的區域

在實際應用中,我們一般不會直接對一張大幅圖像做特徵提取,而是把圖像分割成很多區塊,然後對每個區塊計算HOG特徵,這樣做將能夠將圖像幾何(位置)特性包含進去。這是因爲只有圖像區域比較小的情況,基於統計原理的直方圖對於該區域纔有表達能力,如果圖像區域比較大,那麼兩個完全不同的圖像的HOG特徵,也可能很相似。但是如果區域較小,這種可能性就很小。圖像的分割方式一般來說有overlap(右圖)和non-overlap(左圖)兩種,如下圖所示。overlap指的是分割出的區塊(patch)互相交疊,有重合的區域。non-overlap指的是區塊不交疊,沒有重合的區域。
在這裏插入圖片描述
對於overlap,這種分割方式可以防止對一些物體的切割,以眼睛爲例,如果分割的時候正好把眼睛從中間切割並且分到了兩個patch中,提取完HOG特徵之後,將會影響之後的分類效果,但是如果兩個patch之間overlap,那麼至少在一個patch會有完整的眼睛。overlap的缺點是計算量大,因爲重疊區域的像素需要重複計算。
對於non-overlap,缺點就是上面提到的,有時會將一個連續的物體切割開,得到不太“好”的HOG特徵,優點是計算量小,尤其是與Pyramid(金字塔)結合時,這個優點更爲明顯。

2.2.4 計算區塊的方向梯度直方圖

經過計算,對於每一個像素點都會得到兩個值:梯度幅值/梯度方向。在這一步中,我們假設輸入的patch被分成若干個8×8的cell,例如我們的patch爲64x128的大小,那麼這幅圖像就被劃分爲8x16個8x8的cell單元,併爲每個8×8的cell計算梯度直方圖。當然,cell的劃分也可以是其他值:16x16,8x16等,根據具體的場景確定。
以8x8的cell爲例,一個8x8的cell包含了8x8x2 = 128個值,因爲每個像素包括梯度的大小和方向。
在HOG中,每個8x8的cell的梯度直方圖本質是一個由9個數值組成的向量, 對應於0、20、40、60…160的梯度方向(角度)。那麼原本cell中8x8x2 = 128個值就由長度爲9的向量來表示,用這種梯度直方圖的表示方法,大大降低了計算量,同時又對光照等環境變化更加地魯棒。

首先,看下圖:
在這裏插入圖片描述

左圖是衣服64x128的圖像,被劃分爲8x16個8x8的cell;中間的圖像表示一個cell中的梯度矢量,箭頭朝向代表梯度方向,箭頭長度代表梯度大小。

右圖是 8×8 的cell中表示梯度的原始數值,注意角度的範圍介於0到180度之間,而不是0到360度, 這被稱爲“無符號”梯度,因爲兩個完全相反的方向被認爲是相同的。

接下來,我們來計算cell中像素的梯度直方圖,將0-180度分成9等份,稱爲9個bins,分別是0,20,40…160。然後對每個bin中梯度的貢獻進行統計:

在這裏插入圖片描述

統計方法是一種加權投票統計, 如上圖所示,某像素的梯度幅值爲13.6,方向爲36,36度兩側的角度bin分別爲20度和40度,那麼就按一定加權比例分別在20度和40度對應的bin加上梯度值,加權公式爲:

20度對應的bin:((40-36)/20) * 13.6,分母的20表示20等份,而不是20度;
40度對應的bin:((36-20)/20) * 13.6,分母的20表示20等份,而不是20度;

還有一個細節需要注意,如果某個像素的梯度角度大於160度,也就是在160度到180度之間,那麼把這個像素對應的梯度值按比例分給0度和160度對應的bin。如左下圖綠色圓圈中的角度爲165度,幅值爲85,則按照同樣的加權方式將85分別加到0度和160度對應的bin中。

在這裏插入圖片描述

對整個cell進行投票統計,正是在HOG特徵描述子中創建直方圖的方式,最終得到由9個數值組成的向量—梯度方向圖:

在這裏插入圖片描述

2.2.5 Block 歸一化

HOG特徵將8×8的一個局部區域作爲一個cell,再以2×2個cell作爲一組,稱爲一個block,也就是說一個block表示16x16的區域。

我們可能會想,爲什麼又需要分block呢?

這是因爲,雖然我們已經爲圖像的8×8單元創建了HOG特徵,但是圖像的梯度對整體光照很敏感。這意味着對於特定的圖像,圖像的某些部分與其他部分相比會非常明亮。

我們不能從圖像中完全消除這個。但是我們可以通過使用16×16個塊來對梯度進行歸一化來減少這種光照變化。

由於每個cell有9個值,一個block(2×2個cell)則有36個值,HOG是通過滑動窗口的方式來得到block的,如下圖所示:
在這裏插入圖片描述

前面已經說明,歸一化的目的是爲了降低光照的影響,因爲梯度對整體光照非常敏感,比如通過將所有像素值除以2來使圖像變暗,那麼梯度幅值將減小一半,因此直方圖中的值也將減小一半,我們就需要將直方圖“歸一化”。

歸一化的方法有很多:L1-norm、L2-norm、max/min等等,一般選擇L2-norm。

例如對於一個[128,64,32]的三維向量來說,模長是1282+642+322=146.64\sqrt{128^2+64^2+32^2}=146.64,這叫做向量的L2範數。將這個向量的每個元素除以146.64就得到了歸一化向量 [0.87, 0.43, 0.22]。

採用同樣的方法,一個cell有一個梯度方向直方圖,包含9個數值,一個block有4個cell,那麼一個block就有4個梯度方向直方圖,將這4個直方圖拼接成長度爲36的向量,然後對這個向量進行歸一化。

而每一個block將按照上圖滑動的方式進行重複計算,直到整個圖像的block都計算完成。

2.2.6 獲得HOG描述子

每一個16 * 16大小的block將會得到一個長度爲36的特徵向量,並進行歸一化。 那會得到多少個特徵向量呢?

例如,對於上圖被劃分8 * 16個cell ,每個block有2x2個cell的話,那麼cell的個數爲:(16-1)x(8-1)=105。即有7個水平block和15個豎直block。

每個block有36個值,整合所有block的特徵值,最終獲得由36 * 105=3780個特徵值組成的特徵描述符,而這個特徵描述符是一個一維的向量,長度爲3780。

獲得HOG特徵向量,就可以用來可視化和分類了。

三、opencv之HOG API

OpenCV中的HOG特徵提取功能使用了HOGDescriptor這個類來進行封裝,其中也有現成的行人檢測的接口。
先看看HOGDescriptor所在的頭文件,瞭解它的構造函數需要哪些參數。

    CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8),
    	cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1),
        histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true), 
        nlevels(HOGDescriptor::DEFAULT_NLEVELS)
    {}
CV_WRAP HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride,  
              Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1,  
              int _histogramNormType=HOGDescriptor::L2Hys,  
              double _L2HysThreshold=0.2, bool _gammaCorrection=false,  
              int _nlevels=HOGDescriptor::DEFAULT_NLEVELS)  
: winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize),  
nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma),  
histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold),  
gammaCorrection(_gammaCorrection), nlevels(_nlevels)  
{}  
CV_WRAP HOGDescriptor(const String& filename)  
{  
    load(filename);  
}  
HOGDescriptor(const HOGDescriptor& d)  
{  
    d.copyTo(*this);  
}  

我們看到HOGDescriptor一共有4個構造函數,前三個有CV_WRAP前綴,表示它們是從DLL裏導出的函數,即我們在程序當中可以調用的函數;最後一個沒有上述的前綴,所以我們暫時用不到,它其實就是一個拷貝構造函數。
下面我們就把注意力放在前面的構造函數的參數上面吧,這裏有幾個重要的參數要研究下:winSize(64,128), blockSize(16,16), blockStride(8,8), cellSize(8,8), nbins(9)。上面這些都是HOGDescriptor的成員變量,括號裏的數值是它們的默認值,它們反應了HOG描述子的參數。這裏做了幾個示意圖來表示它們的含義。
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

參考

OpenCV HOGDescriptor 參數圖解
圖像學習-HOG特徵
Histogram of Oriented Gridients(HOG) 方向梯度直方圖
圖像特徵工程:HOG特徵描述子介紹
HOG特徵

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章