其他分享
首页 > 其他分享> > 【opencv学习笔记】HOG+SVM特征点检测

【opencv学习笔记】HOG+SVM特征点检测

作者:互联网

1、HOG特征:

方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。需要提醒的是,HOG+SVM进行行人检测的方法是法国研究人员Dalal在2005的CVPR上提出的,而如今虽然有很多行人检测算法不断提出,但基本都是以HOG+SVM的思路为主。

2、SIFT、HOG、LBP

SIFT、HOG、LBP,这三者都属于局部特征。
一、三者原理上的区别

3、HOG特征提取算法的实现过程:

大概过程:

HOG特征提取方法就是将一个image(你要检测的目标或者扫描窗口):

1)灰度化(将图像看做一个x,y,z(灰度)的三维图像);

2)采用Gamma(可以取1/2)校正法对输入图像进行颜色空间的标准化(归一化);目的是调节图像的对比度,降低图像局部的阴影和光照变化所造成的影响,同时可以抑制噪音的干扰;

3)计算图像每个像素的梯度(包括大小和方向);主要是为了捕获轮廓信息,同时进一步弱化光照的干扰。

4)将图像划分成小cells(例如6*6像素/cell);

5)统计每个cell的梯度直方图(不同梯度的个数),即可形成每个cell的descriptor;

6)将每几个cell组成一个block(例如3*3个cell/block),一个block内所有cell的特征descriptor串联起来便得到该block的HOG特征descriptor。

7)将图像image内的所有block的HOG特征descriptor串联起来就可以得到该image(你要检测的目标)的HOG特征descriptor了。这个就是最终的可供分类使用的特征向量了。

总的来说就是计算方向梯度直方图

那么该怎么计算呢?

1、预处理

通常把图像调整成64*128。这里在opencv可以直接用resize()函数既可;

2、计算梯度图像

可以直接用OpenCV里面的kernel大小为1的Sobel算子来计算。
分别计算x、y方向的梯度;

Mat gx, gy;
Sobel(img, gx, CV_32F, 1, 0, 1);
Sobel(img, gy, CV_32F, 0, 1, 1);

接着,用下面的公式来计算梯度的幅值g和方向theta:
在这里插入图片描述

// C++ Calculate gradient magnitude and direction (in degrees)
Mat mag, angle;
cartToPolar(gx, gy, mag, angle, 1);

x轴方向的梯度主要凸显了垂直方向的线条,y轴方向的梯度凸显了水平方向的梯度,梯度幅值凸显了像素值有剧烈变化的地方。可以通过梯度图像轻易的寻找到人体
在每个像素点,都有一个幅值(magnitude)和方向,对于有颜色的图片,会在三个channel上都计算梯度。那么相应的幅值就是三个channel上最大的幅值,角度(方向)是最大幅值所对应的角。

3、在8*8像素的网格(cell)中计算梯度直方图

将图片分割成88的网格,每四个方格为一个块。为什么要用8 * 8?用特征描述子的一个主要原因是它提供了一个紧凑(compact)/压缩的表示。一个88的图像有883=192个像素值,每个像素有两个值(幅值magnitude和方向direction,三个channel取最大magnitude那个),加起来就是882=128,后面我们会看到这128个数如何用一个9个bin的直方图来表示成9个数的数组。
在这里插入图片描述
直方图是有9个bin的向量,代表的是角度0,20,40,60…160。
在这里插入图片描述中间: 一个网格用箭头表示梯度 右边: 这个网格用数字表示的梯度

中间这个图的箭头是梯度的方向,长度是梯度的大小,可以发现箭头的指向方向是像素强度变化方向,幅值是强度变化的大小。
下一步就是为这些8*8的网格创建直方图,直方图包含了9个bin来对应0,20,40,…160这些角度。

下面这张图解释了这个过程。我们用了上一张图里面的那个网格的梯度幅值和方向。根据方向选择用哪个bin, 根据幅值来确定这个bin的大小。先来看蓝色圆圈圈出来的像素点,它的角度是80,幅值是2,所以它在第五个bin里面加了2,再来看红色的圈圆圈圈出来的像素点,它的角度是10,幅值是4,因为角度10介于0-20度的中间(正好一半),所以把幅值一分为二地放到0和20两个bin里面去。
加粗样式梯度直方图

这里有个细节要注意,如果一个角度大于160度,也就是在160-180度之间,我们知道这里角度0,180度是一样的,所以在下面这个例子里,像素的角度为165度的时候,要把幅值按照比例放到0和160的bin里面去。
在这里插入图片描述把这8*8的cell里面所有的像素点都分别加到这9个bin里面去,就构建了一个9-bin的直方图,上面的网格对应的直方图如下:
在这里插入图片描述

4、16*16块归一化

我们希望我们的特征描述子可以和光线变换无关,所以我们就想让我们的直方图归一化从而不受光线变化影响。
先考虑对向量用l2归一化的步骤是:
v = [128, 64, 32]
[(128^2) + (64^2) + (32^2) ]^0.5=146.64
把v中每一个元素除以146.64得到[0.87,0.43,0.22]
考虑另一个向量2*v,归一化后可以得到向量依旧是[0.87, 0.43, 0.22]。你可以明白归一化是把scale给移除了
在这里插入图片描述

