DPM目标检测算法

      DPM算法由Felzenszwalb于2008年提出,是一种基于部件的检测方法,对目标的形变具有很强的鲁棒性。目前DPM已成为众多分类、分割、姿态估计等算法的核心部分,Felzenszwalb本人也因此被VOC授予"终身成就奖"。

    DPM算法采用了改进后的HOG特征,SVM分类器和滑动窗口(Sliding Windows)检测思想,针对目标的多视角问题,采用了多组件(Component)的策略,针对目标本身的形变问题,采用了基于图结构(Pictorial Structure)的部件模型策略。此外,将样本的所属的模型类别,部件模型的位置等作为潜变量(Latent Variable),采用多示例学习(Multiple-instance Learning)来自动确定。

1、通过Hog特征模板来刻画每一部分,然后进行匹配。并且采用了金字塔,即在不同的分辨率上提取Hog特征。

2、利用提出的Deformable PartModel,在进行object detection时,detect window的得分等于part的匹配得分减去模型变化的花费。

3、在训练模型时,需要训练得到每一个part的Hog模板,以及衡量part位置分布cost的参数。文章中提出了LatentSVM方法,将deformable part model的学习问题转换为一个分类问题:利用SVM学习,将part的位置分布作为latent values模型的参数转化为SVM的分割超平面。具体实现中,作者采用了迭代计算的方法,不断地更新模型。

 rootfilters根滤波器数组,其每个元素表示一个组件模型的根滤波器的信息,每个元素包括3个字段:

        size:根滤波器的尺寸,以cell为单位,w*h

        w:根滤波器的参数向量,维数为(w*h)*31

        blocklabel:此根滤波器所在的数据块标识

滤波器(模版)就是一个权重向量一个w * h大小的滤波器F是一个含w * h * 9 * 4个权重的向量(9*4是一个HOG细胞单元的特征向量的维数)。所谓滤波器的得分就是此权重向量与HOG金字塔中w * h大小子窗口的HOG特征向量的点积(DotProduct)。

有关可变形部件模型(Deformable Part Model)的一些说明https://blog.csdn.net/masibuaa/article/details/17534151

DPM的特征

DPM采用了HOG特征,并对HOG特征进行了一些改进。

     Hog特征提取的过程:

1.对原图像gamma校正,img=sqrt(img);

2.求图像竖直边缘,水平边缘,边缘强度,边缘斜率。

3.将图像每16*16(取其他也可以)个像素分到一个cell中。对于256*256的lena来说,就分成了16*16个cell了。

4.对于每个cell求其梯度方向直方图。通常取9(取其他也可以)个方向(特征),也就是每360/9=40度分到一个方向,方向大小按像素边缘强度加权。最后归一化直方图。

5.每2*2(取其他也可以)个cell合成一个block,所以这里就有(16-1)*(16-1)=225个block。

6.所以每个block中都有2*2*9=36个特征,一共有225个block,所以总的特征有225*36个。

当然一般HOG特征都不是对整幅图像取的,而是对图像中的一个滑动窗口取的。
 

      DPM改进后的HOG特征取消了原HOG中的块(Block),只保留了单元(Cell),如上图所示,假设一个8*8的Cell,将该细胞单元与其对角线临域的4个细胞单元做归一化操作,所以效果和原HOG特征非常类似。计算梯度方向时可以计算有符号(0-360°)或无符号(0-180°)的梯度方向,有些目标适合使用有符号的梯度方向,而有些目标适合使用无符号的梯度,作为一种通用的目标检测方法,DPM与原HOG不同,采用了有符号梯度和无符号梯度相结合的策略。

      提取有符号的HOG梯度,0-360度将产生18个梯度向量,提取无符号的HOG梯度,0-180度将产生9个梯度向量。如果直接将特征向量化,一个8*8的细胞单元将会产生(18+9)*4=108,维度有点高 。

      Felzenszwalb提取了大量单元的无符号梯度,每个单元共 维特征,并进行了主成分分析(Principal Component Analysis,PCA),发现使用前11个特征向量基本上可以包含所有的信息,不过为了快速计算,作者由主成分可视化的结果得到了一种近似的PCA降维效果。

      具体来说:首先,只提取无符号的HOG梯度,将会产生4*9=36维特征,将其看成一个4*9的矩阵,分别将行和列分别相加,最终将生成4+9=13个特征向量,得到13维特征,基本上能达到HOG特征36维的检测效果。为了提高那些适合使用有符号梯度目标的检测精度,作者再对18个有符号梯度方向求和得到18维向量,也加进来,这样,一共产生13+18=31维梯度特征。实现了很好的目标检测。

