HOG特征检测学习笔记
HOG簡介
HOG(Histogram of Oriented Gridients)特征檢測算法,最早由法國研究院Dalal等在CVPR2005上提出,是一種用于檢測人體目標(biāo)檢測的圖像描述子,用于表征圖像局部梯度方向和梯度強(qiáng)度分布特性。其主要思想是:在邊緣具體位置未知的情況下,邊緣方向的分布也可以很好地表示行人目標(biāo)的外形輪廓。Dalal等提出的HOG+SVM算法當(dāng)時在行人檢測上取得了巨大的成功,而此后涌現(xiàn)的許多算法,大多是以HOG+SVM的思想為主線。
HOG特征算法流程
大致分為以下幾個步驟:顏色空間歸一化(Gamma校正)–>梯度計算–>梯度方向直方圖–>重疊塊直方圖歸一化–>HOG特征。
1、顏色空間歸一化
由于圖像的采集環(huán)境、裝置等因素,采集到的圖像效果可能不是很好,容易出現(xiàn)誤檢或漏檢的情況,所以需要對采集到的圖像進(jìn)行預(yù)處理。主要是有兩步:將圖像灰度化、Gamma校正。
a、圖像灰度化
彩色圖像有R、G、B,3個顏色通道,將其轉(zhuǎn)換為單通道的灰度圖像。很簡單,使用以下公式:
gray=0.3?red+0.59?green+0.11?bluegray=0.3?red+0.59?green+0.11?blue
b、Gamma校正
在圖像亮度不均勻的情況下,可以通過Gamma校正來將圖像中整體亮度提高或降低。公式如下:
Y(x,y)=I(x,y)γY(x,y)=I(x,y)γ
其中,γγ為權(quán)值。在這里我們令γ=0.5γ=0.5,即取平方根;也可以自行取其他γγ值來得到不同的效果。
下圖是使用Gamma校正前后的結(jié)果,左圖是原圖,右圖是γ=0.5γ=0.5進(jìn)行Gamma校正的結(jié)果。直觀上可以看出右圖的整體亮度更接近了,左圖的像素間亮度差距較大。
2、梯度計算
前面對顏色空間進(jìn)行歸一化后的圖像,再求取其梯度以及梯度方向。分別在水平和垂直方向進(jìn)行計算。
水平方向梯度算子為:[?101][?101],垂直方向梯度算子為:[?101]T[?101]T。
假設(shè)當(dāng)前在計算像素點(diǎn)(x,y)(x,y)的梯度,則其水平梯度值GxGx和垂直梯度值GyGy為:
Gx(x,y)=I(x+1,y)?I(x?1,y)Gx(x,y)=I(x+1,y)?I(x?1,y)
Gy(x,y)=I(x,y+1)?I(x,y?1)Gy(x,y)=I(x,y+1)?I(x,y?1)
根據(jù)水平梯度值GxGx和垂直梯度值GyGy求出梯度值:
G(x,y)=Gx(x,y)2+Gy(x,y)2?????????????????√G(x,y)=Gx(x,y)2+Gy(x,y)2
角度值θ(x,y)θ(x,y)也可以求出:
θ(x,y)=arctan(Gx(x,y)Gy(x,y))θ(x,y)=arctan(Gx(x,y)Gy(x,y))
計算出的梯度圖如下所示:
3、梯度方向直方圖
將圖像分為若干個cells(單元),先假設(shè)每個cell有8×8=648×8=64個像素,相鄰的cell之間互不重疊。在每個cell中,計算梯度方向直方圖,將所有梯度方向分成9個bins(即9維的特征向量),如下圖所示。
比如說z2塊,對應(yīng)著兩部分,一部分是20°20°到40°40°,另一部分是200°200°到220°220°。
如圖所示,可以分成9個bin分別對應(yīng)一定的角度范圍,這9個bins即為直方圖的橫軸,而這些角度范圍內(nèi)所對應(yīng)的梯度的累加值為直方圖的縱軸。
最后我們可以得到每個cell的梯度方向直方圖。
4、重疊塊直方圖歸一化
一般來說,一個塊(block)由若干個單元(cell)組成,一個單元(cell)由若干個像素點(diǎn)組成。以下是矩形HOG示意圖:
我們常用的三種HOG結(jié)構(gòu):R-HOG(矩形HOG)、C-HOG(圓形HOG)、Single centre C-HOG(中心環(huán)繞HOG)。單位都是block。論文中提到,R-HOG和C-HOG的效果差不多,而Single centre C-HOG則相對差一點(diǎn)。后面都默認(rèn)使用R-HOG,另外兩種不做贅述,如果感興趣,請自行查閱論文。
前面假設(shè)了每個cell有8×8=648×8=64個像素,這里還要假設(shè)每個block有2×2=42×2=4個cell。
下圖表示得比較形象,摘自https://blog.csdn.net/hujingshuang/article/details/47337707/:
顏色標(biāo)出來的就是block,一個block里面有4個cell,不過其像素值不一定跟實(shí)際圖片嚴(yán)格對應(yīng),只是個示意圖。注意到,相鄰block之間都有重疊的cell,目的就是利用相鄰信息,引入各個block之間的關(guān)系。
注意到一個block的大小為64?4=25664?4=256個像素,然而圖片大小不一定正好是其整數(shù)倍,所以還要調(diào)整圖片的大小,縮放到其整數(shù)倍,以分離出整數(shù)個block。
到這里先停停,整理一下相關(guān)的參數(shù)設(shè)置。每個block中有2×2=42×2=4個cell,每個cell中有8×8=648×8=64個像素,計算每個cell的梯度方向直方圖得到9維的bins(HOG特征向量),一個block中HOG特征向量的長度則有4×9=364×9=36。
接著還要對每個block塊內(nèi)的HOG特征向量進(jìn)行歸一化。一般有以下幾種方法:
由于L2-norm較為簡單且在檢測中效果相對較好,故一般采用它。
5、后續(xù)操作
其實(shí)到這里已經(jīng)得到了整幅圖像的HOG特征向量了,使用一系列樣本提取得到的HOG特征向量送入SVM分類器訓(xùn)練,尋找最優(yōu)超平面進(jìn)行分類。
在實(shí)際應(yīng)用中,往往是從一幅圖片中取出若干個小窗口進(jìn)行特征提取,這樣子可以得到有目標(biāo)的窗口作為正樣本,和沒有目標(biāo)的窗口作為負(fù)樣本。將正負(fù)樣本送入SVM訓(xùn)練,識別時也是取一個相同大小的滑動窗口,使用訓(xùn)練好的SVM來判斷滑動窗口是否包含目標(biāo)。
程序?qū)崿F(xiàn)
1、matlab實(shí)現(xiàn)提取hog特征
前面部分截圖就是下面程序的運(yùn)行結(jié)果,已經(jīng)注釋了。程序不算復(fù)雜。
%% % 參考博客:https://blog.csdn.net/baidu_30028771/article/details/65937451。代碼實(shí)現(xiàn),部分原理講解。 % 其他參考資料:%% clear all; clc; close all;%% img = imread('lena.bmp');%% 1、灰度化 img = rgb2gray(img); img = double(img);step = 8; % step*step個像素作為一個cell [m1, n1] = size(img);%改變圖像尺寸為step的最近整數(shù)倍 img = imresize(img, [floor(m1/step)*step, floor(n1/step)*step], 'nearest'); [m, n] = size(img);%% 2、伽馬校正 % Gamma校正前圖片 % figure(); % imshow(img, []);img = sqrt(img);% Gamma校正后圖片 % figure(); % imshow(img, []);%% 3、求梯度和方向 fy = [-1, 0, 1]; %定義豎直模板 fx = fy'; %定義水平模板 Iy = imfilter(img, fy, 'replicate'); %豎直梯度 Ix = imfilter(img, fx, 'replicate'); %水平梯度 Ied = sqrt(Ix.^2 + Iy.^2); %梯度值 Iphase = Iy ./ Ix; %邊緣斜率,有些為inf,-inf,nan,其中nan需要再處理一下 the = atan(Iphase) * 180 / pi;% 計算得到的梯度圖 % figure(); % imshow(Ied, []);for i = 1:mfor j = 1:nif(Ix(i,j)>=0&Iy(i,j)>=0)the(i,j) = the(i,j);elseif(Ix(i,j)<=0&Iy(i,j)>=0)the(i,j) = the(i,j) + 180;elseif(Ix(i,j)<=0&Iy(i,j)<=0)the(i,j) = the(i,j) + 180;elseif(Ix(i,j)>=0&Iy(i,j)<=0)the(i,j) = the(i,j) + 360;endif isnan(the(i,j)) == 1the(i,j) = 0;endend end the = the + 0.000001;%防止角度為0%% 4、劃分cell、求cell的直方圖( 1 cell = 8*8 pixel ) step=8; %step*step個像素作為一個cell orient=9; %方向直方圖的方向個數(shù) angle_step = 360 / orient;%每個方向包含的角度數(shù) Cell = cell(1,1); %所有的角度直方圖,cell是可以動態(tài)增加的,所以先設(shè)了一個 i = 1; j = 1; ii = 1; jj = 1; for i = 1:step:mii = 1;for j = 1:step:nHist1(1:orient) = 0;for p = 1:stepfor q = 1:step%梯度方向直方圖Hist1(ceil(the(i+p-1, j+q-1)/angle_step)) = Hist1(ceil(the(i+p-1, j+q-1)/angle_step)) + Ied(i+p-1, j+q-1);endendCell{ii, jj} = Hist1;ii = ii + 1;endjj = jj + 1; end%% 5、劃分block,求block的特征值,使用重疊方式( 1 block = 2*2 cell ) [m, n] = size(Cell); feature = cell(1, (m-1)*(n-1)); for i=1:m-1for j=1:n-1block = [];block = [Cell{i,j}(:)' Cell{i,j+1}(:)' Cell{i+1,j}(:)' Cell{i+1,j+1}(:)'];block = block ./ sum(block);%歸一化feature{(i-1)*(n-1)+j} = block;end end%% 6、圖像的HOG特征值 [m, n] = size(feature); l = 2 * 2 * orient; featureVec = zeros(1, n * l); for i = 1:nfeatureVec((i-1)*l+1:i*l) = feature{i}(:); end運(yùn)行后,我們再來大概計算一下參數(shù),看看與結(jié)果的維度是否一致。
測試圖片采用的是lena的那張標(biāo)準(zhǔn)圖像。
首先讀入的圖片大小是512*512。
一個cell的大小是8×8=648×8=64,一個block有2×2=42×2=4個cell。
一個block大小為(2×8)×(2×8)=16×16=256(2×8)×(2×8)=16×16=256個像素。
由于圖像長寬均為512,且可以整除16,故不需要對圖像縮放。
使用R-HOG,則共有(512/8?1)×(512/8?1)=63×63=3969(512/8?1)×(512/8?1)=63×63=3969個block。
feature變量保存了每個block的HOG特征向量,matlab中可以看到正好一致。
對于每個cell,其提取出的HOG特征向量有9個bins,即9維特征向量。則每個block有4×9=364×9=36維特征向量。
那么,整幅圖像共有36×3969=14288436×3969=142884維HOG特征向量。
featureVec變量中保存了展開的所有HOG特征向量,可以看到與計算結(jié)果一致:
2、opencv行人檢測
#include <iostream> #include <opencv2/opencv.hpp>int main() {cv::Mat img = cv::imread("test.jpg");cv::HOGDescriptor hog(cv::Size(64, 128), cv::Size(16, 16), cv::Size(8, 8), cv::Size(8, 8), 9);hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());std::vector<cv::Rect> regions;hog.detectMultiScale(img, regions, 0, cv::Size(8, 8), cv::Size(32, 32), 1.05, 1);// 顯示for (size_t i = 0;i < regions.size();i++){cv::rectangle(img, regions[i], cv::Scalar(0, 0, 255), 2);}cv::imshow("行人檢測", img);cv::waitKey();return 0; }opencv中集成了HOG特征算子和訓(xùn)練好的用于行人檢測的SVM分類器,偷下懶就不介紹函數(shù)api了,請自行查詢文檔。
運(yùn)行結(jié)果如下:
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的HOG特征检测学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自适应中值滤波及实现
- 下一篇: 基于Python编写的简易翻译器