HOG 特征, histogram of oriented gradient, 梯度方向直方图特征, 作为提取基于梯度的特征, HOG 采用了统计的方式(直方图)进行提取. 其基本思路是将图像局部的梯度统计特征拼接起来作为总特征. 局部特征在这里指的是将图像划分为多个Block, 每个Block内的特征进行联合以形成最终的特征.
1.将图像分块: 以Block 为单位, 每个Block以一定的步长在图像上滑动, 以此来产生新的Block.
2.Block作为基本的特征提取单位, 在其内部再次进行细分: 将Block 划分为(一般是均匀划分)NxN的小块, 每个小块叫做cell.
3.cell是最基本的统计单元, 在cell内部, 统计每个像素的梯度方向, 并将它们映射到预设的M个方向的bin里面形成直方图。这里需要考虑的是如果出现一个方向,比如10度,幅度为2,那么将其线性分解到0和20度两个bin上,各加1。
把上图中单个cell对应的方向直方图转化为单维向量,也就是按规定组距对对应方向梯度个数进行编码。(8,10,6,12,4,5,8,6,14),得到单个cell的9个特征,每个block(扫描窗口)包含229=36个特征,一个64128大小的图像最后得到的特征数为367*15=3780个。这样将一副直观的梯度图通过分解提取变为计算机容易理解的特征向量。
.
4.每个Block 内部的所有cell的梯度直方图联合起来并进行归一化处理(L1-norm, L2-Norm, L2-hys-norm, etc), 据说这样可以使特征具有光照不变性. 光照属于加性噪声, 归一化之后会抵消掉关照变化对特征的影响.
5.所有Block的特征联合起来, 就是最终的HOG特征
参数说明:
image: input image, 输入图像
orientation: 指定bin的个数. scikit-image 实现的只有无符号方向.
(根据反正切函数的到的角度范围是在-180°~ 180°之间, 无符号是指把 -180°-0°这个范围统一加上180°转换到0°-180°范围内. 有符号是指将-180°-180°转换到0°~360°范围内.)
也就是说把所有的方向都转换为0°~180°内, 然后按照指定的orientation数量划分bins. 比如你选定的orientation= 9, 则bin一共有9个, 每20°一个:
[0°~20°, 20°~40°, 40°~60° 60°~80° 80°~100°, 100°~120°, 120°~140°, 140°~160°, 160°~180°]
pixels_per_cell : 每个cell的像素数, 是一个tuple类型数据,例如(20,20)
cell_per_block : 每个BLOCK内有多少个cell, tuple类型, 例如(2,2), 意思是将block均匀划分为2x2的块
block_norm: block 内部采用的norm类型.
transform_sqrt: 是否进行 power law compression, 也就是gamma correction. 是一种图像预处理操作, 可以将较暗的区域变亮, 减少阴影和光照变化对图片的影响.
feature_vector: 将输出转换为一维向量.
visualise: 是否输出HOG image, (应该是梯度图)
scikit-image 版的HOG 没有进行cell级别的gaussian 平滑, 原文对cell进行了gamma= 8pix的高斯平滑操作.
from skimage.feature import hog
import matplotlib.pyplot as plt
import cv2
# 读入图像
img = cv2.imread('1.png')
img1 = cv2.resize(img, (300, 300))
image1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
plt.subplot(1, 2, 1)
plt.imshow(image1)
# 转化为灰度图
image2 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
# HOG特征
ft, hogimage = hog(image2, # 输入图像
orientations=9, # 将180°划分为9个bin,20°一个
pixels_per_cell=(8, 8), # 每个cell有8*8=64个像素点
cells_per_block=(8, 8), # 每个block中有8*8=64个cell
block_norm='L2-Hys', # 块向量归一化 str {‘L1’, ‘L1-sqrt’, ‘L2’, ‘L2-Hys’}
transform_sqrt=True, # gamma归一化
feature_vector=True, # 转化为一维向量输出
visualize=True) # 输出HOG图像
plt.subplot(1, 2, 2)
plt.imshow(hogimage)
plt.show()