引言:
HOG的核心思想是所检测的局部物体外形能够被光强梯度或边缘方向的分布所描述。通过将整幅图像分割成小的连接区域(称为cells),每个cell生成一个方向梯度直方图或者cell中pixel的边缘方向,这些直方图的组合可表示出(所检测目标的目标)描述子。为改善准确率,局部直方图可以通过计算图像中一个较大区域(称为block)的光强作为measure被对比标准化,然后用这个值(measure)归一化这个block中的所有cells.这个归一化过程完成了更好的照射/阴影不变性。与其他描述子相比,HOG得到的描述子保持了几何和光学转化不变性(除非物体方向改变)。因此HOG描述子尤其适合人的检测。
HOG的优点:
1.核心思想是所检测的局部物体外形能够被梯度或边缘方向的分布所描述,HOG能较好地捕捉局部形状信息,对几何和光学变化都有很好的不变性;
2.HOG是在密集采样的图像块中求取的,在计算得到的HOG特征向量中隐含了该块与检测窗口之间的空间位置关系。
HOG的缺陷:
1.很难处理遮挡问题,人体姿势动作幅度过大或物体方向改变也不易检测(这个问题后来在DPM中采用可变形部件模型的方法得到了改善);
2.跟SIFT相比,HOG没有选取主方向,也没有旋转梯度方向直方图,因而本身不具有旋转不变性(较大的方向变化),其旋转不变性是通过采用不同旋转方向的训练样本来实现的;
3.跟SIFT相比,HOG本身不具有尺度不变性,其尺度不变性是通过缩放检测窗口图像的大小来实现的;
此外,由于梯度的性质,HOG对噪点相当敏感,在实际应用中,在Block和Cell划分之后,对于得到各个像区域中,有时候还会做一次高斯平滑去除噪点。
HOG原理:
参考:
HOG特征(Histogram of Gradient)总结 https://blog.csdn.net/qq_29422251/article/details/51638087
HOG:从理论到OpenCV实践 https://blog.csdn.net/zhazhiqiang/article/details/21047207
HOG特征检测的原理及opencv API调用 - 生命在于折腾! - CSDN博客 https://blog.csdn.net/kuweicai/article/details/78981150
HOG特征的提取过程为:
- Gamma归一化;
- 计算梯度;
- 划分cell
- 组合成block,统计block直方图;
- 梯度直方图归一化;
- 收集HOG特征。
API:
参数含义说明:
<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:检测窗口的最大数量
窗口大小winSize:
块大小 blockSize:
块滑动增量blockStride:
胞元大小cellSize:
梯度方向直方图nbins
nBins表示在一个胞元(cell)中统计梯度的方向数目,例如nBins=9时,在一个胞元内统计9个方向的梯度直方图,每个方向为180/9=20度。
<1>img:源图像。
<2>descriptors:返回的HOG特征向量,descriptors.size是HOG特征的维数。
<3>winStride:窗口移动步长。Winstride告诉Hog每次移动一定量的检测窗口。
<4>padding:在输入图像的每一侧添加一定数量的额外像素。 <5>locations:对于正样本可以直接取(0,0),负样本为随机产生合理坐标范围内的点坐标。
<1>img:源图像
<2>foundLocations:存储检测到的目标位置 <3>hitThreshold: 特征与SVM分类平面之间距离的阈值
<4>winStride:窗口移动步长。Winstride告诉Hog每次移动一定量的检测窗口。
<5>padding:在输入图像的每一侧添加一定数量的额外像素。这样,检测窗口就被放置在输入图像之外一点。正是因为这种填充,Hog可以检测到非常接近输入图像边缘的人。适当的pad可以提高检测的准确率,常见的pad size 有(8, 8), (16, 16), (24, 24), (32, 32). <6>scale:检测窗口增长参数;scale在1.01-1.5这个区间.
为了检测到不同大小的目标,一般有两种做法:逐步缩小图像;或者,逐步放大检测窗口。缩小图像就是把图像长宽同时按照一定比例(默认1.1 or 1.2)逐步缩小,然后检测;放大检测窗口是把检测窗口长宽按照一定比例逐步放大,这时位于检测窗口内的特征也会对应放大,然后检测。
代码展示:
计算
#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main()
{
//待检测图像
Mat src = imread("F:\\visual studio\\Image\\women1.jpg");
if (src.empty())
{
cout << "Can't load the image" << endl;
return -1;
}
resize(src, src, Size(128, 256));
//转化为灰度图
Mat graysrc;
cvtColor(src, graysrc, COLOR_BGR2GRAY);
HOGDescriptor detector(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
//计算HOG特征描述子
vector<float>descriptor;
vector<Point> location;
detector.compute(graysrc, descriptor, Size(32, 32), Size(0, 0), location);
cout << descriptor.size() << endl;
cout << location.size() << endl;
}
结果展示:
HOG+SVM实现行人检测:
#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv2/xfeatures2d.hpp>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main()
{
//待检测图像
Mat src = imread("F:\\visual studio\\Image\\people1.jpg");
if (src.empty())
{
cout << "Can't load the image" << endl;
return -1;
}
//imshow("src", src);
HOGDescriptor hog;
hog.setSVMDetector(hog.getDefaultPeopleDetector());
vector<Rect> peopleLocations;
hog.detectMultiScale(src, peopleLocations, 0, Size(8, 8), Size(16, 16), 1.05);
for (int i = 0; i < peopleLocations.size(); i++)
{
rectangle(src, peopleLocations[i], Scalar(255, 0, 0), 2, LINE_AA, 0);
}
imshow("result", src);
waitKey(0);
}
效果展示: