HOG特征检测,它是通过计算局部区域的梯度方向直方图来构成特征。
(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;
}
运行截图: