在Windows下執行Felzenszwalb的star-cascade DPM(Deformable Part Models)目標檢測Matlab原始碼
可變形部件模型Deformable Part Models(DPM)是非常經典的目標檢測演算法,由Felzenszwalb提出,本文介紹如何在windows下執行Felzenszwalb給出的DPM演算法的star-cascade版本voc-release4.01-star-cascade,相比於基本版本voc-release4.01,star-cascade版本增加了PCA降維,檢測速度可提高十幾倍。
有關Deformable Part Model參見論文
A Discriminatively Trained, Multiscale,Deformable Part Model[CVPR 2008]的中文翻譯
Object Detection with Discriminatively Trained Part Based Models[PAMI 2010]的中文翻譯
及 有關可變形部件模型(Deformable Part Model)的一些說明
Deformable Part Model 相關網頁(其中有原始碼下載):http://www.cs.berkeley.edu/~rbg/latent/index.html
star-cascade版本相關網頁(其中有原始碼下載):http://people.cs.uchicago.edu/~rbg/star-cascade/
Pedro Felzenszwalb的個人主頁:http://cs.brown.edu/~pff/
PASCAL VOC 目標檢測挑戰:http://pascallin.ecs.soton.ac.uk/challenges/VOC/
同樣,Felzenszwalb給出的star-cascade DPM也只能在Linux或Mac系統上執行,我們可以對其進行一些修改,使之可以在Windows的Matlab上跑起來。
我的環境:Win7 + Matlab R2012b(其中配置VS2010中的c++編譯器)
首先,在作者的網站上下載原始碼,由於star-cascade必須在DPM的基本版本之上執行,所以還需要下載對應的DPM原始碼,我這裡用的都是第4版,即voc-release4.01 和 voc-release4.01-star-cascade。下載完成後首先要在Windows上把voc-release4.01跑起來,詳見這篇文章:
在Windows下執行Felzenszwalb的Deformable Part Models(voc-release4.01)目標檢測matlab原始碼
下載完voc-release4.01-star-cascade後,將star-cascade資料夾解壓到voc-release4.01資料夾中(因為要在DPM之上執行)。發現其中有很多“._”開頭的檔案,這些是Linux或Mac系統上使用的(具體我也不是很懂),全部刪掉,windows下用不到。其子資料夾data中的._開頭的檔案也可以刪掉。
然後用notepad++或其他編輯器開啟README,看看說明。README中說先進入star-cascade資料夾,編譯原始碼,然後退回到voc-release4目錄執行。在Linux下可以直接執行作者寫好的Makefile檔案進行編譯,在windows上我們需要手動編譯。開啟Makefile檔案,大體上看一看,發現需要編譯cascade.cc,model.cc和fconv_var_dim.cc三個檔案,接下來嘗試用mex進行編譯,看看會遇到什麼錯誤。
步驟1 編譯cascade.cpp和model.cpp
首先將cascade.cc,model.cc,fconv_var_dim.cc這三個檔案的副檔名都改為.cpp,否則windows中無法識別cc檔案。然後將matlab的工作目錄定位到star-cascade資料夾。cascade.cpp和model.cpp需要同時編譯,在matlab命令列中輸入:
>> mex cascade.cpp model.cpp
出現錯誤提示:
\voc-release4.01-star-cascade\star-cascade\timer.h(6) : fatal error C1083: Cannot open include file: 'sys/time.h': No such file or directory
D:\PROGRA~1\MATLAB\R2012B\BIN\MEX.PL: Error: Compile of 'cascade.cpp' failed.
Error using mex (line 206)
Unable to complete successfully.
是說找不到timer.h中的sys/time.h標頭檔案,網上查了查,這是linux中的檔案,將“sys/”去掉,直接include time.h,因為windows中也有time.h。再次輸入上面的編譯命令,結果為:
voc-release4.01-star-cascade\star-cascade\timer.h(21) : error C2079: 'tv' uses undefined struct 'timer::tic::timeval'
voc-release4.01-star-cascade\star-cascade\timer.h(22) : error C3861: 'gettimeofday': identifier not found
voc-release4.01-star-cascade\star-cascade\timer.h(23) : error C2228: left of '.tv_sec' must have class/struct/union type is 'int'
voc-release4.01-star-cascade\star-cascade\timer.h(23) : error C2228: left of '.tv_usec' must have class/struct/union type is 'int'
voc-release4.01-star-cascade\star-cascade\timer.h(28) : error C2079: 'tv' uses undefined struct 'timer::toc::timeval'
voc-release4.01-star-cascade\star-cascade\timer.h(29) : error C3861: 'gettimeofday': identifier not found
voc-release4.01-star-cascade\star-cascade\timer.h(30) : error C2228: left of '.tv_sec' must have class/struct/union type is 'int'
voc-release4.01-star-cascade\star-cascade\timer.h(30) : error C2228: left of '.tv_usec' must have class/struct/union type is 'int'
說明windows中的time.h和linux中的不一樣,沒有結構體timeval的定義,也沒有gettimeofday函式,網上找了一段替代linux中的gettimeofday函式的程式碼,加到timer.h檔案中,同時再加兩個標頭檔案,修改完的timer.h檔案如下:
#ifndef _TIMER_H_
#define _TIMER_H_
#include <string>
#include <sstream>
//#include <sys/time.h> //windows下的time.h中沒有timeval定義
#include<windows.h> //windows下代替<sys/time.h>
#include<time.h> //windows下代替<sys/time.h>
using namespace std;
//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);
}
class timer {
public:
timer(string timer_name) {
name = timer_name;
total_time = 0;
calls = 0;
};
~timer() {};
void tic() {
struct timeval tv;
gettimeofday(&tv, NULL);
last_time = (double)tv.tv_sec + 1e-6*(double)tv.tv_usec;
calls++;
};
void toc() {
struct timeval tv;
gettimeofday(&tv, NULL);
double cur_time = (double)tv.tv_sec + 1e-6*(double)tv.tv_usec;
total_time += cur_time - last_time;
};
const char *msg() {
ostringstream oss;
oss << "timer '" << name
<< "' = " << total_time << " sec in "
<< calls << " call(s)";
return oss.str().c_str();
};
void mexPrintTimer() {
mexPrintf("timer '%s' = %f sec in %d call(s)\n", name.c_str(), total_time, calls);
};
double getTotalTime() {
return total_time;
};
private:
string name;
int calls;
double last_time;
double total_time;
};
#endif
改完timer.h後,再次編譯,錯誤提示為:
cascade.cpp(116) : error C2065: 'INFINITY' : undeclared identifier
cascade.cpp(130) : error C2065: 'INFINITY' : undeclared identifier
cascade.cpp(170) : error C2065: 'INFINITY' : undeclared identifier
cascade.cpp(216) : error C2065: 'INFINITY' : undeclared identifier
cascade.cpp(217) : error C2065: 'INFINITY' : undeclared identifier
cascade.cpp(218) : error C2065: 'INFINITY' : undeclared identifier
cascade.cpp(219) : error C2065: 'INFINITY' : undeclared identifier
INFINITY是linux中的無窮大,windows下沒有,可以自己定義一個,在cascade.cpp中增加下面的語句:
//INFINITY是Linux下的無窮大標誌,windows下沒有,自己定義一個
#define INFINITY 0xFFFFFFFFF
然後繼續mex cascade.cpp model.cpp,沒有錯誤了。
步驟2 編譯fconv_var_dim.cpp
在matlab命令列中輸入:
>> mex fconv_var_dim.cpp
提示為:
fconv_var_dim.cpp(2) : fatal error C1083: Cannot open include file: 'pthread.h': No such file or directory
D:\PROGRA~1\MATLAB\R2012B\BIN\MEX.PL: Error: Compile of 'fconv_var_dim.cpp' failed.
Error using mex (line 206)
Unable to complete successfully.
找不到pthread.h,可以從這個網站下載Pthreads的win32版本,下載整個pthreads-w32-2-9-1-release壓縮包,我們要用到其中兩個標頭檔案。
將pthread.h的目錄新增到環境變數,嫌麻煩的話直接把pthread.h放到VS2010安裝目錄的include資料夾中。再次編譯,提示:
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\pthread.h(299) : fatal error C1083: Cannot open include file: 'sched.h': No such file or directory
D:\PROGRA~1\MATLAB\R2012B\BIN\MEX.PL: Error: Compile of 'fconv_var_dim.cpp' failed.
Error using mex (line 206)
Unable to complete successfully.
sched.h就是我們需要的第二個檔案,也在pthreads-w32-2-9-1-release中,把它也複製到VS2010的include資料夾中,再次編譯,提示:
\voc-release4.01-star-cascade\star-cascade\fconv_var_dim.cpp(77) : error C4716: 'process' : must return a value
D:\PROGRA~1\MATLAB\R2012B\BIN\MEX.PL: Error: Compile of 'fconv_var_dim.cpp' failed.
Error using mex (line 206)
Unable to complete successfully.
開啟fconv_var_dim.cpp檔案,看process函式的定義,函式型別是void *,但函式體中沒有return,在windows中執行voc-release4.01的文章中說過,可以通過將process函式的型別改為void來解決沒有返回值的錯誤,但這裡如果還這樣改的話會出現下面的錯誤:
fconv_var_dim.cpp(128) : error C2664: 'pthread_create' : cannot convert parameter 3 from 'void (__cdecl *)(void *)' to 'void *(__cdecl *)(void *)'
None of the functions with this name in scope match the target type
D:\PROGRA~1\MATLAB\R2012B\BIN\MEX.PL: Error: Compile of 'fconv_var_dim.cpp' failed.
Error using mex (line 206)
Unable to complete successfully.
因為後面有個用process函式做引數的地方:
if (pthread_create(&ts[i], NULL, process, (void *)&td[i]))
改變process函式的型別會導致引數型別不匹配而無法傳參。
怎麼辦呢,到這裡我也沒轍了。
翻牆去google上查,偶然發現一個大牛的個人主頁,他做了star-cascade DPM演算法的改進,網頁上有原始碼下載,使用說明裡有句話:
The distribution comes with precomputed mex files for 64-bit windows, linux and mac systems.也就是說他為64位的windows、linux和mac系統編譯好了檔案,那麼他的原始碼會不會是win32上的呢,趕緊下載下來一看,果真,他提供了win32版本的和MacOSX版本的原始碼,而且也是基於voc-release4進行改進的。所以,我們可以下載 http://vision.mas.ecp.fr/Personnel/iasonas/dpms.html 上的dtbb_1.zip原始碼,解壓後,進入star-cascade目錄,可以看到幾個cc檔案都為64位系統mex編譯好了,真是良心啊。
.mexa64是給linux-64編譯好的,.mexmaci64是給Mac-64編譯好的,.mexw64是為win-x64編譯好的。所以,如果你是64位系統,就不用編譯了,人家已經給弄好啦。我們編譯完成後,會生成一個字尾為.mexw32的檔案,這個檔案可以看做c++和matlab之間的一個介面,可以在matlab中呼叫,實現matlab和c++混合程式設計。
再仔細看看,發現他寫了個makefile_windows.m檔案,方便windows使用者快速編譯,其實裡面也就兩句話:
mex cascade.cc model.cpp
mex fconv_var_dim.cpp
不用說,幾個需要編譯的cpp檔案肯定也已經針對win32系統做了修改,我們可以挨個看看,cascade.cpp中,他直接將include timer.h註釋掉了,所以timer.h中不相容windows的都不用管了,更簡單,加入了INFINITY的定義 #define INFINITY 1e5。再看看fconv_var_dim.cpp,也就是我不會改的地方,他是在process函式的末尾加上:
#ifdef MThread
pthread_exit(NULL);
#else
return NULL;
#endif
然後將用到process函式的地方改為:
#ifdef MThread
if (pthread_create(&ts[i], NULL, process, (void *)&td[i]))
mexErrMsgTxt("Error creating thread");
#else
process((void *)&td[i]);
mxSetCell(plhs[0], i, td[i].mxC);
#endif
我們直接用他的fconv_var_dim.cpp檔案替換原來的,再次mex fconv_var_dim.cpp,無錯誤提示,成功了。
步驟3 執行star-cascade
將matlab的工作目錄返回到voc-release4.01,先輸入命令:
addpath star-cascade
將star-cascade加入搜尋目錄,然後呼叫cascade_demo,就可以看到檢測結果啦。
最後再提一下,這個網站 http://vision.mas.ecp.fr/Personnel/iasonas/dpms.html 上的DPM演算法改進應該很不錯,以前沒接觸到,以後要好好看看。最想說的是,此網站提供的原始碼真心不錯。
參考
在Windows下執行Felzenszwalb的star-cascade
DPM(Deformable Part Models)目標檢測Matlab原始碼
相關文章
- 在Windows下執行Felzenszwalb的Deformable Part Models(voc-release4.01)目標檢測matlab原始碼WindowsORMMatlab原始碼
- 在windows下執行Felzenszwalb的Deformable Part Model(DPM)原始碼voc-release3.1來訓練自己的模型WindowsORM原始碼模型
- 用DPM(Deformable Part Model,voc-release3.1)演算法在INRIA資料集上訓練自己的人體檢測模型ORM演算法模型
- 使用判別訓練的部件模型進行目標檢測 Object Detection with Discriminatively Trained Part Based Models模型ObjectAI
- 在安卓上執行yolov8目標檢測模型(ncnn)安卓YOLO模型CNN
- 關於DPM(Deformable Part Model)演算法中模型結構的解釋ORM演算法模型
- 關於DPM(Deformable Part Model)演算法中模型視覺化的解釋ORM演算法模型視覺化
- 目標檢測:二維碼檢測方案
- windows bat指令碼 後臺執行目標exeWindowsBAT指令碼
- 目標檢測
- 目標跟蹤:KCF執行流程圖(matlab版本)流程圖Matlab
- java在windows下執行JavaWindows
- 九、目標檢測
- 基於YOLOv4的目標檢測系統(附MATLAB程式碼+GUI實現)YOLOMatlabGUI
- 使用 YOLO 進行實時目標檢測YOLO
- 目標檢測---教你利用yolov5訓練自己的目標檢測模型YOLO模型
- 基於YOLOv5的目標檢測系統詳解(附MATLAB GUI版程式碼)YOLOMatlabGUI
- 目標檢測面面觀
- 目標檢測之SSD
- 目標檢測綜述
- 28-目標檢測
- linux下QT在windows下執行LinuxQTWindows
- 使用關鍵點進行小目標檢測
- windows下檢視oracle 執行緒 (session)WindowsOracle執行緒Session
- SSD 目標檢測 Keras 版Keras
- 目標檢測發展方向
- 目標檢測之YOLO系列YOLO
- 【目標檢測】R-CNNCNN
- 深度學習之目標檢測與目標識別深度學習
- 目標檢測相關論文
- 【目標檢測】Bounding Box Regression
- 深度學習之目標檢測深度學習
- 目標檢測:Segmentation is All You Need ?Segmentation
- 目標檢測資料集分析
- 2018目標檢測
- 目標檢測(Object Detection)總覽Object
- 目標檢測之RetinaNetNaN
- Object Detection(目標檢測神文)Object