HOG特征检测

HOG特征检测,它是通过计算局部区域的梯度方向直方图来构成特征。

其中检测窗口Win、块Block、单元格Cell的基本信息

(1)大小:

A、检测窗口:WinSize=128*64像素,在图像中滑动的步长是8像素(水平和垂直都是)

B、块:BlockSize=16*16像素,在检测窗口中滑动的步长是8像素(水平和垂直都是)

C、单元格:CellSize=8*8像素

D、梯度方向:一个Cell的梯度方向分为9个方向,在一个单元格内统计9个方向的梯度直方图

(2)HOG描述子

    OpenCV中一个Hog描述子是针对一个检测窗口而言的,一个检测窗口有((128-16)/8+1)*((64-16)/8+1)=105个Block,一个Block有4个Cell,一个Cell的Hog描述子向量的长度是9,所以一个检测窗口的Hog描述子的向量长度是105*4*9=3780维。

    HOG特征提取是统计梯度直方图特征。具体来说就是将梯度方向(0->360°)划分为9个区间,将图像化为16x16的若干个block,每个block再化为4个cell(8x8)。对每一个cell,算出每一像素点的梯度方向和模,按梯度方向增加对应bin的值,最终综合N个cell的梯度直方图形成一个高维描述子向量。实际实现的时候会有各种插值

1、HOG与SIFT的区别

    HOG和SIFT都是描述子,以及由于在具体操作上有很多相似的步骤,所以致使很多人误认为HOG是SIFT的一种,其实两者在使用目的和具体处理细节上是有很大的区别的。HOG与SIFT的主要区别如下:

(1)SIFT是基于关键点特征向量的描述。

(2)HOG是将图像均匀的分成相邻的小块,然后在所有的小块内统计梯度直方图。

(3)SIFT需要对图像尺度空间下对像素求极值点,而HOG中不需要。

(4)SIFT一般有两大步骤,第一个步骤对图像提取特征点,而HOG不会对图像提取特征点。

2、HOG的优缺点

优点:

(1)HOG表示的是边缘(梯度)的结构特征,因此可以描述局部的形状信息;

(2)位置和方向空间的量化一定程度上可以抑制平移和旋转带来的影响;

(3)采取在局部区域归一化直方图,可以部分抵消光照变化带来的影响;

(4)由于一定程度忽略了光照颜色对图像造成的影响,使得图像所需要的表征数据的维度降低了;

(5)而且由于这种分块分单元的处理方法,也使得图像局部像素点之间的关系可以很好得到表征。

缺点:

(1)描述子生成过程冗长,导致速度慢,实时性差;

(2)很难处理遮挡问题;

(3)由于梯度的性质,该描述子对噪点相当敏感。

hog特征检测代码示例(需要objdetect库):

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main(int argc, char** argv) 
{
	Mat src = imread("D:/cv400/data/lena.jpg");
	if (src.empty()) 
	{
		cout << "Load image error..." << endl;
		return -1;
	}
	

	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);
	cout<<"number of HOG descriptors : "<<descriptors.size()<<endl;
	imshow("input image", src);
	waitKey();
	return 0;
}

程序运行截图:

最后检测出3780维向量。

实际上Hog更多的用在 Hog+SVM 行人检测上

Hog+SVM行人检测代码示例

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main(int argc, char** argv) 
{
	Mat src = imread("D:/cv400/person.png");
	if (src.empty()) 
	{
		cout << "Load image error..." << endl;
		return -1;
	}
	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);
	
	imshow("HOG SVM Detector Demo", result);

	waitKey();
	return 0;
}

运行截图:

猜你喜欢

转载自blog.csdn.net/andylanzhiyong/article/details/84678447