DPM的检测模型

                                                                                    

                             (a)                                           (b)                                             (c)

     DPM V3版本的目标检测模型由两个组件构成,每一个组件由一个根模型和若干部件模型组成。图 4.5(a)和图 4.5(b)是其中一个组件的根模型和部件模型的可视化的效果(这个只是可视化的结果,不要认为是用这个当做模板与原图特征图做卷积!!,真正与原图特征图做卷积计算的是检测算子,即SVM分类模型系数w)每个单元内都是SVM分类模型系数w梯度方向加权叠加,梯度方向越亮的方向可以解释为行人具有此方向梯度的可能性越大。如图 4.5(a),根模型比较粗糙,大致呈现了一个直立的正面/背面行人。如图 4.5(b)所示,部件模型为矩形框内的部分,共有6个部件,分辨率是根模型的两倍,这样能获得更好的效果。从中,我们可以明显地看到头、手臂等部位。为了降低模型的复杂度,根模型和部件模型都是轴对称的。图 4.5(c)为部件模型的偏离损失,越亮的区域表示偏离损失代价越大,部件模型的理想位置的偏离损失为0。

(图中每一个白色的发散的叉代表每一个cell的梯度直方图,他本质是一个31维的特征向量,我的理解:这个模型好像并不是梯度的特征向量,而是通过SVM学习到的梯度特征向量的权值,即“w”???

DPM检测流程:

      DPM采用了传统的滑动窗口检测方式,通过构建尺度金字塔在各个 尺度搜索。下图为某一尺度下的行人检测流程,即行人模型的匹配过程。某一位置与根模型/部件模型的响应得分,为该模型与以该位置为锚点(即左上角坐标)的子窗口区域内的特征的内积。也可以将模型看作一个滤波算子,响应得分为特征与待匹配模型的相似程度,越相似则得分越高

      左侧为根模型的检测流程,跟模型响应的图中,越亮的区域代表响应得分越高。右侧为各部件模型的检测过程。首先,将特征图像与模型进行匹配得到部件模型响应图。然后,进行响应变换:以锚点为参考位置,综合考虑部件模型与特征的匹配程度部件模型相对理想位置的偏离损失,得到的最优的部件模型位置和响应得分。

                                          

     如上图所示,对于任意一张输入图像,提取其DPM特征图,然后将原始图像进行高斯金字塔上采样放大原图像,然后提取其DPM特征图(2倍分辨率)。将原始图像的DPM特征图和训练好的Root filter做卷积操作,从而得到Root filter的响应图。对于2倍图像的DPM特征图,和训练好的Part filter做卷积操作,从而得到Part filter的响应图。然后对其精细高斯金字塔的下采样操作。这样Root filter的响应图和Part filter的响应图就具有相同的分辨率了。然后将其进行加权平均,得到最终的响应图。亮度越大表示响应值越大。


响应值(score)的计算:

尺度为的层,以为锚点的响应值得分公式如下:

         

其中,x0, y0分别为锚点的横坐标,纵坐标,l_0表示尺度。为根模型的检测分数。

由于同一个目标有多个组件,而不同组件模型的检测分数需要对齐,所以需要设定偏移系数b。

:第i个部件模型的响应,由于部件模型的分辨率是根模型的2倍,因此部件模型需要在尺度层l_0-\lambda匹配。因此,锚点的坐标也需要重新映射到尺度层l_0-\lambda,即放大一倍,,部件模型i 相对锚点的偏移为v_i,所以在尺度层l_0-\lambda,部件模型的理想位置为

 其部件模型 partfilter_i 的响应得分如下:

                           

      上式是在patfilter理想位置,即anchor position的一定范围内,寻找一个综合匹配和形变最优的位置。其中,为部件模型在尺度层的理想位置,为相对的偏移量;

      为部件模型在处的匹配得分;

      为偏移所损失的得分,为偏移向量,为组件模型的锚点和组件模型的检测点间的距离;

        d_i为偏移损失系数,是模型训练时需要学习的参数,模型初始化时,,此时即为偏移损失为偏移量相对理想位置的欧氏距离。

   简单的说,这个公式表明,组件模型的响应越高,各个组件和其相应的锚点距离越小,则响应分数越高,越有可能是待检测的物体。

下面这种方式更好理解:

1、计算一个HOG金字塔:通过计算标准图像金字塔中每层图像的HOG特征得到HOG特征金字塔,HOG金字塔中每一层的的最小单位是细胞单元(cell)。

       滤波器(模版)就是一个权重向量,一个w * h大小的滤波器F是一个含w * h * 9 * 4个权重的向量(9*4是一个HOG细胞单元的特征向量的维数)。所谓滤波器的得分就是此权重向量与HOG金字塔中w * h大小子窗口的HOG特征向量的点积(DotProduct)

       而检测窗口的得分是根滤波器的分数加上各个部件的分数的总和,每个部件的分数是此部件的各个空间位置得分的最大值,每个部件的空间位置得分是部件在该子窗口上滤波器的得分减去变形花费。

       假设H是HOG金字塔,p = (x, y, l) 表示金字塔第l层 (x, y) 位置的一个细胞单元。φ(H, p, w, h)是将金字塔H中以p为左上角点的w * h大小子窗口的HOG特征串接起来得到的向量。所以,滤波器F在此检测窗口上的得分为:F·φ(H, p, w, h)。我们使用φ(H,p)代表φ(H, p, w, h)。

       所以,含n个部件的模型可以通过根滤波器F0和一系列部件模型(P1,..., Pn)来定义,其中Pi = (Fi, vi, si, ai, bi)。Fi是第i个部件的滤波器;vi和si都是二维向量,都以细胞单元为单位,vi指明第i个部件位置的矩形中心点相对于根位置的坐标,si是此矩形的宽高;ai和bi也都是二维向量,指明一个二次函数的参数,此二次函数用来对第i个部件的每个可能位置进行评分。

       模型在HOG金字塔中的位置可以用z = (p0, ..... , pn)来表示,当i=0时,pi = (xi, yi,li )表示根滤波器的位置;i>0时,pi = (xi, yi,li )表示第i个部件滤波器的位置。我们假设每个部件所在层的HOG细胞单元的尺寸是根所在的层的细胞单元尺寸的一半。空间位置的得分等于每个部件滤波器的得分(从数据来看)加上(?加上减去都一样,通过正负号控制就行)每个部件的位置相对于根的得分(从空间来看)。即:

         

(1)式中左边表示所有滤波器(i从0开始,包括根滤波器和部件滤波器)的得分(即滤波器的权重向量与对应的HOG特征向量的点积),右边表示所有部件滤波器(i从1开始)的形变花费

其中:

                   

表示部件i的变形程度, 在-1到1之间。

(x0,y0)是根滤波器在其所在层的坐标,为了统一到部件滤波器所在层需乘以2。vi是部件i相对于根的坐标偏移,所以2(x0, y0)+vi表示未发生形变时部件i的坐标,(xi,yi)是部件i响应最大值时的所处的空间坐标位置。

所以(xi,yi) – [2(x0,y0) + vi]是部件i的形变位移量,再除以部件的矩形框大小si可保证在-1到1之间。计算过程如下图:

图中每个格子表示部件所在HOG金字塔层的细胞单元,红框表示某部件未发生位移时的位置,w=7,h=3.黑框表示部件的实际位置,因此

                                         

from:https://blog.csdn.net/masibuaa/article/details/17534151


多示例学习(Multiple-instance learning) MI-SVM

       一般机器学习算法,只是给了正负样本集。负样本集里面的样本都是负的,但是正样本里面的样本不一定都是正的,但是至少有一个样本是正的。比如检测人的问题,一张天空的照片就可以是一个负样本集;一张某某自拍照就是一个正样本集(你可以在N个区域取N个样本,但是只有部分是有人的正样本)。这样正样本的类别就很不明确,传统的方法就没法训练。

       图像的不是有标注吗?有标注就应该有类别标号啊?这是因为图片是人标的,数据量特大,难免会有些标的不够好,这就是所谓的弱监督集(weakly supervised set)。所以如果算法能够自动找出最优的位置,那分类器不就更精确吗?比如自行车的车轮的位置,是完全没有位置标注的,只知道在bounding box区域附件有一个车轮。不知道精确位置,就没法提取样本。这种情况下,车轮会有很多个可能的位置,也就会形成一个正样本集,但里面只有部分是包含轮子的。

       针对上述问题《Support Vector Machines for Multiple-Instance Learning》提出了MI-SVM。本质思想是将标准SVM的最大化样本间距扩展为最大化样本集间距。具体来说是选取正样本集中最像正样本的样本用作训练,正样本集内其它的样本就等候发落。同样取负样本中离分界面最近的负样本作为负样本。因为我们的目的是要保证正样本中有正,负样本不能为正。就基本上化为了标准SVM。取最大正样本(离分界面最远),最小负样本(离分界面最近):

Latent SVM

      Latent-SVM实质上和MI-SVM是一样的。区别在于扩展了Latent变量。首先解释下Latent变量,MI-SVM决定正样本集中哪一个样本作为正样本的就是一个latent变量。不过这个变量是单一的,比较简单,取值只是正样本集中的序号而已。

      DPM中也是要选择最大的正样本,但是它的latent变量就特别多。比如bounding box的实际位置,在HOG特征金字塔中的level,某样本属于哪一类component。也就是说我们有了一张正样本的图片,标注了bounding box,我们要在某一位置,某一尺度,提取出一个最大正样本作为某一component的正样本。

     不太妥当的例子来说明LSVM好了 比如我们有一个数据集是一组生物的身体特征(没有性别标注)然后输出的label是这个生物是不是人,但是男人与女人的标准显然是完全不同的,所以我们要引入一个隐藏变量V,V=1的时候表示男,V=0的时候表示女,从而我们在进行训练的时候,为了达到最好分类,我们要对男性女性分别有一个不同的SVM分类器的系数,然而由于没有性别标注,我们在训练的时候要找到一个隐变量的最优配置{V},使得整个分类器在对男女分别训练之后效果达到最好,最后训练的结果也就包含了样本中每个个体的性别变量V的配置,这也就是隐变量了,当我们用训练好的模型进行判别新的样本的时候,我们只需要分别计算新的样本在每个模型下的配置,用其中得分最高的那个配置判断该样本是不是人。当然,引入这样的隐变量在模型训练的时候会更麻烦,每次迭代求最优值都要考虑隐变量配置的调整。

      所以总结下来,我对LSVM的理解就是,解决没有标准的混合模型的样本数据中未知的隐变量配置问题的一种手段。不过还是想说,标注是王道啊,有标注的时候老子才不像用LSVM!

    比如图像识别自行车,看图片中是否有把手 是否有轮子,而训练集是只是一些被圈起来的自行车,文章里先用一个svm粗略的检测得到一些components label 比如这些地方像把手,那些地方像轮子,然后再把 components label 加上root location 作为latent label 输入latent SVM里。

  链接:https://www.zhihu.com/question/27726840/answer/66979658
  

直接看Latent-SVM的训练过程:

       3-6就对于MI-SVM的第一步。12就对应了MI-SVM的第二步。作者这里直接用了梯度下降法,求解最优模型β。

       LatentSVM引入Data-minig:作者为什么不直接优化,还搞个Data-minig干嘛呢?因为,负样本数目巨大,Version3中用到的总样本数为2^28,其中Pos样本数目占的比例特别低,负样本太多,直接导致优化过程很慢,因为很多负样本远离分界面对于优化几乎没有帮助。Data-minig的作用就是去掉那些对优化作用很小的Easy-examples保留靠近分界面的Hard-examples

                        

传统的Hog+SVM和DPM+LatentSVM的区别如上面公式所示。

1:是传统的SVM训练过程,与HOG算法一致。作者是随机将正样本按照aspect ration(长宽比)排序,然后很粗糙的均分为两半训练两个component的rootfilte。这两个rootfilter的size也就直接由分到的pos examples决定了。后续取正样本时,直接将正样本缩放成rootfilter的大小。

2:是LSVM训练。Latent variables 有图像中正样本的实际位置包括空间位置(x,y),尺度位置level,以及部件的类别c,即属于部件1 还是属于部件2。要训练的参数为两个 rootfilter(w),offset(b)

3:也是LSVM过程。子模型的添加:作者固定了每个部件component有6个partfilter,但实际上还会根据实际情况减少。为了减少参数,partfilter都是对称的。partfilter在rootfilter中的锚点(anchor location)在按最大energy选取partfilter的时候就已经固定下来了。

    这阶段的Latent variables是最多的有:rootfilter(x,y,scale),partfilters(x,y,scale)。要训练的参数为 rootfilters, rootoffset, partfilters, defs(的偏移Cost)。偏移量offset就是加在每个组件模型的得分公式最后的一个实数值https://blog.csdn.net/masibuaa/article/details/25906985


    DPM算法思想:输入一幅图像,对图像提取图像特征,针对某个物件制作出相应的激励模板,在原始的图像中计算,得到该激励效果图,根据激励的分布,确定目标位置。

      制作激励模板就相当于人为地设计一个卷积核,一个比较复杂的卷积核,拿这个卷积核与原图像进行卷积运算得到一幅特征图。比如拿一个静止站立的人的HOG特征形成的卷积核,与原图像的梯度图像进行一个卷积运算,那么目标区域就会被加密。

     那么说到这里就会出现一个问题,人在图像中可能有各种的姿态,比如躺着,趴着,坐着等等,我们只用一个静止站立状态的人的激励模板去做探测就会失败。也就是说图像中的物件可能会发生形变,那么我们用固定的激励模板去探测目标物件的时候就不再适用,那么该如何解决这一问题呢,这就引出了局部模板,也就是说,我们不做一个整体的人的激励模板,转而去做人的部分组件的模板,比如头、胳膊、腿等,其实这就是DPM算法。再概括一下,HOG的特征提取比较死板,一定要是一个人,这个人还只能是特定的姿态比如站立,动作幅度改变不能太大。而DMP就是先检测整个人,再检测四肢,然后综合两者的信息去判断。

DPM算法的步骤:

  1. 首先要有根模型(root filter)和若干部件模型(part filter)和部件模型的偏离损失。这些东西就是通过已有的人体,四肢等样本提取HOG特征然后经过svm训练而来的。
  2. 用root filter提取原始图像的DMP特征图,再对DMP特征图用root filter和part filter计算响应图。(就是一个模版匹配)
  3. 加权平均root的和part的,得到最终的融合特征图
  4. 对融合特征进行传统分类,回归得到目标位置。

DPM算法优点:

方法直观简单;运算速度块;适应动物变形;

DPM算法缺点:

1、性能一般,无法适应大幅度的旋转,稳定性很差;

2、激励特征人为设计,工作量大;

      这种方法不具有普适性,因为用来检测人的激励模板不能拿去检测小猫或者小狗,所以在每做一种物件的探测的时候,都需要人工来设计激励模板,为了获得比较好的探测效果,需要花大量时间去做一些设计,工作量很大。

from:https://blog.csdn.net/qq_14845119/article/details/52625426

from:https://blog.csdn.net/qq_32742009/article/details/81394560

from :https://blog.csdn.net/carson2005/article/details/22499565

  • 17
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
DPM(Deformable Part-based Model)是一种基于部件的目标检测算法,它在2009年被提出。由于DPM算法实现较为复杂,需要使用到许多库和工具,因此在这里给出一个简化版的DPM目标检测算法的Python源代码,以供参考。 ```python import cv2 import numpy as np from skimage import transform as tf # 加载模型 model = cv2.dpm.readDPM('model.dpm') # 定义滑动窗口大小 winSize = (64, 128) # 定义检测阈值 thresh = 0.5 # 加载测试图片 img = cv2.imread('test.jpg') # 定义图像金字塔 scale = 1.2 pyramid = [img] for i in range(5): pyramid.append(cv2.resize(pyramid[-1], (int(pyramid[-1].shape[1]/scale), int(pyramid[-1].shape[0]/scale)))) # 定义滑动窗口步长 step = 8 # 定义横向和纵向滑动窗口数量 nx = int((img.shape[1]-winSize[0])/step) + 1 ny = int((img.shape[0]-winSize[1])/step) + 1 # 遍历所有滑动窗口 for i in range(ny): for j in range(nx): # 截取当前滑动窗口 x1 = j*step y1 = i*step x2 = x1 + winSize[0] y2 = y1 + winSize[1] roi = img[y1:y2, x1:x2] # 对滑动窗口进行金字塔缩放 for k in range(6): resized_roi = cv2.resize(roi, (int(winSize[0]/scale**k), int(winSize[1]/scale**k))) # 对当前滑动窗口进行HOG特征提取 hog = cv2.HOGDescriptor(winSize, (16,16), (8,8), (8,8), 9) features = hog.compute(resized_roi) # 对当前滑动窗口进行分类 score = model.predict(features) # 如果分类得分超过阈值,则认为检测到目标 if score > thresh: # 计算目标框的位置 x1 = int(x1/scale**k) y1 = int(y1/scale**k) x2 = int(x2/scale**k) y2 = int(y2/scale**k) # 绘制目标框 cv2.rectangle(img, (x1,y1), (x2,y2), (0,255,0), 2) # 显示检测结果 cv2.imshow('result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 需要注意的是,这个代码只是DPM目标检测算法的一个简化版本,实际的实现可能包含更多的细节和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值