本文为原创文章,未经本人允许,禁止转载。转载请注明出处。
1.HOG特征检测
👉【论文阅读】Histograms of Oriented Gradients for Human Detection。
2.cv::HOGDescriptor
使用cv::HOGDescriptor
构建HOGDescriptor对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
cv::HOGDescriptor::HOGDescriptor (
Size _winSize,
Size _blockSize,
Size _blockStride,
Size _cellSize,
int _nbins,
int _derivAperture = 1,
double _winSigma = -1,
int _histogramNormType = HOGDescriptor::L2Hys,
double _L2HysThreshold = 0.2,
bool _gammaCorrection = false,
int _nlevels = HOGDescriptor::DEFAULT_NLEVELS,
bool _signedGradient = false
)
参数详解:
_winSize
:检测窗口大小。HOG原文和API的默认值都是$64 \times 128$。_blockSize
:block的大小(单位是像素)。HOG原文和API默认值都是$(16,16)$。_blockStride
:block滑动步长(单位是像素)。HOG原文和API默认值都是$(8,8)$。_cellSize
:cell的大小(单位是像素)。HOG原文和API默认值都是$(8,8)$。_nbins
:直方图bin的数量。HOG原文和API默认值都是9个。_derivAperture
:官方文档中没有对这个参数的详细解释。cv::Canny
中有个参数apertureSize
指的是Sobel算子的size。这里该参数的默认值为1,即Sobel算子的size为1,刚好就是HOG原文中认为最好的计算梯度的方式:$[-1,0,1]$。此外,该参数还被质疑并没有在HOGDescriptor class中被使用,详见github issue:derivAperture, histogramNormType not used in HOGDescriptor。_winSigma
:个人理解是HOG原文中Gaussian spatial window的$\sigma$值,用于对梯度幅值进行高斯加权,原文默认值是8。API中默认值是-1,猜测可能是不进行高斯加权的意思。在这里找到的解释是“Gaussian smoothing window parameter.”,但HOG原文中提到过在梯度计算之前就对原始图像进行平滑会使性能下降。_histogramNormType
:归一化方式。HOG原文中提到了4种归一化方式:L2-norm、L2-Hys、L1-norm、L1-sqrt。这里默认是L2-Hys归一化。_L2HysThreshold
:L2-Hys归一化对最大值的限制,详见HOG原文,默认值为0.2。_gammaCorrection
:是否使用gamma correction。_nlevels
:在这里找到了对该参数的定义:“Maximum number of detection window increases.”,即检测窗口最多可增加的数量。_signedGradient
:是否使用带符号的梯度,详见HOG原文。
3.cv::HOGDescriptor::compute
使用compute
函数来计算HOG特征。
1
2
3
4
5
6
7
virtual void cv::HOGDescriptor::compute (
InputArray img,
std::vector< float > & descriptors,
Size winStride = Size(),
Size padding = Size(),
const std::vector< Point > & locations = std::vector< Point >()
) const
参数详解:
img
:用于计算HOG特征的输入图像,类型为CV_8U
。descriptors
:计算得到的HOG特征向量,类型为CV_32F
。如果检测窗口的大小为$64 \times 128$,block、cell、步长等参数都是默认值,那么一个窗口有$7 \times 15 = 105$个block,其特征向量长度为$105 \times 36 = 3780$。winStride
:检测窗口的步长,必须是block步长的倍数。padding
:用于对输入图像做padding。locations
:检测到的特征点。
核心实现代码:
1
2
3
4
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);
4.HOG+SVM实现对行人检测
核心实现代码:
1
2
3
4
HOGDescriptor hog = HOGDescriptor();
hog.setSVMDetector(hog.getDefaultPeopleDetector());
vector<Rect> foundLocations;
hog.detectMultiScale(src, foundLocations, 1, Size(8, 8), Size(32, 32), 1.05, 2);
4.1.cv::HOGDescriptor::getDefaultPeopleDetector
1
static std::vector<float> cv::HOGDescriptor::getDefaultPeopleDetector ( )
返回为行人检测已经训练好的分类器的系数(适用于$64 \times 128$的检测窗口)。一个检测窗口得到的HOG特征向量长度为3780,但还要考虑到偏置项$b$,所以这里这个函数返回的系数会是3781维的。
opencv已经预训练好了一个线性SVM行人检测模型。
4.2.cv::HOGDescriptor::setSVMDetector
1
virtual void cv::HOGDescriptor::setSVMDetector ( InputArray _svmdetector )
设置线性SVM分类器的系数。上述例子中我们直接使用opencv已经训练好的SVM模型。
4.3.cv::HOGDescriptor::detectMultiScale
用于检测输入图像中大小不同的目标。检测到的目标以矩形列表的形式返回。
1
2
3
4
5
6
7
8
9
10
11
virtual void cv::HOGDescriptor::detectMultiScale (
InputArray img,
std::vector< Rect > & foundLocations,
std::vector< double > & foundWeights,
double hitThreshold = 0,
Size winStride = Size(),
Size padding = Size(),
double scale = 1.05,
double groupThreshold = 2.0,
bool useMeanshiftGrouping = false
) const
img
:输入图像。类型为CV_8U
或CV_8UC3
。foundLocations
:一个元素为rect的vector,每个rect对应一个被检测到的目标。foundWeights
:一个vector,对应每个被检测目标的confidence。hitThreshold
:是针对HOG特征向量到SVM分类平面的欧氏距离的一个阈值。通常设为0。当距离大于该阈值时,检测结果被接受,否则检测结果会被拒绝。设置此参数可有效降低假阳的出现。winStride
:检测窗口的步长,必须是block步长的倍数。padding
:对输入图像的padding操作。scale
:用于缩放检测窗口的大小。groupThreshold
:同一个目标可能会被多个检测框圈住,因此我们可以对这些检测框进行聚类。该参数用于指定聚类的半径。检测框中心距离小于groupThreshold
的将会被聚类成一个框。如果该参数为0,则表示不进行聚类操作。opencv有的版本也将该参数写为finalThreshold
。useMeanshiftGrouping
:聚类的算法。
另一种重载形式:
1
2
3
4
5
6
7
8
9
10
virtual void cv::HOGDescriptor::detectMultiScale (
InputArray img,
std::vector< Rect > & foundLocations,
double hitThreshold = 0,
Size winStride = Size(),
Size padding = Size(),
double scale = 1.05,
double groupThreshold = 2.0,
bool useMeanshiftGrouping = false
) const
检测结果: