DPM(Deformable PartModel)总结
刚参加完一个机器人比赛,其中要用到双目进行目标定位,做法是从左右场景图中找到目标区域,并用目标区域中的特征点进行双目匹配定位,定位效果非常好。考虑到实时性和简单性,寻找目标区域我用的是DPM算法,匹配效果非常好。DPM已经被实现了,不过源程序接口是基于matlab和C++的,不太符合工程需要,幸好有位大神,硕士毕设就是将DPM检测部分实现了C++化,就用了他的程序,在此特别感谢。
比完赛,收获很大,也想着把每一部分都进行总结,既方便他人,自己日后也能用得着。也欢迎朋友们提出问题进行交流哈!
1、原理
整体流程就是
1)训练:基于HOG(Histogramsof Oriented Gradients,即梯度方向直方图)构建目标轮廓模型,然后利用SVM训练轮廓模型参数;考虑到目标会发生形变,比如行人腿和头等经常发生相对位移,所以根据需要,设置子模型,通过训练得到目标各部分轮廓模型;
2)检测:将训练好的模型与场景进行匹配。
有兴趣的同学具体可参见这位大神的博客,写得很透彻http://blog.csdn.net/ttransposition/article/details/12966521。
2、程序
1)源程序(基于Matlab)
DPM由PedroFelzenszwalb提出,并用matlab实现了。
Felzenszwalb个人主页:http://cs.brown.edu/~pff/。
DPM源程序下载及相关网页:http://www.cs.berkeley.edu/~rbg/latent/index.html,可直接从中下载源程序voc-release5.tgz。
注:程序目前只能在Linux或者Mac上直接运行,要想在Windows下运行,需要进行相关修改和配置,具体可参见这位大神的方法:http://blog.csdn.net/masibuaa/article/details/17577195
2)工程可用
博客名叫yu_xianguo的大神,硕士毕业论文做的就是将DPM检测部分用C++实现了,从而可以通过在Linux和Matlba训练好模型后,直接被工程调用。不过要吐槽的是,检测程序真的很慢,将640*320的图片resize到320*240,处理一帧依然需要1s以上,直到resize到160*120才勉强达到实时要求。
程序地址:http://download.csdn.net/detail/yu_xianguo/9669917
博客:http://blog.csdn.net/yu_xianguo/article/details/49742903
3、实现
网上很多实现方法都是部分碎片化的,我这里以满足双目摄像头实时检测为主线,"voc-release5+FastDPM"为主要程序,整合网上介绍的方法,系统讲一下如何从数据采集、训练、检测等具体实现DPM检测。这里大多是借鉴别人的方法,少部分程序和方法是根据我的需要进行修改、添加的。
1)数据采集(用以训练)
训练数据格式:
正样本图像+用于程序读取数据的txt或xml文件(包含图像名、图像中目标个数、目标区域所在位置:用矩形框左上角和右下角坐标表示)
负样本图像+用于程序读取数据的txt或xml文件(包含负样本图像名)
通用数据集VOC(Visual Object Class):
Pascal VOC比赛使用的标准数据集,也是目前深度学习常用的数据集。至12年,数据集已扩充至包含20类目标,图像中包含哪个目标类、有多少目标、目标所在区域等按照统一格式写入xml文件中,如下图。
具体格式介绍可参看http://www.magicsite.cn/blog/other/other291988.html,http://grunt1223.iteye.com/blog/970449,或者直接下载数据集看看
VOC下载地址http://host.robots.ox.ac.uk/pascal/VOC/#bestpractice
制作自己的数据集:
因为我们要寻找的目标(是个玩偶)不在VOC数据集类,故我们需要重新制作图像;另外为了方便,我们不使用VOC中保存图像目标区域等信息的xml文件的格式,直接用txt按“图像名目标个数 目标左上角和右下角坐标”保存图像中目标区域信息,比如"1.jpg 1 30 40 40 200",用于程序读取正样本数据。
首先,将目标放在不同环境,不同角度拍摄图像若干,作为训练的正样本;
其次,框出正样本图像中的目标,并将信息保存在positive.txt文件中。为了方便,我用matlab写了程序,每次显示图像,再分别点目标矩形框左上角和右下角,自动将区域信息保存。感谢王诗琪同学对程序的修改,有需要的同学可直接下载http://download.csdn.net/detail/sysu_yuhaibao/9802154
然后,获取负样本。因为VOC中图像不包含我想训练的目标模型,所以直接用这些图像。需要说明的是,图像名最好去掉“0”,便于格式统一,可以直接用matlab批量处理。
最后,直接生成negative.txt文件,用于保存负样本图像名。
补充说明:当然也可以直接将自己的数据格式转换成VOC格式,这样训练模型不需要更改数据读取接口,也方便用深度学习直接训练。github上有Python直接框的代码https://github.com/tzutalin/labelImg,也有用matlab直接转化http://caffecn.cn/?/question/95
2)训练
为了方便,直接在linux下跑voc-release程序,用于训练模型:
首先,新建一个文件夹,将正样本图像、positive.txt、negative.txt文件放一起;下载VOC某个版本的代码,拷在同级目录下;
其次,针对自己的数据集,修改程序,如下:
voc_config.m:Base_dir设置成当前路径;line114的conf设置注意添加conf.project变量,总之需要将路径理清楚
data/pascal_data.m:这是用来读取训练数据的程序接口,直接将程序换成我们的数据接口程序,详见这位大神博客http://www.cnblogs.com/louyihang-loves-baiyan/p/4965992.html
PosImageFile改成我们样本图像、positive.txt和negative.txt路径
pascal.m:因为只想训练个模型,测试集制作及路径设置比较麻烦,干脆删掉后面测试部分
然后,设置linux环境:
需要matlab和gcc编译器,其中当前gcc编译器版本不能超过matlab所能支持的最高版本,根据需要设置gcc编译器当前优先支持的版本
最后训练:
建立同级目录文件夹"2007",用于保存训练结果;
psacal('bicycle',2):训练,其中第一个变量不起作用;第二个根据目标可能分为几大块设置
训练的结果保存在2007\bicyle_final.mat中model,可通过visualizemodel(model)可视化训练结果
3)检测
用的是某大神现成的C++代码,相关代码下载地址:
http://download.csdn.net/detail/yu_xianguo/9669917
http://download.csdn.net/detail/j56754gefge/8354899
首先,搭建环境:OpenCV和pthread
OpenCV就不用说了,pthread有几个教程http://blog.csdn.net/qianchenglenger/article/details/16907821
https://www.taculee.com/archives/2282
个人认为用第二个更方便一点,另外可能遇到timespec结构体问题,解决http://bbs.csdn.net/topics/391910387?page=1
以及<windows.h>中:将std::min改为min
其次,将model转换成txt文件:
因为程序接口是C++,可用大神写好的代码http://download.csdn.net/detail/j56754gefge/8354899
最后,改成我们需要的视频需求:
关键是FsatDPM.h中的FastDPM类,检测到的目标数量、目标所在位置等信息都储存在变量detections中
FastDPM.cpp:去掉不必要的显示和操作
注:检测速度很慢,处理一帧640*480图像至少1s以上,所以如果可能的话,需要尽可能resize小一点进行处理。
至此,利用DPM实现检测目标就告一段落了,由于当时做的时候比较仓促,难免有些细节忘记记录,所以可能有一些小错误,欢迎批评指正!