Histograms of Oriented Gradients for Human Detection

    xiaoxiao2021-03-25  73

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

    下面就对每个模块做介绍: HOG基本思想:基于梯度方向上的局部直方图。 操作:将图片分成小的空间区域(cell),每个聚集一个局部一维直方图(梯度方向或者边缘方向),为了光照不变性,采用“对比归一化“:聚集局部直方图能量在更大的块(block)中。 上图左即代表一个图像被分成了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

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

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

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

    4) 归一化重叠块 组合cells成块,然后对每个块进行对比归一化,归一化后的块就叫HOG块描述子,对比归一化的方法有: 其中(a),(b),(d)都有差不多的效果。

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

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

    HOG的OPENCV实现:

    程序实现-我的码云 未加难例生成效果图: 初始分类器生成难例加入负样本效果图: 再次生成难例加入负样本的效果图: 最后这次分类器在一段视频中的效果: 总的来说,加入难例之后,检测效果确实好了不少。

    参考博客:

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

    转载请注明原文地址: https://ju.6miu.com/read-39206.html

    最新回复(0)