zoukankan      html  css  js  c++  java
  • HOG特征提取

    如果可以还是要看第一手资料,看原始论文,避免被人误导。

    原论文:Histograms of Oriented Gradients for Human Detection

    详细信息可以参考其博士论文:Finding People in Images and Videos 

    计算流程:

    RGB colour space with no gamma correction; [−1; 0; 1] gradient filter with no smoothing; linear gradient voting into 9 orientation bins in 0◦–180◦; 16×16 pixel blocks of four 8×8 pixel cells; Gaussian spatial window with σ = 8 pixel; L2-Hys (Lowe-style clipped L2 norm) block normalization; block spacing stride of 8 pixels (hence 4-fold coverage of each cell); 64×128 detection window; linear SVM classifier.

    最佳梯度 模板[−1; 0; 1]。

    Simple 1-D [−1; 0; 1] masks at σ=0 work best. Using larger masks always seems to decrease performance, and smoothing damages it significantly.

    HOG特征的提取过程为:

    Gamma归一化;

    计算梯度;

    划分cell

    组合成block,统计block直方图;

    梯度直方图归一化;

    收集HOG特征。

    Gamma归一化:

    对图像颜色进行Gamma归一化处理,降低局部阴影及背景因素的影响.

    计算梯度:

    通过差分计算出图像在水平方向上及垂直方向上的梯度:

    然后得到各个像素点的梯度的幅值及方向:

    划分cell

    将整个窗口划分成大小相同互不重叠的细胞单元cell(如8×8像素),计算出每个cell的梯度大小及方向.然后将每像素的梯度方向在0−180o0−180o 区间内(无向:0-180,有向:0-360)平均分为9个bins,每个cell内的像素用幅值来表示权值,为其所在的梯度直方图进行加权投票.

    9bins:

    组合成block,统计block直方图

    将2×2个相邻的cell组成大小为16×16的像素块即block.依次将block大小的滑动窗口从左到右从上到下滑动,求其梯度方向直方图向量.

    从论文中的不同大小的cell与不同大小的block作用下的效果对比图看,最佳的block size和cell size组合是3×3 block size 6×6 cell size。但是实际应用中使用的多是 2×2 block size 8×8 cell size,具体原因待补充。

    原文解释:

    Fig. 5 plots the miss rate at 10−4 FPPW w.r.t. cell size and block size in cells. For human detection, 3×3 cell blocks of 6×6 pixel cells perform best, with 10.4% miss-rate at 10−4 FPPW. In fact, 6–8 pixel wide cells

    do best irrespective of the block size – an interesting coincidence as human limbs are about 6–8 pixels across in our images. 2×2 and 3×3 blocks work best. Beyond this, the results deteriorate: adaptivity to local

    imaging conditions is weakened when the block becomes too big, and when it is too small (1×1 block / normalization over orientations alone) valuable spatial information is suppressed.

     

    梯度直方图归一化

    作者对比了L2-norm、L1-norm、L1-sqrt等归一化方法,发现都比非标准数据有显着的改善.其中L2-norm和L1-sqrt效果最好,而L1-norm检测效果要比L2-norm和L1-sqrt低5%.

    这样通过归一化能够进一步地对光照、阴影和边缘进行压缩.

    收集HOG特征

    由于每个cell内的梯度方向分成了9个bins,这样每个细胞单元的HOG特征向量长度是9.

    这样,对于大小为128×64大小的图像,采用8*8像素的sell,2×2个cell组成的16×16像素的block,采用8像素的block移动步长,这样检测窗口block的数量有((128-16)/8+1)×((64-16)/8+1)=15×7.则HOG特征描述符的维数为15×7×4×9.

    上面的计算表达式((128-16)/8+1)×((64-16)/8+1)=15×7可以参考如下的卷积计算公式。

    N=(W-F+2P)/S+1
    其中N:输出大小
    W:输入大小
    F:卷积核大小
    P:填充值的大小
    S:步长大小

    动画辅助理解:

    计算梯度直方图

    在这一步,我们先把整个图像划分为若干个8x8的小单元,称为cell,并计算每个cell的梯度直方图。这个cell的尺寸也可以是其他值,根据具体的特征而定。

    为什么我们要把图像分成若干个8x8的小单元?

    这是因为对于一整张梯度图,其中的有效特征是非常稀疏的,不但运算量大,而且效果可能还不好。于是我们就使用特征描述符来表示一个更紧凑的特征。一个8x8的小单元就包含了8x8x2 = 128个值,因为每个像素包括梯度的大小和方向。

    现在我们要把这个8x8的小单元用长度为9的数组来表示,这个数组就是梯度直方图。这种表示方法不仅使得特征更加紧凑,而且对单个像素值的变化不敏感,也就是能够抗噪声干扰。

    我们来看一下图片中的一个cell中的梯度:

     

    中间那张图中的箭头表示梯度,箭头方向表示梯度方向,箭头长度表示梯度大小。

    右图是 8×8 的cell中表示梯度的原始数字,注意角度的范围介于0到180度之间,而不是0到360度, 这被称为“无符号”梯度,因为两个完全相反的方向被认为是相同的。

    现在我们来计算cell中像素的梯度直方图,先将角度范围分成9份,也就是9 bins,每20°为一个单元,也就是这些像素可以根据角度分为9组。将每一份中所有像素对应的梯度值进行累加,可以得到9个数值。直方图就是由这9个数值组成的数组,对应于角度0、20、40、60... 160。

     

    比如上面方向图中蓝圈包围的像素,角度为80度,这个像素对应的幅值为2,所以在直方图80度对应的bin加上2。红圈包围的像素,角度为10度,介于0度和20度之间,其幅值为4,那么这个梯度值就被按比例分给0度和20度对应的bin,也就是各加上2。

    还有一个细节需要注意,如果某个像素的梯度角度大于160度,也就是在160度到180度之间,那么把这个像素对应的梯度值按比例分给0度和160度对应的bin。

    将这 8x8 的cell中所有像素的梯度值加到各自角度对应的bin中,就形成了长度为9的直方图:

    可以看到直方图中,0度和160附近有很大的权重,说明了大多数像素的梯度向上或者向下,也就是这个cell是个横向边缘。

    现在我们就可以用这9个数的梯度直方图来代替原来很大的三维矩阵,即代替了8x8x2个值。

    Block 归一化

    HOG将8×8的一个区域作为一个cell,再以2×2个cell作为一组,称为block。由于每个cell有9个值,2×2个cell则有36个值,HOG是通过滑动窗口的方式来得到block的,如下图所示:

     

    在前面的步骤中,我们基于图像的梯度对每个cell创建了一个直方图。

    但是图像的梯度对整体光照非常敏感,比如通过将所有像素值除以2来使图像变暗,那么梯度幅值将减小一半,因此直方图中的值也将减小一半。 理想情况下,我们希望我们的特征描述符不会受到光照变化的影响,那么我们就需要将直方图“归一化” 。

    在说明如何归一化直方图之前,先看看长度为3的向量是如何归一化的。

    假设我们有一个向量 [128,64,32],向量的长度为 [公式] ,这叫做向量的L2范数。将这个向量的每个元素除以146.64就得到了归一化向量 [0.87, 0.43, 0.22]

    现在有一个新向量,是第一个向量的2倍 [128x2, 64x2, 32x2],也就是 [256, 128, 64],我们将这个向量进行归一化,你可以看到归一化后的结果与第一个向量归一化后的结果相同。所以,对向量进行归一化可以消除整体光照的影响。

    知道了如何归一化,现在来对block的梯度直方图进行归一化(注意不是cell),一个block有4个直方图,将这4个直方图拼接成长度为36的向量,然后对这个向量进行归一化。

    因为使用的是滑动窗口,滑动步长为8个像素,所以每滑动一次,就在这个窗口上进行归一化计算得到长度为36的向量,并重复这个过程。

    计算HOG特征向量

    终于可以计算整个图像的特征描述符了,每滑动一次,一个block就得到一个长度为36的特征向量,那会得到多少个特征向量呢?

    比如上面这个图,将整幅图像划分成cell的个数为8x16,就是横向有8个cell,纵向有16个cell。每个block有2x2个cell的话,那么cell的个数为:(16-1)x(8-1)=105。即有7个水平block和15个竖直block。

    再将这105个block合并,就得到了整个图像的特征描述符,长度为 105×36=3780。

    只看理论应该就是这样了,但是在实现过程中有一些不得不需要考虑的问题:

    问题一、图片尺寸问题

    这个问题比较容易解决,可以将图片统一归一化到固定尺寸,比如128×64.

    问题二、梯度计算问题

    很多人第一反应,梯度计算会有问题么,不就是直接卷积梯度模板就可以了,其实模板[-1,0,1]不能计算边缘像素的梯度,不考虑边缘,卷积后的图像就会比原图宽高都小2个像素。然后图像就不是原本cell尺寸的整数倍,

    后面的步骤都无法进行。我看了一下matlab中对边缘像素计算梯度时的处理,即对水平方向第一行梯度为第二行减去第一行,最后一行梯度为最后一行减去其前一行;竖直方向第一列梯度为第二列减去第一列,最后一列梯度为最后一列减去其前一列。这样计算后的梯度图像尺寸还是和原图是一样的,可以继续用于后续操作。

     问题三、重复计算问题

    为了提高计算效率就要避免重复计算问题,从前面的动态图可以看到,滑动的Block与前一个(如果有的话)Block有一半的重叠,与上一层的(如果有的话)Block有一半的重叠。消除重复计算就可以提高计算效率。

    解决这个问题就需要一次计算并记录数据,在需要使用的时候调用就可以了。(当然opencv中除了避免重复计算加速还有指令集加速,关于指令集加速不在这里讨论。)

    参考博客:https://blog.csdn.net/zhazhiqiang/article/details/21047207

    参考博客:https://www.jb51.net/article/176145.htm

    参考博客:https://blog.csdn.net/sinat_42239797/article/details/90646935

    参考:https://zhuanlan.zhihu.com/p/85829145

     参考:https://www.learnopencv.com/histogram-of-oriented-gradients/

    下面例举一些以讹传讹的博客:网上资源有对有错,对错只能靠自己去分辨,以其昏昏,使人昭昭是不可能帮助别人的。

    内容有错误的博客:https://blog.csdn.net/krais_wk/article/details/81119237 (这篇错误的博客还有还几篇类似错误的博客,希望大家避开)

  • 相关阅读:
    Metadata Lock原理5
    Seconds_Behind_Master
    Metadata Lock原理4
    MySQL Troubleshoting:Waiting on query cache mutex 腾讯数据库工程师:幕南风
    Metadata Lock原理2
    Metadata Lock原理1
    Online DDL与pt-online-schema-change
    Solaris 安装JDK
    RAID 概述
    4K Block Size的Device和 Aligned IO
  • 原文地址:https://www.cnblogs.com/juluwangshier/p/13024973.html
Copyright © 2011-2022 走看看