HOG全称histogram of oriented gradients.如果翻译成中文就是方向梯度直方图。它可以用来表示图像的物体特征,因此能够检测出这类物体。。
简介
- 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。
- 特征在对象识别与模式匹配中是一种常见的特征提取算法,是基于本地像素块进行特征直方图提取的一种算法,对象局部的变形与光照影响有很好的稳定性。
- 它通过计算和统计图像局部区域的梯度方向直方图来构成特征。Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。
主要思想
- 在一副图像中,局部目标的表象和形状(appearance and shape)能够被梯度或边缘的方向密度分布很好地描述。(本质:梯度的统计信息,而梯度主要存在于边缘的地方)
- 把这些局部直方图在图像的更大的范围内(我们把它叫区间或block)进行对比度归一化(contrast-normalized),所采用的方法是:先计算各直方图在这个区间(block)中的密度,然后根据这个密度对区间中的各个细胞单元做归一化。通过这个归一化后,能对光照变化和阴影获得更好的效果.
优点
- 由于HOG是在图像的局部方格单元上操作,所以它对图像几何的和光学的形变都能保持很好的不变性,这两种形变只会出现在更大的空间领域上。
- 在粗的空域抽样、精细的方向抽样以及较强的局部光学归一化等条件下,只要行人大体上能够保持直立的姿势,可以容许行人有一些细微的肢体动作,这些细微的动作可以被忽略而不影响检测效果。
HOG特征描述子提取
提取过程
1. Gamma矫正
✔️ 为了提高检测器对关照等干扰因素的鲁棒性,需要对图像进行Gamma矫正,完成对整个图像的归一化,调整对比度,降低噪声影响;
G(x,y)=F(x,y)1/r 一般 r=1/2
2. 灰度化
3. 计算图像XY梯度和方向
使用sobel可以出水平和垂直方向的梯度:
12 | gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1) |
---|
利用公式求取梯度幅值和方向:
g=gx2 gy2θ=arctangygx
12 | # Opencv中使用:mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True) |
---|
4. 8x8网格方向梯度权重直方图统计
✔️ 流程:首先将图像划分成若干个块(Block),每个块又由若干个细胞单元(cell)组成,细胞单元由更小的单位像素(Pixel)组成,然后在每个细胞单元中对内部的所有像素的梯度方向进行统计。
- 默认HOG的描述子窗口为64x128, 窗口移动步长为 8x8
- 每个窗口的cell为8x8,每个block由4个cell组成,block移动步长为一个cell,因此可以得到7x15个block
HOG
- 直方图把180度分为9个bin,每个区间为20度,如果像素落在某个区间,就把该像素的直方图累计到对应区间的直方图上
直方图统计
- 每个block有4个cell,每个cell有9个向量值,即每个block有36个向量,所以整个窗口有7x15x36=3780个特征描述子。
5. 块描述子和特征向量归一化
✔️ 每个block可以得到4个9维的向量,需要再次进行一次归一化,这样可以进一步提高泛化能力,同传使用L2-nrom进行归一化(还有L1-norm, L1-sqrt,etc.)
v=v‖v‖22 ε2
整体流程图
HOG提取流程
OpenCV函数
hog = cv2.HOGDescriptor()
:创建HOG特征描述;hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector())
:创建HOG SVM行人检测器;- 多尺度检测API:
123456 | rects, weights = hog.detectMultiScale(img, foundLocations, hitThreshold = 0, winStride, padding, scale = 1.05, finalThreshold = 2.0, useMeanshiftGrouping = false) |
---|
输入
- Img --> 表示输入图像;
- foundLocations --> 表示发现对象矩形框;
- hitThreshold --> 表示SVM距离度量(特征与SVM分类超平面之间距离),默认0表示;
- winStride --> 表示窗口步长;
- padding --> 表示填充;
- scale --> 表示尺度空间;
- finalThreshold --> 最终阈值,默认为2.0;
- useMeanshiftGrouping --> 不建议使用,速度太慢;
PS:其中窗口步长与Scale对结果影响最大,特别是Scale,小的尺度变化有利于检出低分辨率对象,同时也会导致FP发生,高的可以避免FP但是会产生FN(对象漏检)。
行人检测代码示例
1234567891011121314151617181920 | import cv2 as cvsrc = cv.imread("people.png")cv.imshow("input", src)# hog特征描述hog = cv.HOGDescriptor()# 创建SVM检测器hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector())# 检测行人(rects, weights) = hog.detectMultiScale(src, winStride=(4, 4), padding=(8, 8), scale=1.25, useMeanshiftGrouping=False)for (x, y, w, h) in rects: cv.rectangle(src, (x, y), (x w, y h), (0, 255, 0), 2)cv.imshow("hog-people", src)cv.waitKey(0)cv.destroyAllWindows() |
---|
参考资料
- https://zhuanlan.zhihu.com/p/40960756
- https://blog.csdn.net/m0_61897853/article/details/123713892
- https://zhuanlan.zhihu.com/p/75705284