好的,作为一位无所不知的大神,我将为你讲解一个在计算机视觉基础与早期算法中极具代表性的题目。这个题目虽然原理清晰,但理解其推导过程和每一步的动机至关重要。
题目名称:基于梯度直方图(Histogram of Oriented Gradients, HOG)特征的行人检测算法
题目描述
在计算机视觉中,行人检测是目标检测的一个核心子任务。其目标是从一张给定的图像中,精准地定位出所有行人的位置(通常用矩形框表示)。在深度学习普及之前,HOG特征结合支持向量机(SVM)分类器的方法,是行人检测领域最经典、效果最好的算法之一(例如在著名的INRIA行人数据集中)。本题旨在详细解释HOG特征的提取过程,以及如何利用这些特征进行行人检测。
核心问题:如何设计一种特征描述子,使其能有效刻画行人的轮廓和姿态,同时对光照变化、小的形变具有一定的鲁棒性?
解题过程详解
我们可以将整个解题过程分解为几个循序渐进的步骤。
步骤一:核心思想与直觉
首先思考:人在图像中看起来像什么?一个直观的答案是:一个直立、大体呈现“工”字型或“大”字型的物体,有头部、躯干和双腿。 这个形状的边缘(即图像中灰度值剧烈变化的地方)是关键的线索。而边缘的方向(是垂直的、水平的还是倾斜的)比边缘的精确位置更为稳定。
HOG特征的核心思想就是:统计局部区域(细胞单元)内图像梯度的方向分布,并将其作为特征来描述物体的形状。 梯度主要存在于边缘处,梯度的方向与边缘垂直,因此统计梯度方向直方图,实际上就是在统计“边缘方向”的分布。行人的轮廓会产生一组特定方向梯度分布的集合。
步骤二:预处理
- 输入图像:通常是一组固定大小的窗口图像(例如128x64像素),这些窗口是通过滑动窗口在整张图像上遍历得到的。
- 颜色空间归一化(可选但重要):为了减少光照和阴影的影响,可以对图像进行全局的伽马校正或颜色空间归一化(例如,转换为灰度图,并进行对比度拉伸)。不过,后续的局部归一化操作更为关键。
步骤三:计算图像的梯度
这是特征提取的第一步,目的是捕捉图像中的轮廓和纹理信息。
- 梯度计算:对图像的每个像素点,计算其在水平和垂直方向(x和y方向)的梯度值。通常使用简单的差分卷积核来完成:
- 水平梯度 \(G_x\):使用
[-1, 0, 1]核进行卷积。它检测垂直边缘。 - 垂直梯度 \(G_y\):使用
[1, 0, -1]^T核进行卷积。它检测水平边缘。
- 水平梯度 \(G_x\):使用
- 梯度幅值和方向:对于每个像素点(i, j):
- 梯度幅值:\(M(i, j) = \sqrt{G_x(i, j)^2 + G_y(i, j)^2}\)
它代表了该点边缘的“强度”。 - 梯度方向:\(\theta(i, j) = \arctan(\frac{G_y(i, j)}{G_x(i, j)})\)
结果通常在0°到180°之间(对于无符号梯度),代表边缘的方向。
- 梯度幅值:\(M(i, j) = \sqrt{G_x(i, j)^2 + G_y(i, j)^2}\)
现在,我们得到了一幅梯度幅值图和一幅梯度方向图。
步骤四:构建梯度方向直方图(在“细胞单元”中)
这是HOG最核心的一步。我们不直接使用每个像素的梯度,因为这样特征维度过高且对噪声敏感。相反,我们将图像窗口划分为小的、连续的“细胞单元”(Cell),例如8x8像素。
对于每一个细胞单元:
- 建立方向直方图:创建一个包含若干个bin(比如9个,每20°一个bin)的直方图。
- 投票:遍历这个8x8细胞单元内的所有64个像素。每个像素根据其梯度方向 \(\theta\),将其梯度幅值 \(M\) 作为“选票”,投给对应的方向bin。
- 细节:方向往往是连续值(例如10°),而bin是离散的(0°, 20°, 40°...)。这里采用双线性插值投票(或称权重分配):假设一个像素的梯度方向是10°,它位于0°和20°两个bin之间。那么,它的梯度幅值会按照距离比例(10°离0°bin近,离20°bin远)分别累加到这两个bin中。这使得特征对微小的方向变化更鲁棒。
- 结果:经过上述操作,每个细胞单元都被表示为一个9维的特征向量(如果使用9个bin),这个向量概括了该小块区域的主要边缘方向分布。
步骤五:局部对比度归一化(在“块”中)
单个细胞单元的特征仍然对光照和阴影敏感。为了进一步提升鲁棒性,我们需要进行局部对比度归一化。
- 定义“块”:将相邻的若干个细胞单元(例如2x2个)组合成一个更大的“块”(Block)。块在图像窗口上以一定的步长(例如一个细胞单元的大小,即8像素)滑动,因此细胞单元的特征会被多个块共享,这有助于后续分类。
- 块内特征向量串联:将一个块内所有细胞单元的直方图向量串联起来。例如,一个2x2的块包含4个细胞单元,每个细胞单元有9维特征,那么这个块的特征向量就是 4 * 9 = 36 维。
- 归一化:对这个36维的向量进行归一化。常用的方法是L2范数归一化:
- 设向量为 \(v\)。
- 计算其L2范数:\(\|v\|_2 = \sqrt{v_1^2 + v_2^2 + ... + v_{36}^2}\)。
- 归一化后向量:\(v’ = v / (\|v\|_2 + \epsilon)\),其中 \(\epsilon\) 是一个很小的常数,防止除以零。
- 归一化的意义:假设光照突然增强,图像所有像素的梯度幅值都会同比增大,导致 \(v\) 中所有值变大。经过L2归一化后,\(v’\) 的值会回到一个相对稳定的范围,从而减弱了光照的绝对强度带来的影响,只保留了相对的方向分布模式。
步骤六:收集整个检测窗口的HOG特征
- 遍历所有块:按照设定的步长,让块在图像检测窗口内滑动,覆盖所有位置。
- 串联所有块的特征:将所有滑动块归一化后的特征向量按顺序串联起来,形成一个非常长的、最终的特征向量,这就是整个检测窗口的HOG描述子。
计算示例:
- 检测窗口大小:128x64 像素
- 细胞单元大小:8x8 像素 -> 窗口在水平方向有 128/8 = 16 个细胞单元,垂直方向有 64/8 = 8 个细胞单元,共 16*8=128 个细胞单元。
- 块大小:2x2 个细胞单元
- 块步长:1 个细胞单元(即8像素)
- 水平方向可滑动次数:(16 - 2) + 1 = 15 次
- 垂直方向可滑动次数:(8 - 2) + 1 = 7 次
- 总共的块数量:15 * 7 = 105 个块
- 每个块特征维度:229 = 36 维
- 最终HOG特征总维度:105 * 36 = 3780 维。
这个3780维的向量,就以密集的、结构化的方式,编码了整个128x64图像窗口的梯度方向分布信息。
步骤七:训练分类器与检测
- 构建训练集:收集大量包含行人(正样本)和不包含行人(负样本)的128x64图像块。
- 提取HOG特征:为每个训练样本计算其3780维的HOG特征。
- 训练SVM分类器:将这些HOG特征和对应的标签(+1/-1)输入给一个线性SVM进行训练。SVM会学习一个超平面,能够最好地将行人HOG特征和非行人HOG特征分开。
- 多尺度滑动窗口检测:
- 对于一张新的测试图像,我们不知道行人有多大。
- 因此,需要构建一个图像金字塔(以不同的比例缩放图像)。
- 在金字塔的每一层上,用一个固定大小的滑动窗口(如128x64)遍历整个图像。
- 对每个窗口,提取HOG特征,并用训练好的SVM分类器判断其是否为行人。
- 如果分类器给出一个正分数,且超过阈值,则在该窗口位置记录一个检测结果。
- 非极大值抑制:由于滑动窗口的重叠,同一个行人可能会被多个相邻的、高度重叠的窗口检测到。需要使用NMS算法来合并这些重复的检测框,保留最准确的一个。
总结
HOG特征算法通过细胞单元内梯度方向投票、块内对比度归一化以及块特征串联,巧妙地构建了一个能够刻画物体宏观形状,并对光照、局部形变具有鲁棒性的特征描述子。它与线性SVM的结合,在深度学习崛起之前,代表了传统特征工程方法在特定任务(如行人检测)上的巅峰水平。理解HOG,不仅能掌握一个经典算法,更能深刻体会到“如何从图像像素中提取有意义的、与任务相关的模式”这一计算机视觉的根本思想。