HOG+SVM的工作流程如下:
1.首先对输入的图片进行预处理
2.然后计算像素点的梯度特特性,包括梯度幅值和梯度方向。
3.然后投票统计形成梯度直方图,然后对blocks进行normalize
4.最后收集到HOG feature(其实是一行多维的vector)放到SVM里进行监督学习,从而实现行人的检测。
下面我们将对上述HOG的主要步骤进行学习。
1.2 HOG特征的原理
1.2.1 图像预处理
1.灰度变换
2.伽马矫正:
调节图像对比度,减少光照对图像的影响(包括光照不均和局部阴影),使过曝或者欠曝的图像恢复正常,更接近人眼看到的图像。
伽马矫正公式:
f(I)=Iγf(I)=I^\gammaf(I)=I
γ
III表示图像,γ\gammaγ表示幂指数。
如图,当γ\gammaγ取不同的值时对应的输入输出曲线( γ=1\gamma=1γ=1时输入输出保持一致) :
1) 当γ<1\gamma<1γ<1时,输入图像的低灰度值区域动态范围变大,进而图像低灰度值区域对比度得以增强;在高灰度值区域,动态范围变小,进而图像高灰度值区域对比度得以降低。 最终,图像整体的灰度变亮。
2) 当γ>1\gamma>1γ>1时,输入图像的高灰度值区域动态范围变小,进而图像低灰度值区域对比度得以降低;在高灰度值区域,动态范围变大,进而图像高灰度值区域对比度得以增强。 最终,图像整体的灰度变暗。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('*.png', 0)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img2 = np.power(img/float(np.max(img)),1/2.2)
plt.imshow(img2)
plt.axis('off')
plt.show()
1.2.2 计算图像梯度
为了得到梯度直方图,那么首先需要计算图像水平方向和垂直方向梯度。
一般使用特定的卷积核对图像滤波实现,可选用的卷积模板有:soble算子、Prewitt算子、Roberts模板等等。
一般采用soble算子,OpenCV也是如此,利用soble水平和垂直算子与输入图像卷积计算dxdxdx、dydydy:
进一步可以得到图像梯度的幅值:
为了简化计算,幅值也可以作如下近似:
角度为:
这里需要注意的是:梯度方向和图像边缘方向是互相正交的。
mport cv2
import numpy as np
# Read image
img = cv2.imread('*.jpg')
img = np.float32(img) / 255.0 # 归一化
# 计算x和y方向的梯度
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=1)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=1)
# 计算合梯度的幅值和方向(角度)
mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)
opencv实现
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
if __name__ == '__main__':
src = cv.imread("*.jpg")
cv.imshow("input", src)
hog = cv.HOGDescriptor()
hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector())
# Detect people in the image
(rects, weights) = hog.detectMultiScale(src,
winStride=(2,4),
padding=(8, 8),
scale=1.2,
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-detector", src)
cv.imwrite("hog-detector.jpg",src)
cv.waitKey(0)
cv.destroyAllWindows()