在Windows下執行Felzenszwalb的Deformable Part Models(voc-release4.01)目標檢測matlab原始碼
可變形部件模型Deformable Part Models是目前最好的目標檢測演算法,由Felzenszwalb提出,本文介紹如何在windows下執行Felzenszwalb給出的matlab原始碼。
有關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
Pedro Felzenszwalb的個人主頁:http://cs.brown.edu/~pff/
PASCAL VOC 目標檢測挑戰:http://pascallin.ecs.soton.ac.uk/challenges/VOC/
Felzenszwalb給出了matlab版本的實現,且只能執行在linux和Mac作業系統上,有網友給出了其中的第四版voc-release4.01修改後在windows上執行的方法,這裡進行一下總結。
本文參考以下三篇部落格:
Win7+VS2010+Matlab2011b下執行Discriminatively Trained Deformable PartModels(4.01版)程式碼-執行demo()-詳細步驟
如何在window下執行Discriminatively Trained Deformable PartModels程式碼
在windows下執行Felzenszwalb的Discriminatively Trained Deformable Part Models程式碼
我的環境:Win7 + Matlab R2010a(其中配置VC++6.0中的c++編譯器)
在網站http://www.cs.berkeley.edu/~rbg/latent/index.html上下載voc-release4.01原始碼並解壓。
步驟1 在Matlab中配置c++編譯器
在matlab命令列中輸入:
mex –setup
回車,出現提示:
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n?
輸入n,回車,此時會列出matlab支援的編譯器:
Select a compiler:
[1]Intel C++ 11.1 (with Microsoft Visual C++ 2008 SP1 linker)
[2]Intel C++ 9.1 (with Microsoft Visual C++ 2005 SP1 linker)
[3]Intel Visual Fortran 11.1 (with Microsoft Visual C++ 2008 SP1 linker)
[4]Intel Visual Fortran 11.1 (with Microsoft Visual C++ 2008 Shell linker)
[5]Intel Visual Fortran 10.1 (with Microsoft Visual C++ 2005 SP1 linker)
[6]Lcc-win32 C 2.4.1
[7]Microsoft Visual C++ 6.0
[8]Microsoft Visual C++ 2005 SP1
[9]Microsoft Visual C++ 2008 Express
[10]Microsoft Visual C++ 2008 SP1
[11]Open WATCOM C++
[0]None
根據自己機器上安裝的VC版本,選擇對應的編譯器,輸入序號,回車,提示:
Your machine has a Microsoft Visual C++compiler located at
C:\Program Files\Microsoft Visual Studio.Do you want to use this compiler [y]/n?
如果自動檢測給出的是正確的VC目錄,輸入y,否則可以輸入n後手動輸入VC目錄。
步驟2 嘗試呼叫compile()編譯原始碼
將matlab工作目錄設定為資料夾voc-release4.01所在的目錄,在matlab命令列中輸入compile,即呼叫compile()函式嘗試編譯原始碼,我們看看會出現什麼錯誤,然後挨個解決,錯誤提示如下:
Command line warning D4024 : unrecognizedsource file type 'resize.cc', object file assumed
Command line warning D4027 : source file'resize.cc' ignored
Command line warning D4021 : no actionperformed
說明編譯器無法識別.cc檔案,開啟compile.m檔案,如下:mex -O resize.cpp
mex -O dt.cpp
mex -O features.cpp
mex -O getdetections.cpp
% use one of the following depending on your setup
% 0 is fastest, 3 is slowest
% 0) multithreaded convolution using SSE
% mex -O fconvsse.cc -o fconv
% 1) multithreaded convolution using blas
% WARNING: the blas version does not work with matlab >= 2010b
% and Intel CPUs
% mex -O fconvblasMT.cc -lmwblas -o fconv
% 2) mulththreaded convolution without blas
% mex -O fconvMT.cc -o fconv
% 3) convolution using blas
% mex -O fconvblas.cc -lmwblas -o fconv
% 4) basic convolution, very compatible
% mex -O fconv.cc -o fconv
%在windows下使用時加上下面這句,並註釋掉0)
mex -O fconv.cpp
發現首先會編譯resize.cc,dt.cc,features.cc,getdetections.cc 這四個檔案,既然不識別.cc檔案,就將這四個.cc檔案的副檔名都改為.cpp,同時也修改compile.m檔案,將前四句改為: mex -O resize.cpp
mex -O dt.cpp
mex -O features.cpp
mex -O getdetections.cpp
步驟3 修改resize.cpp檔案
然後呼叫compile(),錯誤提示:
resize.cpp(36) : error C2057: expected constant expression
resize.cpp(36) : error C2466: cannot allocate an array of constant size 0
resize.cpp(36) : error C2133: 'ofs' : unknown size
resize.cpp(70) : error C2065: 'bzero' : undeclared identifier
resize.cpp(95) : error C2065: 'round' : undeclared identifier
為解決此問題,修改resize.cpp檔案,在前面加上bzero和round的定義:#define bzero(a,b) memset(a,0,b)
int round(float a){float tmp = a-(int)a; if(tmp>=0.5) return(int)a+1;else return (int)a;}
並並修改ofs陣列的定義,將
alphainfo ofs[len];
這句改成:alphainfo *ofs = new alphainfo[len];
當然在同一作用域後面加上:
delete [] ofs;
修改完後的resize.cpp檔案如下:
#include <math.h>
#include <assert.h>
#include <string.h>
#include "mex.h"
/*
* Fast image subsampling.
* This is used to construct the feature pyramid.
*/
//在windows下使用時加上下面這句
#define bzero(a,b) memset(a,0,b)
int round(float a){float tmp = a-(int)a; if(tmp>=0.5) return (int)a+1;else return (int)a;}
// struct used for caching interpolation values
struct alphainfo {
int si, di;
double alpha;
};
// copy src into dst using pre-computed interpolation values
void alphacopy(double *src, double *dst, struct alphainfo *ofs, int n) {
struct alphainfo *end = ofs + n;
while (ofs != end) {
dst[ofs->di] += ofs->alpha * src[ofs->si];
ofs++;
}
}
// resize along each column
// result is transposed, so we can apply it twice for a complete resize
void resize1dtran(double *src, int sheight, double *dst, int dheight,
int width, int chan) {
double scale = (double)dheight/(double)sheight;
double invscale = (double)sheight/(double)dheight;
// we cache the interpolation values since they can be
// shared among different columns
int len = (int)ceil(dheight*invscale) + 2*dheight;
//alphainfo ofs[len];
alphainfo *ofs = new alphainfo[len];//在windows下使用時加上這句,註釋掉上面一句
int k = 0;
for (int dy = 0; dy < dheight; dy++) {
double fsy1 = dy * invscale;
double fsy2 = fsy1 + invscale;
int sy1 = (int)ceil(fsy1);
int sy2 = (int)floor(fsy2);
if (sy1 - fsy1 > 1e-3) {
assert(k < len);
assert(sy-1 >= 0);
ofs[k].di = dy*width;
ofs[k].si = sy1-1;
ofs[k++].alpha = (sy1 - fsy1) * scale;
}
for (int sy = sy1; sy < sy2; sy++) {
assert(k < len);
assert(sy < sheight);
ofs[k].di = dy*width;
ofs[k].si = sy;
ofs[k++].alpha = scale;
}
if (fsy2 - sy2 > 1e-3) {
assert(k < len);
assert(sy2 < sheight);
ofs[k].di = dy*width;
ofs[k].si = sy2;
ofs[k++].alpha = (fsy2 - sy2) * scale;
}
}
// resize each column of each color channel
bzero(dst, chan*width*dheight*sizeof(double));
for (int c = 0; c < chan; c++) {
for (int x = 0; x < width; x++) {
double *s = src + c*width*sheight + x*sheight;
double *d = dst + c*width*dheight + x;
alphacopy(s, d, ofs, k);
}
}
delete[] ofs;//在windows下使用時加上這句
}
// main function
// takes a double color image and a scaling factor
// returns resized image
mxArray *resize(const mxArray *mxsrc, const mxArray *mxscale) {
double *src = (double *)mxGetPr(mxsrc);
const int *sdims = mxGetDimensions(mxsrc);
if (mxGetNumberOfDimensions(mxsrc) != 3 ||
mxGetClassID(mxsrc) != mxDOUBLE_CLASS)
mexErrMsgTxt("Invalid input");
double scale = mxGetScalar(mxscale);
if (scale > 1)
mexErrMsgTxt("Invalid scaling factor");
int ddims[3];
ddims[0] = (int)round(sdims[0]*scale);
ddims[1] = (int)round(sdims[1]*scale);
ddims[2] = sdims[2];
mxArray *mxdst = mxCreateNumericArray(3, ddims, mxDOUBLE_CLASS, mxREAL);
double *dst = (double *)mxGetPr(mxdst);
double *tmp = (double *)mxCalloc(ddims[0]*sdims[1]*sdims[2], sizeof(double));
resize1dtran(src, sdims[0], tmp, ddims[0], sdims[1], sdims[2]);
resize1dtran(tmp, sdims[1], dst, ddims[1], ddims[0], sdims[2]);
mxFree(tmp);
return mxdst;
}
// matlab entry point
// dst = resize(src, scale)
// image should be color with double values
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
if (nrhs != 2)
mexErrMsgTxt("Wrong number of inputs");
if (nlhs != 1)
mexErrMsgTxt("Wrong number of outputs");
plhs[0] = resize(prhs[0], prhs[1]);
}
步驟4 修改dt.cpp檔案
修改完resize.cpp檔案後,繼續compile,錯誤提示如下:
dt.cpp(61): error C2065: 'int32_t' : undeclared identifier
等等。
為解決此問題,在dt.cpp檔案前面加上:
#defineint32_t int
然後繼續compile,錯誤提示如下:
dt.cpp(77): error C2374: 'x' : redefinition; multiple initialization
dt.cpp(70) : seedeclaration of 'x'
說明有變數的二次定義,其實這是VC++6.0編譯器的一個bug,在VC++6.0中,如果有如下的語句:
for(int i=0; i < 10; i++)
{...}
for(int i=0; i <10; i++)
{...}
則編譯器會提示第二個變數i是重複定義,也就是說,編譯器不認為在for語句內定義的變數的作用域僅限於for語句內,這與C++語法不符,現在的VS2010中已經沒有這個問題了。所以在resize.cpp檔案的對應位置註釋掉二次定義就可以了,或者如果你選擇的編譯器不是VC++6.0的話,就沒有這個問題。
步驟5 修改features.cpp檔案
修改好dt.cpp檔案後,再次compile,錯誤提示如下:
features.cpp(48) : error C2065: 'round' : undeclared identifier
features.cpp(158) : error C2374: 'x' : redefinition; multiple initialization
features.cpp(65) : see declaration of 'x'
features.cpp(195) : error C2374: 'o' : redefinition; multiple initialization
features.cpp(179) : see declaration of 'o'
可以看出有三個問題,round()函式未定義,變數x和o重複定義,
所以在features.cpp檔案中加入round()函式的定義:
intround(float a){float tmp = a-(int)a; if(tmp>=0.5) return (int)a+1;elsereturn (int)a;}
並根據出錯位置註釋掉變數x和o的二次定義
步驟6 再次修改compile.m檔案
修改完features.cpp檔案後,再次compile,錯誤提示如下:
Usage:
MEX [option1 ... optionN] sourcefile1 [... sourcefileN]
[objectfile1 ... objectfileN] [libraryfile1 ... libraryfileN]
Use the -help option for more information, or consult the MATLAB API Guide.
Error in ==> compile at 10
mex -O fconvsse.cc -o fconv
開啟compile.m檔案,檢視第10行之前的註釋:% use one of thefollowing depending on your setup
% 0 is fastest, 3 isslowest(應該是0 is fastest, 4 is slowest)
可以看到0-4只是效率不同,作用一樣,既然第10行的0號出問題了,就換一個,根據網友pozen的說明:其他幾個fconv用了其他平臺的multiThread在windows上跑不起,所以在最後加上:
mex -O fconv.cpp
並將第10行的
mex -O fconvsse.cc -o fconv
註釋掉。
注意這裡要先將fconv.cc檔案的副檔名改為cpp,否則還會出現一開始的不識別.cc檔案的問題。
修改完後的compile.m檔案如下:
mex -O resize.cpp
mex -O dt.cpp
mex -O features.cpp
mex -O getdetections.cpp
% use one of the following depending on your setup
% 0 is fastest, 3 is slowest
% 0) multithreaded convolution using SSE
% mex -O fconvsse.cc -o fconv
% 1) multithreaded convolution using blas
% WARNING: the blas version does not work with matlab >= 2010b
% and Intel CPUs
% mex -O fconvblasMT.cc -lmwblas -o fconv
% 2) mulththreaded convolution without blas
% mex -O fconvMT.cc -o fconv
% 3) convolution using blas
% mex -O fconvblas.cc -lmwblas -o fconv
% 4) basic convolution, very compatible
% mex -O fconv.cc -o fconv
%在windows下使用時加上下面這句,並註釋掉0)
mex -O fconv.cpp
步驟7 修改fconv.cpp檔案
修改完compile.m檔案後,再次compile,錯誤提示如下:
fconv.cpp(75): error C4716: 'process' : must return a value
所以修改fconv.cpp檔案,將
void*process(void *thread_arg)
改為:
void process(void*thread_arg)
即去掉指標符號。
然後再次compile,沒錯誤提示了,編譯成功了。
步驟8 執行demo(),進行目標檢測試驗
編譯完成後,在matlab命令列中輸入demo,進行目標檢測試驗,根據提示,依次會出現小轎車、人、自行車的部件模型和檢測結果,如果想檢測其他圖片,修改demo檔案即可。
結果
(1) 小轎車
(2) 人
(3) 自行車
參考
在Windows下執行Felzenszwalb的Deformable Part Models(voc-release4.01)目標檢測matlab原始碼
相關文章
- 在Windows下執行Felzenszwalb的star-cascade DPM(Deformable Part Models)目標檢測Matlab原始碼WindowsORMMatlab原始碼
- 在windows下執行Felzenszwalb的Deformable Part Model(DPM)原始碼voc-release3.1來訓練自己的模型WindowsORM原始碼模型
- 使用判別訓練的部件模型進行目標檢測 Object Detection with Discriminatively Trained Part Based Models模型ObjectAI
- 在安卓上執行yolov8目標檢測模型(ncnn)安卓YOLO模型CNN
- 目標檢測:二維碼檢測方案
- 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
- 不帶Anchors和NMS的目標檢測
- 0-目標檢測模型的基礎模型
- 52 個深度學習目標檢測模型彙總,論文、原始碼一應俱全!深度學習模型原始碼