HOG 特征提取+SVM 分类器
1、HOG 特征提取过程
步骤 1:预处理图像(标准化,提升鲁棒性) ①转灰度图:丢弃颜色信息(颜色对目标检测无核心帮助,还会增加计算量)。 ②Gamma 校正(可选):对图像做灰度值非线性变换,抑制光照变化的影响(比如过亮、过暗区域的细节保留)。 ③裁剪或缩放:将图像块调整为 winSize(64x64)尺寸(对应训练/检测的窗口大小),保证特征提取的一致性。
步骤 2:计算图像梯度(提取边缘/纹理信息,梯度能反映图像的边缘、纹理变化,目标的轮廓就是强梯度区域,这是 HOG 特征的核心来源) ①对每个像素点,分别计算水平梯度(x 方向)和垂直梯度(y 方向)(常用 Sobel 算子或简单差分法)。 ②由每个像素的 x、y 梯度,计算两个关键值:
- 梯度幅值:反映梯度的强度(边缘的清晰程度)。
- 梯度方向:反映边缘的朝向(范围 0-180° 或 0-360°) 最终得到两张和原图尺寸一致的「梯度幅值图」和「梯度方向图」。
步骤 3:细胞单元(cellSize)构建梯度直方图(量化特征) ①将 winSize 梯度幅度图和梯度方向图按 cellSize 分别划分为多个独立细胞单元; ②对每个细胞单元内的所有像素,构建直方图(区间个数 nbins);其中梯度方向决定哪个区间计数,梯度幅值决定计数的权重。 ③每个细胞单元最终得到一个长度为 nbins 的一维数组,这是最基础的局部特征,反映该区域的纹理方向分布。
步骤 4:将相邻的多个细胞单元组合成一个块(Block),Block 内特征归一化。 块的滑动步长为 blockStride,在 winSize 窗口内滑动,对每个块内的所有细胞直方图进行归一化处理(常用 L2 归一化),消除光照、对比度变化带来的特征偏差(比如同一目标在亮处和暗处的梯度幅值差异)。
步骤 5:拼接所有块特征,得到一位数组即最终 HOG 特征向量。

如果不打算细究具体的实现算法,我理解 HOG 特征就是基于图像的梯度与局部梯度的直方图经过一系列计算的新向量化表示。
2、SVM 分类器判断
下文详解
3、非极大值抑制(NMS)
非极大值抑制(NMS)的唯一核心作用是去除目标检测过程中产生的大量重复、重叠的候选检测框,只保留置信度最高、最具代表性的那个框;属于目标检测的推理/检测阶段
4、绘制边框,得到检测结果
使用二分类模型实现目标检测原理:
SVM 本身确实只是二分类模型,它完全没有能力直接预测目标的坐标值,最终能得到检测框坐标,是「HOG + 滑动窗口 + 多尺度缩放」这套组合流程的功劳,SVM 只在其中承担「分类判断」的单一角色。
第一步:SVM 的训练阶段(只做二分类,和坐标无关) 训练时,只给 SVM 喂两种数据,让它学习「是目标」和「不是目标」的区分:
- 正样本:裁剪好的「仅包含目标」的图像块(尺寸和 HOG 的 winSize 一致,比如 64x64),提取 HOG 特征后,标注为「1」(是目标)。
- 负样本:不包含目标的图像块(尺寸同样 64x64),提取 HOG 特征后,标注为「-1」(不是目标)。 训练完成后,这个 SVM 只有一个能力:输入一个 64x64 图像块的 HOG 特征,返回一个分类结果(是目标/不是目标),附带一个置信度得分,它完全不知道这个图像块来自整张图片的哪个位置。
第二步:检测阶段(滑动窗口 + 多尺度,让 SVM'间接'产出坐标) 检测时,坐标不是 SVM 预测的,而是「滑动窗口」遍历图像时的「窗口位置」决定的,流程如下:
固定尺寸滑动窗口(遍历单张图) 以 HOG 的 winSize(64x64)为窗口大小,以一定步长(比如 16 像素),在整张输入图片上「从左到右、从上到下」滑动。 每滑动到一个位置,就裁剪出这个窗口对应的 64x64 图像块,提取 HOG 特征。 把这个 HOG 特征输入给训练好的 SVM,让 SVM 做二分类判断:「这个窗口里是目标吗?」。 如果 SVM 判断「是目标」(置信度得分较高),就记录下「这个窗口在整张图上的左上角坐标 + 窗口尺寸(64x64)」,这就是最初的检测框坐标(x, y, w, h)。
多尺度缩放(解决不同大小的目标) 因为目标在图片中可能有大有小(比如近处的人更大,远处的人更小),固定 64x64 窗口无法检测到所有尺寸的目标。 所以会先把输入图片按不同比例缩放(比如缩小为 0.8 倍、0.6 倍…),形成一组「多尺度图像金字塔」。 对每一张缩放后的图像,都执行上面的「滑动窗口 + SVM 分类」流程,收集所有 SVM 判断为「是目标」的窗口位置。 最终坐标整合 所有尺度下的窗口,都会映射回原始图片的尺寸(还原缩放带来的坐标偏差),形成最终的 locations 检测框列表。 hog.detectMultiScale() 其实已经封装了「滑动窗口 + 多尺度缩放 + SVM 分类 + 坐标还原」这一系列操作,所以直接返回了可用的检测框坐标。


