HOG特征

梯度方向直方图 (Histogram of Oriented Gradient,HOG) 特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度方向直方图来构成特征。 HOG 特征结合 SVM 分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功


算法思想

HOG 特征的核心思想是在一幅图像中,局部目标的表象和形状 (appearance and shape) 能够被梯度和边缘的方向密度(梯度的统计信息,而梯度主要存在于边缘地方)很好地描述。通过将整幅图像分为多个小的连通区域 (cell) ,并计算每个 cell 的梯度或边缘方向直方图,这些直方图的组合可用于构成特征描述子,为了提高准确率,可以将局部直方图在图像更大范围内 (称为block) 进行对比度归一化 (constrast-normalized) 。所采用的方法是:先计算各直方图在对应的 block 中的密度,然后根据这个密度对 block 中的所有 cell 做归一化 (normalize) 。归一化操作对光照变化和阴影具有更好的鲁棒性


算法特点

  • HOG 特征是在图像的局部区域内进行操作,对图像几何和光学的变化有较好的稳健性,这两种变化只会出现在更大的空域上
  • 在粗粒度的空域抽样、细粒度的方向抽样,以及较强的局部光学归一化条件下,只要行人大体保持直立的姿势,可以容许行人有一些细微的肢体动作,而不影响检测效果

算法实现

HOG 特征提取的流程如下:

图像预处理
  • 灰度化: HOG 提取的是纹理特征,颜色信息不起作用,所以将彩色图转化为灰度图
  • Gamma 校正(归一化):对图像进行 Gamma 校正,完成对整个图像的标准化(归一化),可以调节图像的对比度,降低局部光照不均匀或者阴影的影响,同时也可以在一定程度上降低噪声的干扰,提高特征描述器对光照等干扰因素的鲁棒性。校正公式如下:

\[ I(x, y) = I(x, y)^{\gamma}, \gamma = \dfrac{1}{2} \]

计算图像梯度

分别求取图像水平方向和垂直方向的梯度,然后计算每个像素点的梯度幅值和方向,微分求图像梯度不仅可以捕获图像边缘和纹理信息,而且可以弱化光照不均匀的影响 \[ G\_x(x,y) = I(x+1,y) - I(x-1,y) \\ G\_y(x,y) = I(x,y+1) - I(x,y-1) \\ \nabla G(x,y) = \sqrt{G\_x(x,y)^2+G\_y(x,y)^2} \\ \theta(x,y) = arctan(G\_y(x,y) / G\_x(x,y)) \] 一般采用梯度算子对图像进行卷积运算求取图像梯度,例如用 $ [-1,0,1] $ 梯度算子对图像进行卷积操作得到水平方向的梯度分量,用 $ [-1,0,1]^T $ 梯度算子进行卷积操作得到竖直方向的梯度分量,然后求取图像的梯度幅值和方向

cell 中计算梯度方向直方图

将图像划分为若干个连通区域 (cell),例如每个 cell 为 $ 8 * 8 $ 个像素,相邻的 cell 之间不重叠,将所有梯度方向划分为 9 个方向块 (bin) ,然后在每个 cell 内统计梯度方向直方图。在计算梯度方向时,可把方向的角度范围定位 $ (0, 180^{}) $ 或者 $ (0, 360^{}) $ 。最后每个 cell 都对应一个 9 维的特征向量。此外,还可以考虑梯度幅值作为 bin 的统计权重。在行人检测中,通过给局部图像区域进行编码,可以保持对目标对象的姿势和外观的弱敏感性,更好地捕获图像的轮廓和纹理信息

block 中归一化梯度方向直方图

将多个 cell 组合成更大连通块 (block) ,将 block 内所有 cell 的特征向量串联起来便得到该 blockHOG 特征描述子,不同 block 之间可能相互重叠,可以有效地利用局部邻域信息。类比在卷积神经网络中,掩码和步长的选择。在更大范围内 (block) 统计梯度直方图,并做归一化处理,能够更好地适应光照和对比度的变化。常用的归一化方法有以下几种:

  • L2-norm

\[ v = \dfrac{v}{\sqrt{\left|v\right\|\_{2}^{2} + \varepsilon^2}} \]

  • L1-norm

\[ v = \dfrac{v}{\left|v\right\|\_{1} + \varepsilon} \]

  • L1-sqrt

