最近项目中需要用到行人检测,对比了几种常用的算法后,果断选择出自大神Piotr Dollar的ICF(Integral Channel Features)。
下面开始了苦逼之旅。。。。
由于从网上down的代码都是MATLAB版的,如果翻译成C++的话,劳民伤财。以前就听说opencv_contrib里集成了该算法,但不知道效果如何,还是本着对大神的敬仰,重新编译了集成扩展功能的opencv3.0。
万事俱备,开始干活!(看完xobjdetect.hpp后,就觉得这里面的坑不是一般的多,很多关键的参数都木有注释!!!)
准备训练样本是件枯燥的事,但很重要。ICF的训练对样本没有特别的要求:正样本需要归一化(推荐64*128),彩图;负样本不需要归一化。图片准备好之后,生成文件列表pos_list,txt和neg_list.txt。
直接贴代码吧
#include "opencv2\opencv.hpp"
#include "opencv2\xobjdetect.hpp"
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
using namespace xobjdetect;
bool resize_img(string posfile, string negfile)
{
fstream fin_p(posfile.c_str());
string p_sample;
if (!fin_p)
{
cout << "Can not open posfile!" << endl;
return false;
}
while (getline(fin_p,p_sample))
{
Mat src = imread(p_sample, 1);
if (src.empty())
break;
Mat dst;
resize(src, dst, Size(96, 160));
imwrite(p_sample, dst);
}
fin_p.close();
return true;
}
bool train_model(String posfile, String negfile,String model_name)
{
std::vector<String> vposfile;
std::vector<String> vnegfile;
fstream fin_p(posfile.c_str());
string p_sample;
if (!fin_p)
{
cout << "Can not open posfile!" << endl;
return false;
}
while (getline(fin_p, p_sample))
{
vposfile.push_back(p_sample);
}
fin_p.close();
fstream fin_n(negfile.c_str());
string n_sample;
if (!fin_n)
{
cout << "Can not open negfile!" << endl;
return false;
}
while (getline(fin_n, n_sample))
{
vnegfile.push_back(n_sample);
}
fin_n.close();
ICFDetector HH_icfDetector;
ICFDetectorParams icf_params;
icf_params.alpha = 0.15f;
icf_params.bg_per_image = 5;
icf_params.feature_count = 15000;
icf_params.weak_count = 200;
icf_params.features_type = "icf";
icf_params.is_grayscale = false;
icf_params.model_n_cols = 56; //model尺寸?训练过程中图片归一化的尺寸
icf_params.model_n_rows = 70;
icf_params.use_fast_log = false;
HH_icfDetector.train(vposfile, vnegfile, icf_params);
//FileStorage fs;
//xobjdetect::write(fs, model_name, HH_icfDetector);
FileStorage fs(model_name, FileStorage::WRITE);
HH_icfDetector.write(fs);
fs.release();
return true;
}
bool test_model(String modelfile)
{
FileStorage fs(modelfile, FileStorage::READ);
if (fs.isOpened())
{
cout << "OPENED!" << endl;
}
FileNode model = fs["model"];
ICFDetector HH_icfDetector;
HH_icfDetector.read(model);
fs.release();
Mat image = imread("test.png", 1);
vector<Rect> vR;
vector<float> ftrs;
HH_icfDetector.detect(image, vR, 1.1, Size(30, 50), Size(300, 500), 1, 1, ftrs);
//HH_icfDetector.detect(image, vR, 1, 4, 1.2, 0, 5, ftrs);
for (int i = 0; i < vR.size();i++)
{
rectangle(image, vR[i], Scalar(0, 255, 0), 1, 8);
}
namedWindow("result", CV_WINDOW_NORMAL);
imshow("result", image);
waitKey(0);
return true;
}
void main()
{
String posfile = "pos_list.txt";
String negfile = "neg_list.txt";
String icf_model_name = "hh_icf_20171228.xml";
//train model
//bool trainflag = train_model(posfile, negfile, icf_model_name);
//test model
bool testflag = test_model(icf_model_name);
}
测试图片
测试结果
效果是非常的渣,并且检测速度不尽人意。折腾了两天,有些失望。。。。
后面继续关注这个算法,万一效果很赞呢