SVM算法在項(xiàng)目實(shí)踐中的應(yīng)用!
↑↑↑關(guān)注后"星標(biāo)"Datawhale
每日干貨?&?每月組隊(duì)學(xué)習(xí),不錯(cuò)過(guò)
?Datawhale干貨?作者:蘇麗敏,Datawhale優(yōu)秀學(xué)習(xí)者,北理工計(jì)算機(jī)碩士
支持向量機(jī)(Support Vector Machine)是Cortes和Vapnik于1995年首先提出的,它在解決小樣本、非線(xiàn)性及高維模式識(shí)別中表現(xiàn)出許多特有的優(yōu)勢(shì),并能夠推廣應(yīng)用到函數(shù)擬合等其他機(jī)器學(xué)習(xí)問(wèn)題中。
正是由于SVM具有很多獨(dú)特的優(yōu)勢(shì),基于SVM分類(lèi)器在很多時(shí)候都具有較好的擬合作用。本文對(duì)SVM算法在行人檢測(cè)項(xiàng)目實(shí)踐中的應(yīng)用進(jìn)行詳細(xì)講解,同時(shí)給出調(diào)用OpenCV分類(lèi)器及可視化的代碼實(shí)現(xiàn),便于大家學(xué)習(xí)實(shí)踐。
目前的行人檢測(cè)基本上都是基于法國(guó)研究人員Dalal在2005的CVPR發(fā)表的HOG+SVM的行人檢測(cè)算法(Histograms of Oriented Gradients for Human Detection, Navneet Dalel,Bill Triggs, CVPR2005)。HOG+SVM作為經(jīng)典算法也集成到OpenCV里面去了,可以直接調(diào)用實(shí)現(xiàn)行人檢測(cè)。
本文目錄? ??1. HOG特征描述符
????????1.1. 主要思想
????????1.2. 微觀
? ? ? ? 1.3. 宏觀(硬核)
? ? ? ? 1.4. HOG算法優(yōu)缺點(diǎn)
????2.?HOG特征的原理
????????2.1.?圖形預(yù)處理
??????? 2.2. 計(jì)算圖像梯度
? ? ? ? 2.3.?計(jì)算梯度直方圖
? ? ? ? 2.4.?Block歸一化
? ? ? ? 2.5.?獲得HOG描述子
? ? ? ? 2.6.?使用HOG特征數(shù)據(jù)
????3. 基于OpenCV的簡(jiǎn)單實(shí)現(xiàn)
????????3.1. 行人檢測(cè)
????????3.2. 可視化
一、HOG特征描述符
HOG(Histogram of Oriented Gradients)HOG特征在對(duì)象檢測(cè)與模式匹配中是一種常見(jiàn)的特征提取技術(shù)(深度學(xué)習(xí)之前),是基于本地像素塊進(jìn)行特征直方圖提取的一種算法,對(duì)像局部的變形與光照影響有很好的穩(wěn)定性,最初是用HOG特征來(lái)識(shí)別人像,通過(guò)HOG特征提取+SVM訓(xùn)練,可以得到很好的效果,OpenCV已經(jīng)有相應(yīng)的接口。
HOG特征是在2005年CVPR的會(huì)議發(fā)表,在圖像手工特征提取方面具有里程碑式的意義,當(dāng)時(shí)在行人檢測(cè)領(lǐng)域獲得了極大成功。1.1 主要思想
局部目標(biāo)的外表和形狀可以被局部梯度的分布很好的描述,即使我們不知道對(duì)應(yīng)的梯度和邊緣的位置。(本質(zhì):梯度的統(tǒng)計(jì)信息,梯度主要存在于邊緣edge或角落corner的地方)1.2 宏觀
特征描述符就是通過(guò)提取圖像的有用信息,并且丟棄無(wú)關(guān)信息來(lái)簡(jiǎn)化圖像的表示。HOG特征描述符可以將3通道的彩色圖像轉(zhuǎn)換成一定長(zhǎng)度的特征向量。那么我們就需要定義什么是“有用的”,什么是“無(wú)關(guān)的”。這里的“有用”,是指對(duì)于什么目的有用,顯然特征向量對(duì)于觀察圖像是沒(méi)有用的,但是它對(duì)于像圖像識(shí)別和目標(biāo)檢測(cè)這樣的任務(wù)非常有用。當(dāng)將這些特征向量輸入到類(lèi)似支持向量機(jī)(SVM)這樣的圖像分類(lèi)算法中時(shí),會(huì)得到較好的結(jié)果。那什么樣的“特征”對(duì)分類(lèi)任務(wù)是有用,比如我們想檢測(cè)出馬路上的車(chē)道線(xiàn),那么我們可以通過(guò)邊緣檢測(cè)來(lái)找到這些車(chē)道線(xiàn),在這種情況下,邊緣信息就是“有用的”,而顏色信息是無(wú)關(guān)的。方向梯度直方圖(HOG)特征描述符常和線(xiàn)性支持向量機(jī)(SVM)配合使用,用于訓(xùn)練高精度的目標(biāo)分類(lèi)器。
1.3 微觀(硬核)
在HOG特征描述符中,梯度方向的分布,也就是梯度方向的直方圖被視作特征。圖像的梯度(x和y導(dǎo)數(shù))非常有用,因?yàn)檫吘壓凸战?強(qiáng)度突變的區(qū)域)周?chē)奶荻确群艽螅⑶疫吘壓凸战潜绕教箙^(qū)域包含更多關(guān)于物體形狀的信息。HOG特征是一種圖像局部特征,基本思路是將圖像劃分為很多小的連通區(qū)域,即細(xì)胞單元Cell,然后對(duì)Cell的梯度幅值和方向進(jìn)行投票統(tǒng)計(jì),形成基于梯度特性的直方圖。把直方圖在圖像更大的范圍內(nèi)(又名區(qū)間或者Block)進(jìn)行歸一化。歸一化的塊描述符叫做HOG描述子feature descriptor。將檢測(cè)窗口中的所有塊的HOG描述子組合成最終的特征向量。然后使用SVM分類(lèi)器進(jìn)行目標(biāo)和非目標(biāo)的二分類(lèi)(檢測(cè))。HOG+SVM的工作流程如下:
首先對(duì)輸入的圖片進(jìn)行預(yù)處理,然后計(jì)算像素點(diǎn)的梯度特性,包括梯度幅值和梯度方向。然后投票統(tǒng)計(jì)形成梯度直方圖,然后對(duì)blocks進(jìn)行normalize,最后收集到檢測(cè)窗口的HOG feature(一行多維的vector)放入SVM里進(jìn)行監(jiān)督學(xué)習(xí),實(shí)現(xiàn)行人的檢測(cè)。接下來(lái)對(duì)上述HOG的主要步驟進(jìn)行學(xué)習(xí)。
檢測(cè)窗口在整個(gè)圖像的所有位置和尺度進(jìn)行掃描,并對(duì)輸出的金字塔進(jìn)行非極大值抑制來(lái)檢測(cè)目標(biāo)(檢測(cè)窗口的大小一般為128x64)
1.4?HOG算法優(yōu)缺點(diǎn)
HOG算法具有以下優(yōu)點(diǎn):核心思想是所檢測(cè)的局部物體外形能夠被梯度或邊緣方向的分布所描述,HOG能較好地捕捉局部形狀信息,對(duì)幾何和光學(xué)變化都有很好的不變性;
HOG是在密集采樣的圖像塊中求取的,在計(jì)算得到的HOG特征向量中隱含了該塊與檢測(cè)窗口之間的空間位置關(guān)系。
特征描述子獲取過(guò)程復(fù)雜,維數(shù)較高,導(dǎo)致實(shí)時(shí)性差;
很難處理遮擋問(wèn)題,人體姿勢(shì)動(dòng)作幅度過(guò)大或物體方向改變也不易檢測(cè)(這個(gè)問(wèn)題后來(lái)在DPM中采用可變形部件模型的方法得到了改善);
跟SIFT相比,HOG沒(méi)有選取主方向,也沒(méi)有旋轉(zhuǎn)梯度方向直方圖,因而本身不具有旋轉(zhuǎn)不變性(較大的方向變化),其旋轉(zhuǎn)不變性是通過(guò)采用不同旋轉(zhuǎn)方向的訓(xùn)練樣本來(lái)實(shí)現(xiàn)的;
跟SIFT相比,HOG本身不具有尺度不變性,其尺度不變性是通過(guò)縮放檢測(cè)窗口圖像的大小來(lái)實(shí)現(xiàn)的;
此外,由于梯度的性質(zhì),HOG對(duì)噪點(diǎn)相當(dāng)敏感,在實(shí)際應(yīng)用中,在block和Cell劃分之后,對(duì)于得到各個(gè)區(qū)域,有時(shí)候還會(huì)做一次高斯平滑去除噪點(diǎn)。
二、HOG特征的原理
接下來(lái)讓我們進(jìn)入到計(jì)算圖像的HOG特征描述符的具體步驟。以下面這張圖片為例(寬高為100x200):
2.1 圖形預(yù)處理
預(yù)處理包括灰度化和Gamma變換。灰度處理是可選操作,因?yàn)榛叶葓D像和彩色圖像都可以用于計(jì)算梯度圖。對(duì)于彩色圖像,先對(duì)三通道顏色值分別計(jì)算梯度,然后取梯度值最大的那個(gè)作為該像素的梯度。然后進(jìn)行伽馬矯正,調(diào)節(jié)圖像對(duì)比度,減少光照對(duì)圖像的影響(包括光照不均和局部陰影),使過(guò)曝或者欠曝的圖像恢復(fù)正常,更接近人眼看到的圖像。Gamma矯正公式:,其中表示圖像,表示冪指數(shù)。(越大,圖像越暗;為1時(shí),表示沒(méi)有變化。) 如圖,當(dāng)取不同的值時(shí)對(duì)應(yīng)的輸入輸出曲線(xiàn)( =1時(shí)輸入輸出保持一致) :1) 當(dāng)<1時(shí),輸入圖像的低灰度值區(qū)域動(dòng)態(tài)范圍變大,進(jìn)而圖像低灰度值區(qū)域?qū)Ρ榷鹊靡栽鰪?qiáng);在高灰度值區(qū)域,動(dòng)態(tài)范圍變小,進(jìn)而圖像高灰度值區(qū)域?qū)Ρ榷鹊靡越档汀W罱K,圖像整體的灰度變亮。2) 當(dāng)>1時(shí),輸入圖像的低灰度值區(qū)域動(dòng)態(tài)范圍變小,進(jìn)而圖像低灰度值區(qū)域?qū)Ρ榷鹊靡越档停辉诟呋叶戎祬^(qū)域,動(dòng)態(tài)范圍變大,進(jìn)而圖像高灰度值區(qū)域?qū)Ρ榷鹊靡栽鰪?qiáng)。最終,圖像整體的灰度變暗。
代碼:
import cv2import numpy as npfrom matplotlib import pyplot as pltimg = cv2.imread('*.png', 0)img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)img2 = np.power(img/float(np.max(img)),1/2.2)plt.imshow(img2)plt.axis('off')plt.show()
放圖,左圖是,中圖是,右圖是:

