本文共 4055 字,大约阅读时间需要 13 分钟。
HOG:从理论到OpenCV实践
一、理论
HOG(Histogram of Oriented Gradients)特征描述子是一种基于图像局部区域的密集型描述符,通过计算局部区域的梯度方向直方图来构成特征。本文将详细介绍HOG的理论基础及其在OpenCV中的实现。
1、HOG特征描述子的定义
HOG特征描述子是局部归一化的梯度方向直方图。具体来说,是对图像局部区域的密集型描述,通过计算局部区域的梯度方向直方图来构成特征。这种方法能够有效地捕捉图像中局部形状信息。
2、本质
HOG描述子通过统计图像局部区域的梯度方向信息,作为该局部图像区域的表征。它能够提供图像局部区域的密集描述,同时具有一定的鲁棒性,能够弱化光照变化的影响。
3、OpenCV中的HOG算法来源
HOG算法的实现源自2005年CVPR会议的一篇论文。本文将重点介绍其在OpenCV中的实现方法。
二、OpenCV中的HOG算法实现
4、HOG描述子的实现细节
(1)参数设置
- 检测窗口:WinSize=128×64像素,滑动步长为8像素(水平和垂直均为8像素)。
- 块大小:BlockSize=16×16像素,检测窗口中块的滑动步长为8像素。
- 单元格大小:CellSize=8×8像素。
- 梯度方向:每个单元格内统计9个方向的梯度直方图。
(2)HOG描述子
OpenCV中一个HOG描述子是针对一个检测窗口而言的。一个检测窗口包含105个Block,每个Block包含4个Cell。每个Cell的HOG描述子向量长度为9维,因此一个检测窗口的HOG描述子向量总长度为:[105 \times 4 \times 9 = 3780 \text{维}]
5、HOG特征提取过程
(1)图像预处理
(2)梯度计算
计算图像中每个像素的梯度,包括梯度方向和模长。梯度计算使用水平和垂直边缘算子:[\text{水平边缘算子} = [-1, 0, 1]][\text{垂直边缘算子} = [-1, 0, 1]^T]每个像素的梯度方向由这两个算子计算得出。
(3)单元格划分
将图像划分为8×8像素的单元格(Cell)。每个单元格内计算梯度方向直方图。
(4)梯度直方图统计
每个单元格统计9个方向的梯度直方图。每个像素的梯度方向对应到直方图中的特定bin,并根据梯度模长进行加权投票。
(5)加权投票
采用三线性插值方法,将像素的梯度模长作为权值投入对应的bin中。这种插值方法能够有效减少混叠效应,避免边界和量化带来的突变。
(6)块归一化
将多个单元格组合成一个块,计算块内的梯度直方图并进行归一化。OpenCV支持四种归一化方法:
- L2-norm
- L1-norm
- L1-sqrt
- L2-Hys(结合L2归一化和截断)
通过归一化,可以有效压缩梯度强度的变化范围,减少光照和阴影对特征的影响。
三、OpenCV中的HOG函数说明
1、HOGDescriptor类
(1)构造函数
gpu::HOGDescriptor::HOGDescriptor(Size win_size, Size block_size, Size block_stride, Size cell_size, int nbins, double win_sigma, double threshold_L2hys, bool gamma_correction, int nlevels)
参数说明:
win_size:检测窗口大小,默认为128×64。block_size:块大小,默认为16×16。block_stride:块滑动步长,默认为8×8。cell_size:单元格大小,默认为8×8。nbins:直方图bin数量,默认为9。win_sigma:高斯滤波窗口参数,默认值由函数定义。threshold_L2hys:L2-Hys归一化收缩率,默认为0.2。gamma_correction:是否进行Gamma校正,默认为true。nlevels:检测窗口的最大数量,默认值由函数定义。
(2)getDescriptorSize函数
获取检测窗口的HOG特征向量维数:
size_t gpu::HOGDescriptor::getDescriptorSize() const
(3)getBlockHistogramSize函数
获取块的直方图大小:
size_t gpu::HOGDescriptor::getBlockHistogramSize() const
2、SVM检测器设置
void gpu::HOGDescriptor::setSVMDetector(const vector& detector)
3、获取默认检测器
static vectorgpu::HOGDescriptor::getDefaultPeopleDetector()
4、多尺度检测
void gpu::HOGDescriptor::detectMultiScale(const GpuMat& img, vector& found_locations, double hit_threshold, Size win_stride, Size padding, double scale0, int group_threshold)
5、特征提取
void gpu::HOGDescriptor::compute(const Mat& img, vector& descriptors, Size win_stride, Size padding, const vector & locations) const
6、梯度计算
void HOGDescriptor::computeGradient(const Mat& img, Mat& grad, Mat& qangle, Size paddingTL, Size paddingBR) const
四、示例代码
1、行人检测
#include#include #include #include using namespace cv;int main(int argc, char** argv) { Mat img = imread(argv[1]); if (argc != 2 || !img.data) { printf("没有图片\n"); return -1; } HOGDescriptor defaultHog; defaultHog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); vector found; defaultHog.detectMultiScale(img, found); for (int i = 0; i < found.size(); i++) { Rect r = found[i]; rectangle(img, r.tl(), r.br(), Scalar(0, 0, 255), 3); } namedWindow("检测行人", CV_WINDOW_AUTOSIZE); imshow("检测行人", img); waitKey(0); return 0;}
2、HOG特征提取
#include#include #include using namespace cv;int main(int argc, char** argv) { Mat img = imread(argv[1]); if (argc != 2 || !img.data) { printf("没有图片\n"); return -1; } HOGDescriptor defaultHog; vector descriptors; defaultHog.compute(img, descriptors, Size(8,8), Size(0,0)); printf("特征向量大小:%zu\n", descriptors.size()); for (int j=0; j<3780; j++) { printf("%f,", descriptors[j]); } printf("\n"); return 0;}
五、总结
1、HOG与SIFT的区别
- SIFT:基于关键点特征向量,需要对图像进行尺度空间下的极值点检测。
- HOG:将图像均匀划分为块和单元格,统计每个单元格内的梯度方向直方图。
2、HOG的优缺点
- 优点:
- 表示边缘结构特征,描述局部形状信息。
- 归一化处理能够部分抵消光照变化影响。
- 位置和方向的量化能抑制平移和旋转带来的影响。
- 缺点:
- 特征提取过程较为复杂,速度较慢。
- 对噪点敏感,容易受到遮挡的影响。
通过以上内容,可以看出HOG是一种高效的特征提取方法,广泛应用于行人检测等任务中。
发表评论
最新留言
关于作者