由于最近要做目标检测,需要用到DPM模型,DPM作为连续三年检测冠军,检测效果让人惊讶。不过最近好像又有用FAST R-CNN进行目标检测,而且效果相当不错,应用到实时处理没有问题。如果要用DPM5的话,一般大小的图片(600*600)通过划定兴趣区域,可以做到一秒一帧。
今天主要讲的还是如何在Windows下跑通DPM5的代码,其中过多的的原理我不会讲解,纯粹是从调试代码的角度考虑的。前面有不少网友在Windows下调通了Release3和Release4的代码,当然有一定的启发性。建议不要用4或者3的DPM模型,如果应用Opencv2.4.x的检测代码,速度慢的惊奇,而且opencv2.4.x也不能应用DPM5的模型。Opencv3里面应用的是DPM5的模型,如果要用里面的检测部分,需要自己训练,我看了一些网友的检测速度,还不错。而我用的DPM5的C++检测部分是xuxianguo的开源库,速度也不错,但是要用他的检测代码,必须是DPM5训练的模型。下面讲讲如何在Windows下对DPM5的代码进行编译以及训练自己的模型。
第一部分、在Windows下成功编译DPM5代码
(1)修改feature文件夹中的resize.cc部分,添加#define bzero(a,b) memset(a,0,b) 。如下图:
同时修改该.cc中的
alphainfo *ofs = new alphainfo[len];
delete []ofs;
这样resize.cc中的内容修改完毕。但是如果细心的网友可以看到其中有一个变量sy没有定义,不过不影响使用。
(2)修改fv_cache文件夹的内容
a、对于fc_cache.cc
注释掉sigaction相关的代码 ,这个结构类型在windows下未定义,注释fv_cache.cc中所有相关代码。大概位置在47、69、782-786、799行。
b、对于fv_compile.m,注释以下语句;同时按图中红色部分修改。
% if ispc
% error('This code is not supported on Windows.');
% end
c、对于model.h,添加一下语句
#define INFINITY INT_MAX ///Windows加上
注释掉double hnrms2[M.num_components];double pc[M.num_components];
换成以下部分:
double *hnrms2 = new double[M.num_components];
delete []hnrms2;注意:hnrms2有两处
double *pc = new double[M.num_components];
delete []pc;
(3)修改gdetect文件夹的内容
a、对于bounded_dt.cc,在开头添加以下语句
typedef int int32_t ;///windows下面定义/
#define INFINITY INT_MAX ///windows下面定义/
b、对于dt.cc,在开头添加以下部分
typedef int int32_t ;///windows下面定义/
a、对于cascade.cc,在开头部分添加以下语句
#define INFINITY INT_MAX//Windows下面定义///
b、对于cascade_compile.m,注释掉以下语句
% if ispc
% error('This code is not supported on Windows.');
% end
c、对于timer.h,按一下方法修改
首先是头文件:按如图修改:
其次是gettimeofday函数,该函数是linux下面的函数,需要自己在windows下实现该函数,实现代码如下:
// 定义gettimeofday函数
int gettimeofday(struct timeval *tp, void *tzp)
{
time_t clock;
struct tm tm;
SYSTEMTIME wtm;
GetLocalTime(&wtm);
tm.tm_year = wtm.wYear - 1900;
tm.tm_mon = wtm.wMonth - 1;
tm.tm_mday = wtm.wDay;
tm.tm_hour = wtm.wHour;
tm.tm_min = wtm.wMinute;
tm.tm_sec = wtm.wSecond;
tm. tm_isdst = -1;
clock = mktime(&tm);
tp->tv_sec = clock;
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}
(5)修改utils文件夹的内容
a、对于procid.m,按以下修改
i = strfind(d, '\'); // 注意windows下的路径分隔符和linux下相反
至此,就可以在Windows下编译DPM5了,点击compile.m的运行按钮,可以在命令窗口中看到如下信息:
同时在,bin文件夹中出现了新的文件,文件列表如下:
第二部分、模型训练
前面已经跑通了编译部分,现在只需要训练自己的模型即可,比较简单
a、对于pascal.m,注释掉以下语句
%diary(conf.training.log([cls '-'timestamp]));%%%%%%%%%注释掉%%%%%%%%%%%%%
b、对于voc_config.m
先注释掉以下语句
%exists_or_mkdir(conf.cascade.data_dir);
%exists_or_mkdir(conf.paths.model_dir);
然后修改BASE_DIR(注意:需要在DPM文件里面提前新建voc-release5文件夹,再在这个文件夹里面新建2007文件夹,如下图所示布局)
BASE_DIR ='e:/SEU_VocData/voc-release5'; %%%%%%原来是'/var/tmp/rbg'
最后,修改conf变量,如下所示:
还有一个问题需要注意,就是VOCdevkit的位置,我的是按如下布局:
数据集VOC2007也放到VOCdevkit文件夹中
好了,现在就可以训练自己的模型了,时间会很长,如果想看自己的代码能否跑通,可以用少量的数据集,修改部分(也是在voc_config.m)如下:
其中trainval_small和train_small是自己在相应路径下建立的文本文档,里面的编号可以直接从trainval和trian中复制一部分。
ok,现在就可以训练模型了
下面是我用DPM检测车的效果:
TIPS:
1、startup.m中的if isempty(G_STARTUP)感觉只能运行一次,我觉得此处有bug,可以尝试改为:if ~isempty(G_STARTUP)。建议不改,我说的只是我的理解,可以忽略这点。
2、Matlab建议不要采用破解版,我第一次用的是Matlab2014Ra版本,中途有个优化函数一直报错,是matlab内部错误,后来换了个版本matlab2015,非破解版,就没有这个问题了,当然是遇到matlab内部错误才需要考虑这个问题。
模型训练完毕,可以通过网友分享的代码将mat转化为txt文档,再采用C++检测代码调用txt模型。
好了,就这些,第一次发帖,不对的地方多多包涵。有问题大家可以一起讨教。