2.2 計(jì)算圖像梯度
為了得到梯度直方圖,那么首先需要計(jì)算圖像水平方向和垂直方向梯度。可以通過(guò)使用以下內(nèi)核過(guò)濾圖像實(shí)現(xiàn),分別用于計(jì)算水平梯度和垂直梯度。

可以使用內(nèi)核大小為1的sobel算子獲取相同結(jié)果,OpenCV也是如此。
利用sobel水平和垂直算子與輸入圖像卷積計(jì)算、:進(jìn)一步得到圖像梯度的幅值:
簡(jiǎn)化計(jì)算,幅值也可以做近似:
圖像梯度的方向:
這里需要注意的是:梯度方向和圖像邊緣方向是互相正交的。

代碼:
mport cv2import numpy as np# Read imageimg = cv2.imread('*.jpg')img = np.float32(img) / 255.0 # 歸一化# 計(jì)算x和y方向的梯度gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)# 計(jì)算合梯度的幅值和方向(角度)mag,?angle?=?cv2.cartToPolar(gx,?gy,?angleInDegrees=True)
下圖展示了梯度:

第一個(gè)圖:x-梯度的絕對(duì)值,第二個(gè)圖:y梯度的絕對(duì)值 ,第三個(gè)圖:梯度的幅值,第四個(gè)圖:角度。
注意到,x-梯度在垂直線(xiàn)觸發(fā),y-梯度在水平線(xiàn)觸發(fā)。梯度的幅值在有密集的劇烈改變時(shí)觸發(fā)。當(dāng)區(qū)域很平緩時(shí),梯度沒(méi)有明顯變化。梯度圖除去了很多不必要的信息(例如有顏色的背景),強(qiáng)調(diào)凸顯線(xiàn)條。當(dāng)你看到梯度圖像,很容易想到這張圖片有一個(gè)人。
在每個(gè)像素點(diǎn),梯度有一個(gè)幅值和方向。對(duì)于有顏色的圖像,計(jì)算三通道的梯度(如上圖所示)。一個(gè)像素點(diǎn)的梯度的幅值是三通道中梯度幅值最大的值,角度也是最大梯度對(duì)應(yīng)的角度。
2.3 計(jì)算梯度直方圖
此時(shí),每一個(gè)像素點(diǎn)具有兩個(gè)值:梯度幅值和梯度方向。在這一步中,圖像被分成若干個(gè)8×8的Cell,如下圖所示,例如我們將圖像resize至64x128的大小,那么這幅圖像就被劃分為8x16個(gè)8x8的Cell單元,并為每個(gè)8×8的Cell計(jì)算梯度直方圖。當(dāng)然,Cell的劃分也可以是其他值:16x16,8x16等,根據(jù)具體的場(chǎng)景確定。

