opencv 3.0 DPM cascade contrib模塊
轉載請注明出處,樓燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/
在opencv3.0 中 加入DPM檢測的C++代碼,目前開源的DPMC++代碼不多,在2.4的opencv 版本中,DPM模塊中在檢測時用的是latentSVM,這個是標准的DPM matlab源碼中使用的分類器,不過在在voc_release 5.01版本中已經也加入了cascade。這一版本的C++ DPM也加入了級聯分類器,並做了TBB和openMP加速,先曬一張TBB加速后的圖
x64, release 開啟TBB加速,TBB加速的效果比較明顯,在0.5S左右
目前工程化的代碼比較少,在這之前我還試了yuxiaoguo 的DPM代碼,這里我放一個鏈接yuxiaoguo,作者的碩士畢設完成的是將DPM源碼實現了C++的版本,並做了不少優化。
首先感謝這么有奉獻精神的人士,讓大家在學習應用DPM的時候有了更多的資源,他已經開源了,相關的代碼可以在其博客上下到,首先的性能還不錯。
今天我主要說一下怎么跑opencv 3.0 中的DPM代碼,需要說明的是在3.0模塊中,DPm的相關部分已經被剝離了,在opencv_contrib這個模塊中,這里給出模塊的github鏈接,必須到上面去下,原始的3.0SDK中已經沒有了
下面是鏈接
https://github.com/Itseez/opencv_contrib
你可以直接把代碼建工程,鏈接到相應的另外的opencv庫,也可以直接把模塊編譯進去,生成庫文件
生成庫文件的具體步驟如下:
http://segmentfault.com/a/1190000003496009
但是我跟着步驟,用cmake做了configure,去除了部分沒有的選項,添加了額外的contrib module,configure generate沒有任何報錯,在用visual studio 2013 打開工程,在cmake targets 中直接Build install,生成的時候報了不少錯,因為着急看效果,因此也懶得折騰了,如果誰有碰到opencv編譯報錯,可以把相關的處理過程貼一下。
DPM +TBB and openMP
這一版本的opencv DPM檢測代碼加入了TBB並行加速和openMP並行加速,有個開關可以控制
開啟TBB加速
需要定義HAVE_TBB這個宏,不想在文件里加的話,直接全局生效,右鍵點擊工程-->屬性-->c/c++-->預處理器-->預處理器定義,點擊下拉框中的編輯里天機即可
接着還需要下載tbb這個庫,TBB是英特爾推出的並行庫
這里是官網鏈接https://www.threadingbuildingblocks.org
具體的配置我就不再詳述了,跟opencv 配置一樣,添加path變量,在工程屬性頁中添加include頭文件路徑和相應的庫目錄和鏈接的庫名字
開啟openMP加速
直接在工程的屬性頁中C++頁卡,語言下面選擇openMP支持即可
因此我這里選擇了直接建立工程,直接把項目clone 到本地,打開DPM的文件夾,
建立工程列表如下:
主函數:
#include "dpm.hpp"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace cv;
using namespace cv::dpm;
using namespace std;
int save_results(const string id, const vector<DPMDetector::ObjectDetection> ds, ofstream &out);
static void help()
{
cout << "\nThis example shows object detection on image sequences using \"Deformable Part-based Model (DPM) cascade detection API\n"
"Call:\n"
"./example_dpm_cascade_detect_sequence <model_path> <image_dir>\n"
"The image names has to be provided in \"files.txt\" under <image_dir>.\n"
<< endl;
}
static bool readImageLists( const string &file, vector<string> &imgFileList)
{
ifstream in(file.c_str(), ios::binary);
if (in.is_open())
{
while (in)
{
string line;
getline(in, line);
imgFileList.push_back(line);
}
return true;
}
else
{
cerr << "Invalid image index file: " << file << endl;
return false;
}
}
void drawBoxes(Mat &frame,
vector<DPMDetector::ObjectDetection> ds,
Scalar color,
string text);
int main( int argc, char** argv )
{
const char* keys =
{
"{@model_path | | Path of the DPM cascade model}"
"{@image_dir | | Directory of the images }"
};
CommandLineParser parser(argc, argv, keys);
//string model_path(parser.get<string>(0));
//string image_dir(parser.get<string>(1));
//string image_list = image_dir + "/files.txt";
string model_path ="D:\\WorkSpace\\VS_Projects\\opencv_dpm\\opencv_dpm\\inriaperson.xml";
string image_dir = "D:\\DataSet\\INRIAPerson";
string image_list = "D:\\DataSet\\INRIAPerson\\Test\\pos1.lst";
if( model_path.empty() || image_dir.empty() )
{
help();
return -1;
}
vector<string> imgFileList;
if ( !readImageLists(image_list, imgFileList) )
return -1;
#ifdef HAVE_TBB
cout << "Running with TBB" << endl;
#else
#ifdef _OPENMP
cout << "Running with OpenMP" << endl;
#else
cout << "Running without OpenMP and without TBB" << endl;
#endif
#endif
cv::Ptr<DPMDetector> detector = \
DPMDetector::create(vector<string>(1, model_path));
namedWindow("DPM Cascade Detection", 1);
// the color of the rectangle
Scalar color(0, 255, 255); // yellow
Mat frame;
for (size_t i = 0; i < imgFileList.size(); i++)
{
double t = (double) getTickCount();
vector<DPMDetector::ObjectDetection> ds;
string imageFile = image_dir + "\\" + imgFileList[i];
Mat image = imread(imageFile);
frame = image.clone();
if (image.empty()) {
cerr << "\nInvalid image:\n" << imgFileList[i] << endl;
return -1;
}
// detection
detector->detect(image, ds);
// compute frame per second (fps)
t = ((double) getTickCount() - t)/getTickFrequency();//elapsed time
cout << t << endl;
// draw boxes
string text = format("%0.1f fps", 1.0/t);
drawBoxes(frame, ds, color, text);
// show detections
imshow("DPM Cascade Detection", frame);
waitKey(0);
//if ( waitKey(30) >= 0)
// break;
}
return 0;
}
void drawBoxes(Mat &frame, \
vector<DPMDetector::ObjectDetection> ds, Scalar color, string text)
{
for (unsigned int i = 0; i < ds.size(); i++)
{
rectangle(frame, ds[i].rect, color, 2);
}
// draw text on image
Scalar textColor(0,0,250);
putText(frame, text, Point(10,50), FONT_HERSHEY_PLAIN, 2, textColor, 2);
}
在x64 release 模式下,圖像的分辨率480*360,測試的是Inria行人數據集
不開加速的檢測時間如下:大約在0.6~0.7秒之間
x64, release 開啟TBB加速,TBB加速的效果比較明顯,在0.5S左右
x64, release 開啟openMP加速,openMP加速不如TBB加速明顯,在0.5S~0.6S之間
代碼寫的非常規整,有較高的參考價值