圖像學(xué)習(xí)-HOG特征

好久沒寫東西了珠移,由于樓主換了個(gè)城市工作的畴,發(fā)現(xiàn)工作量蹭蹭的上來了,周末又喜歡出去覓食足淆,導(dǎo)致沒學(xué)習(xí)很久巢块,今天準(zhǔn)備水一篇來翻譯一下如何理解HOG(Histogram Of Gradient, 方向梯度直方圖)。本文主要翻譯了這篇文章巧号,也是我非常喜歡的博主之一(奈何他開的課程錯(cuò)過了T-T~~)族奢。

特征描述子(Feature Descriptor)

特征描述子就是圖像的表示,抽取了有用的信息丟掉了不相關(guān)的信息裂逐。通常特征描述子會(huì)把一個(gè)w*h*3(寬*高*3歹鱼,3個(gè)channel)的圖像轉(zhuǎn)換成一個(gè)長度為n的向量/矩陣。比如一副64*128*3的圖像卜高,經(jīng)過轉(zhuǎn)換后輸出的圖像向量長度可以是3780弥姻。

什么樣子的特征是有用的呢?假設(shè)我們想要預(yù)測(cè)一張圖片里面衣服上面的扣子掺涛,扣子通常是圓的庭敦,而且上面有幾個(gè)洞,那你就可以用邊緣檢測(cè)(edge detector)薪缆,把圖片變成只有邊緣的圖像秧廉,然后就可以很容易的分辨了,那么對(duì)于這張圖邊緣信息就是有用的拣帽,顏色信息就是沒有用的疼电。而且好的特征應(yīng)該能夠區(qū)分紐扣和其它圓形的東西的區(qū)別。

方向梯度直方圖(HOG)中减拭,梯度的方向分布被用作特征蔽豺。沿著一張圖片X和Y軸的方向上的梯度是很有用的,因?yàn)樵谶吘壓徒屈c(diǎn)的梯度值是很大的拧粪,我們知道邊緣和角點(diǎn)包含了很多物體的形狀信息修陡。

(HOG特征描述子可以不局限于一個(gè)長度的,也可以用很多其他的長度可霎,這里只記錄一種計(jì)算方法魄鸦。)

怎么計(jì)算方向梯度直方圖呢?

我們會(huì)先用圖像的一個(gè)patch來解釋癣朗。

第一步:預(yù)處理

Patch可以是任意的尺寸拾因,但是有一個(gè)固定的比列,比如當(dāng)patch長寬比1:2旷余,那patch大小可以是100*200, 128*256或者1000*2000但不可以是101*205盾致。

這里有張圖是720*475的,我們選100*200大小的patch來計(jì)算HOG特征荣暮,把這個(gè)patch從圖片里面摳出來庭惜,然后再把大小調(diào)整成64*128。

hog_preprocess

第二步:計(jì)算梯度圖像

首相我們計(jì)算水平和垂直方向的梯度穗酥,再來計(jì)算梯度的直方圖护赊。可以用下面的兩個(gè)kernel來計(jì)算砾跃,也可以直接用OpenCV里面的kernel大小為1的Sobel算子來計(jì)算骏啰。

horizontal_vertical_gradient_kernel

調(diào)用OpenCV代碼如下:

// C++ gradient calculation.
// Read image
Mat img = imread("bolt.png");
img.convertTo(img, CV_32F, 1/255.0);
 
// Calculate gradients gx, gy
Mat gx, gy; 
Sobel(img, gx, CV_32F, 1, 0, 1);
Sobel(img, gy, CV_32F, 0, 1, 1);
# Python gradient calculation 
 
# Read image
im = cv2.imread('bolt.png')
im = np.float32(im) / 255.0
 
# Calculate gradient 
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)

接著,用下面的公式來計(jì)算梯度的幅值g和方向theta:

gradient_direction_formula

可以用OpenCV的cartToPolar函數(shù)來計(jì)算:

// C++ Calculate gradient magnitude and direction (in degrees)
Mat mag, angle; 
cartToPolar(gx, gy, mag, angle, 1);
# Python Calculate gradient magnitude and direction ( in degrees ) 
mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)

計(jì)算得到的gradient圖如下:

左邊:x軸的梯度絕對(duì)值 中間:y軸的梯度絕對(duì)值 右邊:梯度幅值

從上面的圖像中可以看到x軸方向的梯度主要凸顯了垂直方向的線條抽高,y軸方向的梯度凸顯了水平方向的梯度判耕,梯度幅值凸顯了像素值有劇烈變化的地方。(注意:圖像的原點(diǎn)是圖片的左上角翘骂,x軸是水平的壁熄,y軸是垂直的)