如下圖所示,左圖是衣服64x128的圖像,被劃分為8x16個(gè)8x8的Cell;中間的圖像表示一個(gè)Cell中的梯度矢量,箭頭朝向代表梯度方向,箭頭長(zhǎng)度代表梯度大小。
右圖是 8×8 的Cell中表示梯度的原始數(shù)值,注意角度的范圍介于0到180度之間,而不是0到360度, 這被稱(chēng)為“無(wú)符號(hào)”梯度,因?yàn)閮蓚€(gè)完全相反的方向被認(rèn)為是相同的。和是相同的。(經(jīng)驗(yàn)表明這樣處理對(duì)于行人檢測(cè)效果更好。)


再比如:(如上圖所示)某像素的梯度幅值為13.6,方向?yàn)?6,36度兩側(cè)的角度bin分別為20度和40度,那么按一定加權(quán)比例分別在20度和40度對(duì)應(yīng)的bin加上梯度值,加權(quán)公式為:
20度對(duì)應(yīng)的bin:((40-36)/20) x13.6,分母的20表示20等份,其中4份給20度對(duì)應(yīng)的bin;
40度對(duì)應(yīng)的bin:((36-20)/20) x13.6,分母的20表示20等份,其中16份給20度對(duì)應(yīng)的bin;