5、计算HOG特征向量

为了计算这整个patch的特征向量,需要把36*1的向量全部合并组成一个巨大的向量。向量的大小可以这么计算:

我们有多少个16*16的块?水平7个,垂直15个,总共有7*15=105次移动。

每个16*16的块代表了(4个8*8 每个小cell中有9个bin)36*1的向量。所以把他们放在一起也就是36*105=3780维向量。

可视化HOG

通常HOG特征描述子是画出88网格中91归一化的直方图,见下图。你可以发现直方图的主要方向捕捉了这个人的外形,特别是躯干和腿。
在这里插入图片描述

行人检测(HOG+SVM)

原理可以查看:https://blog.csdn.net/qq_26898461/article/details/46786033

函数代码:

1、HOG构造函数

C++: gpu::HOGDescriptor::HOGDescriptor(Size win_size=Size(64, 128), 
                      Size block_size=Size(16, 16), 
                      Size block_stride=Size(8, 8),
                      Size cell_size=Size(8, 8), 
                      int nbins=9, 
                      double win_sigma=DEFAULT_WIN_SIGMA, 
                      double threshold_L2hys=0.2, 
                      bool gamma_correction=true, 
                      int nlevels=DEFAULT_NLEVELS
                      )

参数注释:
<1> win_size:检测窗口大小。
<2> block_size:块大小,目前只支持Size(16, 16)。
<3> block_stride:块的滑动步长,大小只支持是单元格cell_size大小的倍数。
<4> cell_size:单元格的大小,目前只支持Size(8, 8)。
<5> nbins:直方图bin的数量(投票箱的个数),目前每个单元格Cell只支持9个。
<6> win_sigma:高斯滤波窗口的参数。
<7> threshold_L2hys:块内直方图归一化类型L2-Hys的归一化收缩率
<8> gamma_correction:是否gamma校正
<9> nlevels:检测窗口的最大数量


2、getDefaultPeopleDetector 函数
(1)作用:获取行人分类器(默认检测窗口大小)的系数(获得3780维检测算子)
(2)函数原型:
C++: static vector gpu::HOGDescriptor::getDefaultPeopleDetector()

3、setSVMDetector 函数
(1)作用:设置线性SVM分类器的系数
(2)函数原型:
C++: void gpu::HOGDescriptor::setSVMDetector(const vector& detector)

4、detect 函数
(1)作用:用没有多尺度的窗口进行物体检测
(2)函数原型:

C++: void gpu::HOGDescriptor::detect(const GpuMat& img, 
                     vector& found_locations, 
                     double hit_threshold=0, 
                     Size win_stride=Size(), 
                     Size padding=Size()
                     )  

(3)参数注释
<1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
<2>found_locations:检测出的物体的边缘。
<3>hit_threshold:特征向量和SVM划分超平面的阀值距离。通常它为0,并应由检测器系数决定。但是,当系数被省略时,可以手动指定它。
<4>win_stride:窗口步长,必须是块步长的整数倍。
<5>padding:模拟参数,使得CUP能兼容。目前必须是(0,0)。

5、detect 函数
(1)作用:用没有多尺度的窗口进行物体检测
(2)函数原型:

C++: void gpu::HOGDescriptor::detect(const GpuMat& img, 
                     vector& found_locations, 
                     double hit_threshold=0, 
                     Size win_stride=Size(), 
                     Size padding=Size()
                     ) 

(3)参数注释
<1>img:源图像。只支持CV_8UC1和CV_8UC4数据类型。
<2>found_locations:检测出的物体的边缘。
<3>hit_threshold:特征向量和SVM划分超平面的阀值距离。通常它为0,并应由检测器系数决定。但是,当系数被省略时,可以手动指定它。
<4>win_stride:窗口步长,必须是块步长的整数倍。
<5>padding:模拟参数,使得CUP能兼容。目前必须是(0,0)。

代码展示

# include<opencv2\opencv.hpp>
# include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("E:/tuku/xingren1.jpg");
	if (src.empty()) {
		cout << "can't find this picture...";
		return -1;
	}
	imshow("input", src);
	namedWindow("out put", 1);
	//HOG特征点检测 
	Mat 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> descripts;
	vector<Point> location;
	detector.compute(dst_gray, descripts, Size(0, 0), Size(0, 0), location);
	printf("number of HOG descripts:%d\n", descripts.size());
    //HOG+SVM行人检测
	HOGDescriptor hog = HOGDescriptor();
	hog.setSVMDetector(hog.getDefaultPeopleDetector());
	vector<Rect> foundlocationgs;
	Mat reslut = src.clone();
	hog.detectMultiScale(src, foundlocationgs, 0, Size(8, 8), Size(4, 4), 1.05, 2);
	for (size_t i = 0; i < foundlocationgs.size(); i++) {
		rectangle(reslut, foundlocationgs[i], Scalar(0, 0, 255), 2, 8, 0);
	}
	imshow("out put", reslut);
	waitKey(0);
	return 0;
}

效果图展示

在这里插入图片描述

在这里插入图片描述

标签:HOG,SVM,梯度,像素,cell,opencv,直方图,Size
来源: https://blog.csdn.net/CSDNjpl/article/details/99003682