HOG是什么?
HOG全称是Histogram of oriented gradient,顾名思义梯度方向直方图,也就是带方向的梯度直方图。它是一种手工提取图片特征的方式,通过统计图像局部区域的梯度方向信息来作为该局部图像区域的特征。
HOG特征的求取方法?
1)灰度化
2)计算每个像素的梯度(大小、方向)
3)将图像分成小cells,每3*3个cell组成1个block
4)统计每个cell的梯度直方图,每个cell都有一个特征
5)每个cell的特征串起来得到block的特征
6)将每个block的特征串起来归一化后便得到整张图片的特征了
1、灰度化
灰度化的方法可以使用opencv的工具包
image_gray
2、计算每个图像的梯度
- 梯度
梯度:
对应到图片上:位置每变化一,亮度值变化多少
![e38b9104b1acd1b9a8e71bc9d0e5d317.png](https://i-blog.csdnimg.cn/blog_migrate/a8d4563fb1984e59684acc24b01157dd.png)
图像上有两个维度的梯度:x方向和y方向,如x方向(红色箭头方向)像素值121->10->78,数值发生了变化,也就产生了梯度。梯度大的地方也就是颜色发生变化大的地方,多是图像中物体的边缘、轮廓等,所以通过梯度的信息可以找到图像中物体的特征。
![a5f828cc7090984ed1e36b06e94f2e9c.png](https://i-blog.csdnimg.cn/blog_migrate/0cf65fb4c53b8079b49a2087fa9efd46.png)
- 方法
分别对x方向和y方向求每个像素点的梯度以及梯度方向,使用水平边缘算子[-1,0,1]和垂直边缘算子[-1,0,1]T ,对于边缘的点可以不求梯度也可以在外圈补零。对上图152这个像素点来说:
x方向变化(Gx)= 68-48 = 20
y方向变化(Gy)= 78 - 10 = 68
这点的模长 =
梯度方向
由此图片的一个像素点对应三个值
![e8d6160bd7a49c5cb7e73f6aca40e433.png](https://i-blog.csdnimg.cn/blog_migrate/9f90d4edb188ce70ee83e4d136657bd9.jpeg)
def s_x(img): #dx
kernel = np.array([[-1, 0, 1]])
imgx = signal.convolve2d(img, kernel, boundary='symm', mode='same')
return imgx
def s_y(img): #dy
kernel = np.array([[-1, 0, 1]]).T
imgy = signal.convolve2d(img, kernel, boundary='symm', mode='same')
return imgy
def grad(img): #模长
imgx = s_x(img)
imgy = s_y(img)
s = np.sqrt(imgx ** 2 + imgy ** 2)
theta = np.arctan2(imgx,imgy)
theta = np.degrees(theta)#显示角度值
#print('theta{}'.format(theta))
theta[theta < 0] = np.pi + theta[theta < 0]
return (s, theta)
3、将图像分成小cells
![f3168f3c0822b6cd3d4a1fd4886a19ca.png](https://i-blog.csdnimg.cn/blog_migrate/b46fac3fe3d445b19f277f115f2bc950.png)
4、统计每个cell的梯度直方图,每个cell都有一个特征
将360度分成bin份,对应每个像素点的角度值将其模长放入对应bin区域,对应完整个cell的像素点,将对应bin内的模长累加,便得到这个cell的特征向量了。下图所示bin=8,A、B、C三点是cell中的三个像素点。
![9dbf82f2d0d649f0d03836afd282580a.png](https://i-blog.csdnimg.cn/blog_migrate/4c6455ca04ab200612d703bbd0325083.png)
![341d9d0a49f16c6dfd089461521e2eb2.png](https://i-blog.csdnimg.cn/blog_migrate/8e408a1fc3224bdfbebd62e85fa4b6ca.png)
cell_size = 6 #cell 6*6个像素点组成一个cell
bin_size = 8 #360°分8份,8个bin
angle_unit = 360 / bin_size #每个bin的度数
gradient_magnitude = abs(gradient_magnitude) #取模长的绝对值
cell_gradient_vector = np.zeros((int(height / cell_size), int(width / cell_size), bin_size))#整张图片对应多少个cell
def cell_gradient(cell_magnitude, cell_angle): #每个cell的特征
orientation_centers = [0] * bin_size #建立一个全零的cell的特征向量
for k in range(cell_magnitude.shape[0]): #cell是6*6的,遍历每一个像素点
for l in range(cell_magnitude.shape[1]):
gradient_strength = cell_magnitude[k][l] #对应的这个像素点的模长
gradient_angle = cell_angle[k][l] #对应的这个像素点的角度
angle = int(gradient_angle / angle_unit)#角度值除以均分的每一部分的度数,整数部分是几就在第几个bin中
orientation_centers[angle] = orientation_centers[angle]+ gradient_strength#将模长放入对应的bin中,每个bin的值不断累加更新
return orientation_centers #返回cell的特征向量
5、每个cell的特征串起来得到block的特征
![eff4d62b102849088b12f41c4c0a20da.png](https://i-blog.csdnimg.cn/blog_migrate/cf8b65a256fcf58f64d01e5bd95b74d4.png)
6、将每个block的特征串起来归一化后便得到整张图片的特征了
for i in range(cell_gradient_vector.shape[0]): #遍历所有cell
for j in range(cell_gradient_vector.shape[1]):
cell_magnitude = gradient_magnitude[i * cell_size:(i + 1) * cell_size, #取出图片上对应cell的模长
j * cell_size:(j + 1) * cell_size]
cell_angle = gradient_angle[i * cell_size:(i + 1) * cell_size, #取出图片上对应cell的角度
j * cell_size:(j + 1) * cell_size]
cell_gradient_vector[i][j] = cell_gradient(cell_magnitude, cell_angle) #将所有cell的特征向量串到一起
feature = cell_gradient_vector[i][j] #得到整张图片的feature
return feature
代码完整版
yuzhangzhang/Deep-learning-computer-visiongithub.com![13d609180149256f14554da1df67af83.png](https://i-blog.csdnimg.cn/blog_migrate/92cae0acbdf8d3c048e540f8bc22c8ff.png)