對(duì)整個(gè)Cell進(jìn)行投票統(tǒng)計(jì),最終得到9-bin直方圖:

可以看到直方圖中,0度和160附近有很大的權(quán)重,說(shuō)明了大多數(shù)像素的梯度向上或者向下,也就是這個(gè)Cell是個(gè)橫向邊緣。
2.4 Block歸一化
HOG特征將8×8的一個(gè)局部區(qū)域作為一個(gè)Cell,再以2×2個(gè)Cell作為一組,稱(chēng)為一個(gè)block,也就是說(shuō)一個(gè)block表示16x16的區(qū)域。
由于每個(gè)Cell有9個(gè)值,一個(gè)block(2×2個(gè)Cell)則有36個(gè)值,HOG是通過(guò)滑動(dòng)窗口的方式來(lái)得到block的,如下圖所示:

接下來(lái)對(duì)Block進(jìn)行歸一化。(再再再一次強(qiáng)調(diào),歸一化的目的是為了降低光照/遷移的影響):
歸一化的方法有很多:L1-norm、L2-norm、max/min等等,一般選擇L2-norm。
例如對(duì)于一個(gè)[128,64,32]的三維向量來(lái)說(shuō),模長(zhǎng)是:
2.5 獲得HOG描述子
每一個(gè)16x16大小的block將會(huì)得到一個(gè)長(zhǎng)度為36x1的特征向量,并進(jìn)行歸一化。那會(huì)得到多大的特征向量呢?對(duì)于上圖被劃分8 x16個(gè)Cell ,每個(gè)block有2x2個(gè)Cell的話(huà),那么Cell的個(gè)數(shù)為:(8-1)x(16-1)=105。
每個(gè)16x16 block由36x1維向量,合并所有105個(gè)block的特征,最終得到由36 x105=3780維向量表示的特征描述符。
獲得HOG特征向量,就可以用來(lái)可視化和分類(lèi)了。對(duì)于多維的HOG特征,SVM就可以排上用場(chǎng)了。
介紹以下Dalal等人的訓(xùn)練方法:
提取正負(fù)樣本的HOG特征;
用正負(fù)樣本訓(xùn)練一個(gè)初始的分類(lèi)器,然后由分類(lèi)器生產(chǎn)檢測(cè)器;
然后用初始分類(lèi)器在負(fù)樣本原圖上進(jìn)行行人檢測(cè),檢測(cè)出來(lái)的矩形區(qū)域自然都是分類(lèi)錯(cuò)誤的負(fù)樣本,這就是所謂的難例(hard examples);
提取難例的HOG特征并結(jié)合第一步中的特征,重新訓(xùn)練,生成最終的檢測(cè)器 ;
2.6 使用HOG特征數(shù)據(jù)
HOG特征本身是不支持旋轉(zhuǎn)不變性與多尺度檢測(cè)的,但是通過(guò)構(gòu)建高斯金字塔實(shí)現(xiàn)多尺度的開(kāi)窗檢測(cè)就會(huì)得到不同分辨率的多尺度檢測(cè)支持,如下圖所示。