圖像的梯度去掉了很多不必要的信息(比如不變的背景色)帚豪,加重了輪廓。換句話說草丧,你可以從梯度的圖像中還是可以輕而易舉的發(fā)現(xiàn)有個(gè)人狸臣。

在每個(gè)像素點(diǎn),都有一個(gè)幅值(magnitude)和方向昌执,對(duì)于有顏色的圖片烛亦,會(huì)在三個(gè)channel上都計(jì)算梯度。那么相應(yīng)的幅值就是三個(gè)channel上最大的幅值懂拾,角度(方向)是最大幅值所對(duì)應(yīng)的角煤禽。

第三步:在8*8的網(wǎng)格中計(jì)算梯度直方圖

在這一步,上面的patch圖像會(huì)被分割成8*8大小的網(wǎng)格(如下圖)岖赋,每個(gè)網(wǎng)格都會(huì)計(jì)算一個(gè)梯度直方圖檬果。那為什么要分成8*8的呢?用特征描述子的一個(gè)主要原因是它提供了一個(gè)緊湊(compact)/壓縮的表示贾节。一個(gè)8*8的圖像有8*8*3=192個(gè)像素值汁汗,每個(gè)像素有兩個(gè)值(幅值magnitude和方向direction,三個(gè)channel取最大magnitude那個(gè))栗涂,加起來就是8*8*2=128知牌,后面我們會(huì)看到這128個(gè)數(shù)如何用一個(gè)9個(gè)bin的直方圖來表示成9個(gè)數(shù)的數(shù)組。不僅僅是可以有緊湊的表示斤程,用直方圖來表示一個(gè)patch也可以更加抗噪角寸,一個(gè)gradient可能會(huì)有噪音,但是用直方圖來表示后就不會(huì)對(duì)噪音那么敏感了忿墅。

這個(gè)patch的大小是64*128,分割成8*8的cell扁藕,那么一共有64/8 * 128/8 = 8*16=128個(gè)網(wǎng)格

對(duì)于64*128的這幅patch來說,8*8的網(wǎng)格已經(jīng)足夠大來表示有趣的特征比如臉疚脐,頭等等亿柑。
直方圖是有9個(gè)bin的向量,代表的是角度0,20,40,60.....160棍弄。

我們先來看看每個(gè)8*8的cell的梯度都是什么樣子:

中間: 一個(gè)網(wǎng)格用箭頭表示梯度 右邊: 這個(gè)網(wǎng)格用數(shù)字表示的梯度

中間這個(gè)圖的箭頭是梯度的方向望薄,長度是梯度的大小,可以發(fā)現(xiàn)箭頭的指向方向是像素強(qiáng)度都變化方向呼畸,幅值是強(qiáng)度變化的大小痕支。

右邊的梯度方向矩陣中可以看到角度是0-180度,不是0-360度蛮原,這種被稱之為"無符號(hào)"梯度("unsigned" gradients)因?yàn)橐粋€(gè)梯度和它的負(fù)數(shù)是用同一個(gè)數(shù)字表示的卧须,也就是說一個(gè)梯度的箭頭以及它旋轉(zhuǎn)180度之后的箭頭方向被認(rèn)為是一樣的。那為什么不用0-360度的表示呢?在事件中發(fā)現(xiàn)unsigned gradients比signed gradients在行人檢測(cè)任務(wù)中效果更好花嘶。一些HOG的實(shí)現(xiàn)中可以讓你指定signed gradients笋籽。

下一步就是為這些8*8的網(wǎng)格創(chuàng)建直方圖,直方圖包含了9個(gè)bin來對(duì)應(yīng)0,20,40,...160這些角度察绷。

下面這張圖解釋了這個(gè)過程干签。我們用了上一張圖里面的那個(gè)網(wǎng)格的梯度幅值和方向津辩。根據(jù)方向選擇用哪個(gè)bin, 根據(jù)副值來確定這個(gè)bin的大小拆撼。先來看藍(lán)色圈圈出來的像素點(diǎn),它的角度是80喘沿,副值是2闸度,所以它在第五個(gè)bin里面加了2,再來看紅色的圈圈出來的像素點(diǎn)蚜印,它的角度是10莺禁,副值是4,因?yàn)榻嵌?0介于0-20度的中間(正好一半)窄赋,所以把幅值一分為二地放到0和20兩個(gè)bin里面去哟冬。

梯度直方圖

