一、HOG向梯度直方圖概述
?
向梯度直方圖(Histogram of Oriented Gradient, HOG)特征是基于對(duì)稠密網(wǎng)格中歸一化的局部方向梯度直方圖的計(jì)算。此方法的基本觀點(diǎn)是:局部目標(biāo)的外表和形狀可以被局部梯度或邊緣方向的分布很好的描述,即使我們不知道對(duì)應(yīng)的梯度和邊緣的位置。在實(shí)際操作中,將圖像分為小的元胞(cells),在每個(gè)元胞內(nèi)累加計(jì)算出一維的梯度方向(或邊緣方向)直方圖。
為了對(duì)光照和陰影有更好的不變性,需要對(duì)直方圖進(jìn)行對(duì)比度歸一化,這可以通過(guò)將元胞組成更大的塊(blocks)并歸一化塊內(nèi)的所有元胞來(lái)實(shí)現(xiàn)。歸一化的塊描述符就叫作HOG描述子。將檢測(cè)窗口中的所有塊的HOG描述子組合起來(lái)就形成了最終的特征向量,然后使用SVM分類器進(jìn)行行人檢測(cè)。檢測(cè)窗口劃分為重疊的塊,對(duì)這些塊計(jì)算HOG描述子,形成的特征向量放到線性SVM中進(jìn)行目標(biāo)/非目標(biāo)的二分類。檢測(cè)窗口在整個(gè)圖像的所有位置和尺度上進(jìn)行掃描,并對(duì)輸出的金字塔進(jìn)行非極大值抑制來(lái)檢測(cè)目標(biāo)。
=========================================================================
二、向梯度直方圖(Histogram of Oriented Gradient, HOG)特征算法大概過(guò)程:
1)HOG特征提取方法就是將一個(gè)image即要檢測(cè)的目標(biāo)或者掃描窗體進(jìn)行圖像灰度化,就是將圖像看做一個(gè)R,G,B三顏色的三維圖像,對(duì)于彩色圖像,將RGB分量轉(zhuǎn)化成灰度圖像,其轉(zhuǎn)化數(shù)學(xué)公式為:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
2)采用Gamma校正法對(duì)輸入圖像進(jìn)行顏色空間的標(biāo)準(zhǔn)化(歸一化);目的是調(diào)節(jié)圖像的對(duì)照度,減少圖像局部的陰影和光照變化所造成的影響,同一時(shí)候能夠抑制噪音的干擾。?在圖像照度不均勻的情況下,可以通過(guò)Gamma校正,將圖像整體亮度提高或降低。在實(shí)際中可以采用兩種不同的方式進(jìn)行Gamma標(biāo)準(zhǔn)化,平方根、對(duì)數(shù)法。這里我們采用平方根的辦法,公式如下(其中γ=0.5):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
3)計(jì)算圖像每一個(gè)像素的梯度dx和dy(包含梯度大小和梯度方向);主要是為了捕獲輪廓信息,同一時(shí)候進(jìn)一步弱化光照的干擾,計(jì)算圖像的X方向梯度dx與Y方向梯度dy,根據(jù)梯度計(jì)算mag與角度,計(jì)算梯度時(shí)候可以先高斯模糊,使用sobel算子或者其它一階導(dǎo)數(shù)算子計(jì)算梯度值dx、dy,梯度的大小和方向:
?,
sobel的水平方向算子和垂直方向算子:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ? ??
首先用sobel算子,Horizontal Direction梯度算子對(duì)原圖像做卷積運(yùn)算,得到x方向(水平方向,以向右為正方向)的梯度分量gradscalx,然后用Horizontal Direction梯度算子對(duì)原圖像做卷積運(yùn)算,得到y(tǒng)方向(豎直方向,以向上為正方向)的梯度分量gradscaly。然后再用以下公式計(jì)算該像素點(diǎn)的梯度大小和方向:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
分別表示輸入圖像中像素點(diǎn)的(x,y)處的水平方向梯度,垂直方向梯度和像素值,像素點(diǎn)(x,y)c處的梯度幅值和梯度方向分別為:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
將圖像劃分為8x8的小網(wǎng)格,對(duì)每個(gè)小網(wǎng)格內(nèi)的圖像做梯度方向直方圖,每個(gè)8x8=64個(gè)像素為一個(gè)cell,對(duì)每個(gè)cell根據(jù)角度分為9個(gè)直方圖塊(BIN),對(duì)cell內(nèi)每一個(gè)像素用梯度方向在直方圖中進(jìn)行加權(quán)投影,映射到固定的角度范圍,就能夠得到這個(gè)cell的梯度方向直方圖了,就是該cell中對(duì)應(yīng)的9維特征向量,例如,20°-40°和200°-220°劃入一個(gè)直方圖塊里。
? ? ? ? ? ? ? ? ? ? ? ??
4)將圖像劃分成小網(wǎng)格cells,為每一個(gè)網(wǎng)格單元構(gòu)建梯度方向直方圖,將cell的梯度方向360度分成9個(gè)方向塊Block。一般地,一個(gè)塊(Block)都由若干網(wǎng)格單元Cell組成,一個(gè)單元Cell都有若干個(gè)像素點(diǎn)組成。假設(shè)行人檢測(cè)的參數(shù)設(shè)置是:2×2 cell/block、8×8像素/cell、9個(gè)直方圖通道(9 bins),一個(gè)cell的hog描述子向量的長(zhǎng)度為9,一個(gè)塊的特征向量長(zhǎng)度為:2×2×9=36,所以檢測(cè)窗口的HOG向量長(zhǎng)度=105×4×9=3780。
5)統(tǒng)計(jì)每一個(gè)cell的梯度直方圖不同梯度的個(gè)數(shù),就可以形成每一個(gè)cell的描述算子descriptor;在計(jì)算每個(gè)cell的梯度直方圖時(shí),可以用三線性插值來(lái)提高計(jì)算速率。對(duì)于每個(gè)cell里的點(diǎn),我們認(rèn)為都是一個(gè)三維向量? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
從下面的圖片可以看到,原圖像大小為720×475,裁剪成大小為64×128個(gè)像素的圖片,然后可以被分割成128個(gè)8*8大小的網(wǎng)格cell,每個(gè)網(wǎng)格cell都會(huì)計(jì)算一個(gè)梯度直方圖。8×8像素大小的網(wǎng)格cell可以提供了一個(gè)緊湊(compact)/壓縮的表示。
在圖像中,每個(gè)像素點(diǎn)包括像x方向梯度幅值magnitude,梯度方向direction三個(gè)要素,即一個(gè)8×8像素大小的圖像有8×8×3=192個(gè)像素值,三個(gè)channel取最大magnitude那個(gè),加起來(lái)就是8*8*2=128,后面我們會(huì)看到這128個(gè)數(shù)如何用一個(gè)9個(gè)bin的直方圖來(lái)表示成9個(gè)數(shù)的數(shù)組。不僅僅是可以有緊湊的表示,用直方圖來(lái)表示一個(gè)圖像也可以更加抗噪,一個(gè)gradient可能會(huì)有噪音,但是用直方圖來(lái)表示后就不會(huì)對(duì)噪音那么敏感了。
?
上面這個(gè)圖片的大小是64×128個(gè)像素,分割成了128個(gè)8×8像素大小的網(wǎng)格cell,那么整個(gè)圖像一共有64/8 ×128/8 = 8*16=128個(gè)網(wǎng)格
根據(jù)梯度幅值magnitude,梯度方向direction的兩張表格,根據(jù)梯度方向direction選擇bin的位置, 根據(jù)副值來(lái)確定這個(gè)bin的大小。藍(lán)色圈的像素點(diǎn)對(duì)應(yīng)的梯度方向direction為80,對(duì)應(yīng)的幅值大小為2,與其對(duì)應(yīng)的直方圖第五個(gè)bin里面加2;對(duì)應(yīng)的梯度方向direction為10,對(duì)應(yīng)的幅值大小為4,因?yàn)榻嵌?0介于0-20度的中間(正好一半),所以把幅值一分為二按照比例影響大小放到0和20兩個(gè)bin里面去。
如果角度大于 160 度,則這個(gè)角度介于 160 度和 180 度之間,角度環(huán)繞使 0 度和 180 度相等。因此,在下面的示例中,角度為 165 度的像素對(duì) 0 度 bin 和 160 度 bin 的貢獻(xiàn)成比例。
可以看到有很多值分布在0-180的bin里面,這其實(shí)也就是說(shuō)明這個(gè)網(wǎng)格中的梯度方向很多都是要么朝上,要么朝下。把每個(gè)8*8的cell里面所有的像素點(diǎn)都分別加到這9個(gè)bin里面去,就構(gòu)建了一個(gè)9-bin的直方圖,上面的網(wǎng)格對(duì)應(yīng)的直方圖如下:
?
6)將每幾個(gè)cell組成一個(gè)block(比如2×2個(gè)cell/block),一個(gè)block內(nèi)全部cell的特征descriptor串聯(lián)起來(lái)便得到該block的HOG特征描述算子descriptor。有幾個(gè)參數(shù)非常重要,分別為winSize(64,128), ?blockSize(16,16), ?blockStride(8,8), cellSize(8,8), ?nbins(9),在此,用幾個(gè)示意圖來(lái)表示。
a)???????窗口大小winSize(64,128)
b)??????塊大小blockSize(16,16)
?c)???????胞元大小cellSize(8,8)
?Hog特征維數(shù)的計(jì)算
HOGDescriptor* hog = newHOGDescriptor(cvSize(64, 48), cvSize(8, 6), cvSize(8, 6), cvSize(4, 3), 9);
根據(jù)上面的描述可知,cvSize(64,128)表示窗口的大小,cvSize(16, 16)表示塊(block)大小,cvSize(8,8)表示塊滑動(dòng)增量(blockStride)大小,cvSize(4, 4)表示胞元(cell)大小,9表示每個(gè)胞單元中梯度直方圖的數(shù)量。
可知:一個(gè)塊(block)包含A=(blockSize.width/cellSize.width)*(blockSize.height / cellSize.height)=128個(gè)網(wǎng)格(cell),所以一個(gè)塊(block)含有9A=1125個(gè)梯度直方圖??梢酝ㄟ^(guò)計(jì)算一個(gè)窗口中包含了B=((windowSize.width-blockSize.width)/(blockStrideSize.width)+1)* ((windowSize.height-blockSize.height)/(blockStrideSize.height)+1)=105個(gè)塊(block),所以一個(gè)窗口包含9AB=3780個(gè)梯度直方圖。
將2x2的網(wǎng)格單元cell組合成為一個(gè)大的塊(Block)對(duì)每個(gè)塊之間有1/2部分是重疊區(qū)域。主要是將每個(gè)Cell的直方圖合并為一個(gè)大的直方圖向量,這樣每個(gè)塊就有36個(gè)向量描述子。對(duì)每個(gè)塊的描述子做歸一化處理,常見的歸一化處理為L(zhǎng)2-norm或者L1-norm,公式如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
7)將圖像image內(nèi)的全部block的HOG特征descriptor串聯(lián)起來(lái)就能夠得到該image(你要檢測(cè)的目標(biāo))的HOG特征descriptor了。這個(gè)就是終于的可供分類使用的特征向量了。
=========================================================================
代碼實(shí)現(xiàn):
#include"stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include "math.h"
#include <opencv2/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
//using namespace cv::features2d;
int main(int argc, char** argv) {
Mat src = imread("F:/photo/h1.jpg");
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
namedWindow("input image", WINDOW_AUTOSIZE);
imshow("input image", src);
/*Mat dst, dst_gray;
resize(src, dst, Size(64, 128));
cvtColor(dst, dst_gray, COLOR_BGR2GRAY);
HOGDescriptor detector(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
vector<float> descriptors;
vector<Point> locations;
detector.compute(dst_gray, descriptors, Size(0, 0), Size(0, 0), locations);
printf("number of HOG descriptors : %d", descriptors.size());
*/
HOGDescriptor hog = HOGDescriptor();
hog.setSVMDetector(hog.getDefaultPeopleDetector());
vector<Rect> foundLocations;
hog.detectMultiScale(src, foundLocations, 0, Size(8, 8), Size(32, 32), 1.05, 2);
Mat result = src.clone();
for (size_t t = 0; t < foundLocations.size(); t++) {
rectangle(result, foundLocations[t], Scalar(0, 0, 255), 2, 8, 0);
}
namedWindow("HOG SVM Detector Demo", WINDOW_AUTOSIZE);
imshow("HOG SVM Detector Demo", result);
waitKey(0);
return 0;
}
圖像處理效果:
行人識(shí)別:?
行人識(shí)別:
灰度圖行人識(shí)別:
??文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-441543.html
文章參考:Histogram of Oriented Gradients explained using OpenCV文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-441543.html
到了這里,關(guān)于OpenCV圖像特征提取學(xué)習(xí)五,HOG特征檢測(cè)算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!