前言
DPM(Deformable Part Model)模型,又称为可变型部件模型,是Felzenszwalb于2008年提出的一个模型。这可以说是传统目标识别算法中最为经典的算法之一,我认为对计算机视觉有一些深入了解的同学应该对DPM模型都有所耳闻。
首先说一下DPM模型这篇文章有多牛。DPM模型的坐着Felzenszwalb凭借这个模型一举获得2010年voc挑战赛的终身成就奖,感觉还是不够牛?不知道Felzenszwalb是何许人也?Felzenszwalb正是Ross B. Girshick(DPM模型的第二作者)硕士和博士期间的导师。我想,如果连Ross B. Girshick都不知道的话就真的称不上是一个计算机视觉领域的学习者了。它正是R-CNN系列、YOLO系列等现如今被奉为经典的计算机视觉模型的提出者或共同提出者,可以说是这几年计算机视觉领域比较有作为的一位研究者。
说完DPM的作者很牛,那和DPM有什么关系?前面提到,它的作者是近几年计算机视觉领域非常知名的研究者,因此,自然而然,这几年比较成功的计算机视觉模型都会受到这个标杆性算法的影响。多尺度、锚点、可变型部件,都对后面深度学习计算机视觉带了巨大的影响。
介绍完DPM模型的背景,再回到这个算法本身。DPM模型和前文讲到的HOG整体流程非常类似,HOG采用HOG特征加linear SVM,而DPM采用多尺度特征加latent SVM,此外,DPM在特征提取方面也是在HOG特征的基础上进行稍加改进。虽然从文中看上去两者差别并不大,但是其实DPM无论是在特征提取层面还是在机器学习层面都做了巨大的改进。
首先是特征提取思想,HOG模型仅仅考虑根模型的特征,不考虑部件模型的特征,而DPM模型采用根模型加部件模型的思路,同时考虑外观和细节部分的特征。
其次是SVM方面,Latent SVM加入了潜在信息的训练。
下面就分别从特征提取到模型训练介绍一下这个模型。
特征提取
文章中讲的有点让新学者难以理解,这里我就对照着HOG特征讲解一下,更有助于理解。
两者相同的是第一步都要先计算梯度方向,然后对梯度方向进行统计。
不同之处是,HOG特征含有块(block)的概念,它首先把一副图像划分成若干个块,然后再把块划分成若干个单元,然后对单元内部的像素进行梯度统计,然后对同一个块内的特征向量进行归一化,HOG采用的是0~180度之间的梯度方向,20度一个区间,这样每个细胞单元就统计得到一个9维特征向量,一个块内就得到n * 9维特征向量。
由于HOG采用的梯度方向为0~180度方向不敏感特征,这样会丢失很多特征信息,DPM模型对HOG做了很大的改进。首先DPM模型没有快的概念,它是去一个细胞单元四角对应的领进单元的特征进行归一化,此外,更重要的是DPM不仅提取结合0~180度方向不敏感特征和0~360度方向敏感特征两种特征,它首先提取0~180度之间的特征,得到上图所示4*9维的特征,拼接起来得到13维特征向量,然后再提取0~360度之间的特征,得到18维特征向量,二者相加得到31维特征向量。
模型训练
前面介绍了一下DPM模型特征提取的方法,虽然思想与HOG有很大不同之处,但是在最基本的梯度方向统计方面是相同的。
知道了如何从一副图像中提取我们想要的特征,要进一步深入理解一个算法,我认为从模型训练、模型预测方面是最简单明了的方法,无论是传统目标识别还是深度计算机视觉。知道它是如何训练、如何预测的就知道这个模型的运作情况,输入是什么?中间经历了什么过程?输出是什么?下面就来看一下DPM模型的训练过程。
本算法采用的训练说句来自于Pascal VOC,用过这个数据集的都知道,它只标记了图片中目标的包围合,并没有标记图像的部件,例如它只标记了一个人,并没有标记人的胳膊、腿、头部等,而DPM被称为可变型部件模型,那么部件体现在哪里?怎么知道它的部件在哪?下面来了解一下它的训练过程,能够帮助理解这个算法。
DPM的在训练之前先进性了初始化,主要包括3个阶段:
初始化根滤波器
为了训练一个有m个组件的混合模型,首先将正样本按照长宽比划分成m组,然后针对每一组训练一个根滤波器F1、F2、...、Fm,在训练根模型过程中使用的是标准的SVM,不含有潜在信息,例如上图(a)、(b)就是初始化的两个根模型。
合并组件
把初始化的根滤波器合并到一个没有部件的混合模型中并且重新训练参数,在这个过程中,组件的标签和根的位置是潜在变量(组件和部件不是同一个概念)。
初始化部件滤波器
前面提到,数据集中并没有标记部件的位置,因此文中在初始化部件滤波器是用了一个简单的假设,将每个组件的部件数量固定在6个,并使用一个矩形部件形状的小池,文中贪婪地放置部件,以覆盖根过滤器得分较高的区域。
另外需要清楚的是,部件滤波器是在根据滤波器2倍分辨率的图像上进行初始化,因为分辨率越高,细节越清晰,越能提取部件的特征。
经过初始化之后就可以训练模型参数。
下面是详细的训练过程,
模型检测
前面介绍了DPM模型的特征提取和训练过程,下面就来看一下模型检测过程。
上述就是就是DPM模型检测的详细过程:
- 对输入图像进行特征提取,得到特征图和2倍分辨率的特征图
- 分别在特征图和2倍分辨率上计算根滤波器和部件滤波器的得分
- 合并根位置的得分,得到总得分
用数学语言表示,图像的总得分为,
Latent SVM
在经典的SVM中,认为训练样本的标记是严格符合类别标签的,标记的正样本就是正样本、标记负样本就是负样本,但是由于标记过程中有很多人为因素,因此,虽然能保证负样本一定是负的,但是却不能保证正样本一定属于正的。因此在训练过程中有很多潜在的未知信息,作者发现,将根位置作为一个潜在变量,可以有效地补偿正样本中存在噪声的边界框标签。
Latent SVM训练的目标函数为,
源码解析
由于DPM模型工程量较大,而且作者已经开源代码并且经过多个版本的迭代,目前非常成熟,因此不在这里逐步实现,在这里主要讲解一下怎么使用源码去检测目标和训练模型。
目前源码版本为 voc-release5,可以直接访问官网下载,
http://www.rossgirshick.info/latent/
也可以关注公众号回复voc获取。
DPM的源码是由Matlab和C++进行混编而成,Matlab主要用于做一些简单的图像处理,由于在模型训练和特征提取过程中非常缓慢,因此,为了提高效率,作者用C++实现了特征提取和模型训练部分,另外,由于C++部分使用了一些多线程的库,所以在windows下无法直接运行,需要做一些修改,在linux和mac下可以直接运行。
目标检测
用训练好的模型检测目标,主要有如下几个步骤,
- 解压缩代码。
- 运行Matlab。
- 运行'compile'函数来编译helper函数。
- 加载模型和图像。
- 检测目标。
示例,
>> load VOC2007/car_final.mat; >> im = imread('000034.jpg'); >> bbox = process(im, model, -0.5); >> showboxes(im, bbox);
训练模型
可以自己按照voc的格式准备数据,训练自己的模型,去检测相应的目标,详细过程如下,
- 下载数据集和VOC devkit工具包。
- 根据自己的数据配置voc_config.m。
- 运行'compile'函数来编译helper函数。
- 利用pascal.m脚本训练模型
示例,
>> pascal('bicycle', 3);