這里有個(gè)細(xì)節(jié)要注意,如果一個(gè)角度大于160度忆绰,也就是在160-180度之間浩峡,我們知道這里角度0,180度是一樣的错敢,所以在下面這個(gè)例子里翰灾,像素的角度為165度的時(shí)候,要把幅值按照比例放到0和160的bin里面去稚茅。

角度大于160的情況

把這8*8的cell里面所有的像素點(diǎn)都分別加到這9個(gè)bin里面去纸淮,就構(gòu)建了一個(gè)9-bin的直方圖,上面的網(wǎng)格對(duì)應(yīng)的直方圖如下:

8*8網(wǎng)格直方圖

這里亚享,在我們的表示中咽块,Y軸是0度(從上往下)。你可以看到有很多值分布在0,180的bin里面欺税,這其實(shí)也就是說明這個(gè)網(wǎng)格中的梯度方向很多都是要么朝上侈沪,要么朝下。

第四步: 16*16塊歸一化

上面的步驟中魄衅,我們創(chuàng)建了基于圖片的梯度直方圖峭竣,但是一個(gè)圖片的梯度對(duì)于整張圖片的光線會(huì)很敏感。如果你把所有的像素點(diǎn)都除以2晃虫,那么梯度的幅值也會(huì)減半皆撩,那么直方圖里面的值也會(huì)減半,所以這樣并不能消除光線的影響。所以理想情況下扛吞,我們希望我們的特征描述子可以和光線變換無關(guān)呻惕,所以我們就想讓我們的直方圖歸一化從而不受光線變化影響。

先考慮對(duì)向量用l2歸一化的步驟是:
v = [128, 64, 32]
[(128^2) + (64^2) + (32^2) ]^0.5=146.64
把v中每一個(gè)元素除以146.64得到[0.87,0.43,0.22]
考慮另一個(gè)向量2*v滥比,歸一化后可以得到向量依舊是[0.87, 0.43, 0.22]亚脆。你可以明白歸一化是把scale給移除了。

你也許想到直接在我們得到的9*1的直方圖上面做歸一化盲泛,這也可以濒持,但是更好的方法是從一個(gè)16*16的塊上做歸一化,也就是4個(gè)9*1的直方圖組合成一個(gè)36*1的向量寺滚,然后做歸一化柑营,接著,窗口再朝后面挪8個(gè)像素(看動(dòng)圖)村视。重復(fù)這個(gè)過程把整張圖遍歷一邊官套。


hog-16x16-block-normalization

第五步:計(jì)算HOG特征向量

為了計(jì)算這整個(gè)patch的特征向量,需要把36*1的向量全部合并組成一個(gè)巨大的向量蚁孔。向量的大小可以這么計(jì)算:

  1. 我們有多少個(gè)16*16的塊奶赔?水平7個(gè),垂直15個(gè)杠氢,總共有7*15=105次移動(dòng)站刑。
  2. 每個(gè)16*16的塊代表了36*1的向量。所以把他們放在一起也就是36*105=3780維向量修然。

可視化HOG

通常HOG特征描述子是畫出8*8網(wǎng)格中9*1歸一化的直方圖笛钝,見下圖。你可以發(fā)現(xiàn)直方圖的主要方向捕捉了這個(gè)人的外形愕宋,特別是軀干和腿玻靡。

visualizing_histogram
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市中贝,隨后出現(xiàn)的幾起案子囤捻,更是在濱河造成了極大的恐慌,老刑警劉巖邻寿,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝎土,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绣否,警方通過查閱死者的電腦和手機(jī)誊涯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蒜撮,“玉大人暴构,你說我怎么就攤上這事跪呈。” “怎么了取逾?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵耗绿,是天一觀的道長。 經(jīng)常有香客問我砾隅,道長误阻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任晴埂,我火速辦了婚禮究反,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘邑时。我一直安慰自己奴紧,他們只是感情好特姐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布晶丘。 她就那樣靜靜地躺著,像睡著了一般唐含。 火紅的嫁衣襯著肌膚如雪浅浮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天捷枯,我揣著相機(jī)與錄音滚秩,去河邊找鬼。 笑死淮捆,一個(gè)胖子當(dāng)著我的面吹牛郁油,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播攀痊,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼桐腌,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了苟径?” 一聲冷哼從身側(cè)響起案站,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棘街,沒想到半個(gè)月后蟆盐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遭殉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年石挂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片险污。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痹愚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情里伯,我是刑警寧澤城瞎,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站疾瓮,受9級(jí)特大地震影響脖镀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜狼电,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一蜒灰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肩碟,春花似錦强窖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至髓抑,卻和暖如春咙崎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吨拍。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工褪猛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羹饰。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓伊滋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親队秩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笑旺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容