\[ v = \sqrt{\dfrac{v}{\left|v\right\|\_{1} + \varepsilon}} \]

  • 还有一种 L2-Hys ,即先做一次 L2-norm ,然后把大于特定值 0.2 的分量幅值为 0.2 再做一次 L2-norm ,一般在检测中采用 L2-norm 的效果更好。在一个 block 中,如果 cell 的数量为 $ 2 * 2 $ ,那 block 的特征数为 $ 2 * 2 * 9 = 36 $ 维特征
统计整幅图像(检测窗口)的 HOG 特征

在实际应用中,通常是选取固定大小的滑动窗口来提取 HOG 特征,对于一个 $ 64 * 128 $ 的图像窗口,每 $ 8 * 8 $ 个像素组成一个 cell ,每 $ 2 * 2 $ 个 cell 组成一个 block ,一共有 $ (8-1) * (16-1) = 105 $ 个 block ,因此该图像的窗口特征维数为 $ 105 * 36 = 3780 $ 。当然也可以将整幅图像作为一个窗口来提取 HOG 特征


代码实现

根据以上步骤流程,提取 HOG 特征的 MATLAB 代码如下:(其中 N 就是我们最终想得的 HOG 描述子)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
close all; clear; clc;
img = imread('person.png');
if size(img,3) == 3
img = rgb2gray(img);
end
img = rescale(sqrt(im2double(img))); % gamma为1/2的光照(阴影)校正
img = imresize(img,0.5);
% figure; imshow(img,[]);
Gx = imfilter(img,[-0.5;0;0.5],'symmetric');
Gy = imfilter(img,[-0.5,0,0.5],'symmetric');
Gmag = sqrt(Gx.^2 + Gy.^2);
% figure; imshow(rescale(Gmag),[]);
Gdir = atan2d(Gy,Gx); % 使用atand将有:0/0出现NaN,(非0)/0出现±Inf,使用atan2d则无此顾虑
[rows,cols] = size(img);
cell_size = 8;
row_cells = floor(rows/cell_size);
col_cells = floor(cols/cell_size);
M = cell(row_cells,col_cells); % 通过划分cell获得的描述子
bins = 9;
bin_step = 180/bins;
cell_hist = zeros(1,bins);
for i = 1:row_cells
for j = 1:col_cells
op_cell_mag = Gmag((i-1)*cell_size+1:i*cell_size,(j-1)*cell_size+1:j*cell_size);
op_cell_dir = Gdir((i-1)*cell_size+1:i*cell_size,(j-1)*cell_size+1:j*cell_size);
label = ceil(((op_cell_dir<0)*180+op_cell_dir)/bin_step);
label(label==0) = 1; % 0°属于第一个bin
for k = 1:numel(label)
cell_hist(uint8(label(k))) = cell_hist(uint8(label(k))) + op_cell_mag(k); % 按权重投票
end
M{i,j} = cell_hist;
cell_hist = zeros(1,bins);
end
end

%% 可视化通过划分cell获得的描述子(为了理解而加的代码)
% hog = zeros(rows,cols);
% figure; imshow(hog,[]); hold on;
% for i = 1:row_cells
% for j = 1:col_cells
% centre = [(i-0.5)*cell_size ,(j-0.5)*cell_size]; % 绘制中心
% for k = 1:bins
% offset = [M{i,j}(k)*cosd((k-0.5)*bin_step),M{i,j}(k)*sind((k-0.5)*bin_step)];
% quiver(centre(2),centre(1),offset(1),offset(2),2,'w'); % 绘制单向箭头
% end
% end
% end
% hold off;

%% 在block中归一化梯度方向直方图(N即为最终所求的描述子)
block_size = 2;
N = cell(row_cells-1,col_cells-1);
for i = 1:row_cells-1 % blok的数量显然要更少
for j = 1:col_cells-1
block_hist = [M{i,j},M{i,j+1},M{i+1,j},M{i+1,j+1}];
N{i,j} = block_hist/sum(block_hist); % 归一化
end
end

提取效果:(可以很清晰地看到, HOG 描述的是纹理信息


参考文章(网上文章一搜一堆)

本博客理论部分的主要来源

HOG 特征详解(这篇不错)

目标检测的图像特征提取之 HOG 特征

这是一篇博采众长的文章(推荐)

只能说这个是十分的详细(不过我没有细看)

HOG 特征