Histograms of Oriented Gradients for Human Detection

第一次看这篇论文的时候,看完也只是粗略的了解,看得不够细,感觉看论文在研讨课上讨论一次会收获很大,自己看可以模拟一下,也就是自己给自己提问,这篇论文在什么背景下主要讲了什么方法?如何实现?缺点是什么?所以遵循这个思路,重新看了一遍这篇论文,按照自己理解做的笔记,可能乱,以后逐步改进。
#背景:
之前的行人检测都是基于表达的稀疏特征方法,而HOG是在均匀空间cells中的稠密网格中做计算,并且使用重叠局部对比归一化。大概的区别就在于此。
闲话不多说,主要是掌握一个算法嘛。
#实现:
流程如下图:
这里写图片描述

下面就对每个模块做介绍:
HOG基本思想:基于梯度方向上的局部直方图。
操作:将图片分成小的空间区域(cell),每个聚集一个局部一维直方图(梯度方向或者边缘方向),为了光照不变性,采用“对比归一化“:聚集局部直方图能量在更大的块(block)中。
Histograms of Oriented Gradients for Human Detection_第1张图片
上图左即代表一个图像被分成了4个4x4的cell(由细边包围)和1个8x8的块(block),中间的箭头方向梯度方向,长度代表梯度大小。
由于对图像的处理要经过4层扫描,分别为图像金字塔层,即每层中的滑动窗口,滑动窗口中的block,block中的cell,cell中的像素点。有这么多层,每层都还是二维的,因此处理速度非常慢,作者提出HOG缓存的想法,即将每个block的hog描述子向量都存在内存查找表中,由于滑动窗口滑动时,有很多重叠block计算,因此重叠计算过的block可以从查找表中读取,就节省了很多时间。
下面是源代码中的解释:

// Initialize 2 lookup tables, pixData & blockData.
 619     // Here is why:
 620     //
 621     // The detection algorithm runs in 4 nested loops (at each pyramid layer):
 622     //  loop over the windows within the input image
 623     //    loop over the blocks within each window
 624     //      loop over the cells within each block
 625     //        loop over the pixels in each cell
 626     //
 627     // As each of the loops runs over a 2-dimensional array,
 628     // we could get 8(!) nested loops in total, which is very-very slow.
 629     //
 630     // To speed the things up, we do the following:
 631     //   1. loop over windows is unrolled in the HOGDescriptor::{compute|detect} methods;
 632     //         inside we compute the current search window using getWindow() method.
 633     //         Yes, it involves some overhead (function call + couple of divisions),
 634     //         but it's tiny in fact.
 635     //   2. loop over the blocks is also unrolled. Inside we use pre-computed blockData[j]
 636     //         to set up gradient and histogram pointers.
 637     //   3. loops over cells and pixels in each cell are merged
 638     //       (since there is no overlap between cells, each pixel in the block is processed once)
 639     //      and also unrolled. Inside we use PixData[k] to access the gradient values and
 640     //      update the histogram

Histograms of Oriented Gradients for Human Detection_第2张图片
数据集:INRIA。
输入:数据集中随机取1239张含人图片并将其水平翻转得到共2478张正样本图片,并在随机取的1280张不含人的图片中取12180个patch作为初始负样本,然后训练一次后找到假正例(这里称为“难例“,就是本来是负样本被预测为正样本),再将原始负样本加上这些难例再训练得到最终的探测器,这样做的目的是为了提高探测器分类性能,重复这么做经过实验收益并不大,做一次就够了。
过程:
1) gamma归一化
为了减少光照因素的影响,首先需要将整个图像进行规范化(归一化),这种处理能够有效地降低图像局部的阴影和光照变化,采用平方根伽马校正的效果最好。将原来每个通道像素值范围从0~255变换到0~√255。

2) 计算梯度
图像中像素点(x,y)的梯度。
Histograms of Oriented Gradients for Human Detection_第3张图片
梯度幅值和方向采用双线性插值,每一个点梯度角度在0~180度之间任意值,将其离散化为9个bin,即每个bin为20度,一般bin序号都标在其中间,故当梯度角度离散化到这9个bin中,一般都有两个相邻的bin,如下图,若恰好在某个bin中心,则对该bin权重为1,一般梯度幅值是用来计算梯度直方图权重投票的,故每个像素点幅值分解到角度相邻的两个bin上,越近的那个bin权重越大,因此幅度图像用了两个通道,每个通道都是原像素点幅值的一个分量,同理梯度方向也用了两个通道,序号小的放在第一通道,若为三通道,则取梯度最大的那个通道的值为该点的梯度幅值。
Histograms of Oriented Gradients for Human Detection_第4张图片
加权公式为:
Histograms of Oriented Gradients for Human Detection_第5张图片

3) 在cell中的权值投票
计算每个像素的梯度,将其梯度方向在0-180度(效果最好)分成9个区间(bin),投票在邻域上使用双线性插值(将邻域的bin的中心及其位置来作为插值权重,插入的值为像素的梯度幅值)。

4) 归一化重叠块
组合cells成块,然后对每个块进行对比归一化,归一化后的块就叫HOG块描述子,对比归一化的方法有:
Histograms of Oriented Gradients for Human Detection_第6张图片
其中(a),(b),(d)都有差不多的效果。

5) 生成特征描述向量
将所有的HOG块描述子组合在一起,形成最终的特征向量,该特征向量就描述了检测窗口的图像内容。

6)分类器
采用线性SVM分类器,虽然用高斯核函数SVM性能更好,但同时增加了更多的运行时间。

HOG的OPENCV实现:
Histograms of Oriented Gradients for Human Detection_第7张图片

程序实现-我的码云
未加难例生成效果图:
Histograms of Oriented Gradients for Human Detection_第8张图片
初始分类器生成难例加入负样本效果图:
Histograms of Oriented Gradients for Human Detection_第9张图片
再次生成难例加入负样本的效果图:
Histograms of Oriented Gradients for Human Detection_第10张图片
最后这次分类器在一段视频中的效果:
Histograms of Oriented Gradients for Human Detection_第11张图片
总的来说,加入难例之后,检测效果确实好了不少。

参考博客:

http://www.cnblogs.com/tornadomeet/archive/2012/08/15/2640754.html
http://www.cnblogs.com/zhazhiqiang/p/3595266.html

你可能感兴趣的:(数字图像处理)