OpenCV中HOG多尺度對(duì)象檢測(cè)API如下:
virtual void cv::HOGDescriptor::detectMultiScale(
? ?InputArray ?img,
? ?std::vector< Rect > & ? foundLocations,
? ?double ?hitThreshold = 0,
? ?Size ? ?winStride = Size(),
? ?Size ? ?padding = Size(),
? ?double ?scale = 1.05,
? ?double ?finalThreshold = 2.0,
? ?bool ? ?useMeanshiftGrouping = false
)
Img-表示輸入圖像
foundLocations-表示發(fā)現(xiàn)對(duì)象矩形框
hitThreshold-表示SVM距離度量,默認(rèn)0表示,表示特征與SVM分類(lèi)超平面之間
winStride-表示窗口步長(zhǎng)
padding-表示填充
scale-表示尺度空間
finalThreshold-最終閾值,默認(rèn)為2.0
useMeanshiftGrouping-不建議使用,速度太慢拉
3.1 行人檢測(cè)
代碼:
import cv2 as cvimport numpy as npfrom matplotlib import pyplot as pltif __name__ == '__main__':src = cv.imread("*.jpg")cv.imshow("input", src)hog = cv.HOGDescriptor()hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector())# Detect people in the image(rects, weights) = hog.detectMultiScale(src,winStride=(2,4),padding=(8, 8),scale=1.2,useMeanshiftGrouping=False)for (x, y, w, h) in rects:cv.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2)cv.imshow("hog-detector", src)cv.imwrite("hog-detector.jpg",src)cv.waitKey(0)cv.destroyAllWindows()
待檢測(cè)圖片:

檢測(cè)圖片(有點(diǎn)不完美,調(diào)參調(diào)不動(dòng)了,先醬~):

3.2?可視化
feature.log函數(shù):
image:可以是灰度圖或者彩色圖;
orientations:就是把180度分成幾份,也就是bin的數(shù)量;
pixels_per_Cell:一個(gè)Cell里包含的像素個(gè)數(shù);
Cells_per_block:一個(gè)block包含的Cell個(gè)數(shù);
visualize:是否返回一個(gè)hog圖像用于顯示,下面會(huì)顯示這張圖;
為了顯示效果,把Cell的尺寸改為(16, 16),對(duì)于每一個(gè)Cell,畫(huà)出它歸一化后的梯度直方圖。如下圖所示,我們可以很明顯的看出一個(gè)人的輪廓。from skimage import feature, exposureimport cv2image = cv2.imread('hog.jpg')fd, hog_image = feature.hog(image, orientations=9, pixels_per_Cell=(16, 16),Cells_per_block=(2, 2), visualize=True)# Rescale histogram for better displayhog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 10))cv2.imshow('img', image)cv2.imshow('hog', hog_image_rescaled)hog_image_rescaled = 255.0 * hog_image_rescaledcv2.imwrite('edge_hog.jpg', hog_image_rescaled)cv2.waitKey(0)==ord('q')

本文電子版 后臺(tái)回復(fù) 行人檢測(cè) 獲取
“竟然學(xué)習(xí)完了,給自己點(diǎn)個(gè)贊↓
