您的位置:首页 > 运维架构

opencv学习笔记-----使用SVM做行人判断

2017-03-05 14:14 417 查看
opencv库中的ml模块是opencv组件中的机器学习模块,包含:

统计模型 (Statistical Models)


2. 一般贝叶斯分类器 (Normal Bayes Classifier)


3. K-近邻 (K-NearestNeighbors)


4. 支持向量机 (Support Vector Machines)


5. 决策树 (Decision Trees)


6. 提升(Boosting)


7. 梯度提高树(Gradient Boosted Trees)


8. 随机树 (Random Trees)


9. 超随机树 (Extremely randomized trees)


10. 期望最大化 (Expectation Maximization)


11. 神经网络 (Neural Networks)

12.MLData
这次,我要做的实验是用其中的支持向量机(SVM)做行人判断,给定图片,判断图片中有无行人。
下图为无行人:



下图为有行人:



本次实验使用100中正样本和100张负样本做行人识别。

大家都知道,使用机器学习做分类判断有两部,第一:使用带标签的数据做分类器的训练,即:train,第二:使用训练好的分类器做新图片的识别, 即:test。

完整的训练和测试源码:

#include <iostream>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/ml/ml.hpp>

#define PosSamNum 100    //正样本个数
#define NegSamNum 100   //负样本个数

std::string train_image_folder = "./";
std::string test_image_folder  = "./";

void train(){

std::cout<<"start traning..."<<std::endl;

std::ifstream train_pos_file(train_image_folder + "train/pos.lst");
std::ifstream train_neg_file(train_image_folder + "train/neg.lst");

std::string image_name; //图片路径

cv::Mat src;

//定义HOG检测器
int descriptor_dim = 0;
//检测窗口(64,128),块尺寸(16,16),块步长(8,8),cell尺寸(8,8),直方图bin个数9
cv::HOGDescriptor hog(cv::Size(64,128),cv::Size(16,16),cv::Size(8,8),cv::Size(8,8),9);//HOG检测器,用来计算HOG描述子的
std::vector<float> descriptors; //HOG描述子向量

cv::Mat sample_features; //所有训练样本的特征向量组成的矩阵,行数等于所有样本的个数,列数等于HOG描述子维数
cv::Mat sample_labels;  //训练样本的类别向量,行数等于所有样本的个数,列数等于1;1表示有人,-1表示无人

//获取训练数据的正样本
for(int num=0; num<PosSamNum && getline(train_pos_file,image_name);num++){
image_name = train_image_folder + image_name;
src = cv::imread(image_name,0);

cv::resize(src,src,cv::Size(96,160)); //统一训练格式

if(src.empty()){
std::cout<<"no image in pos image path:"<<image_name<<std::endl;
exit(0);
}

hog.compute(src,descriptors,cv::Size(8,8));

if(num==0){
std::cout<<"Init feature size..."<<std::endl;
descriptor_dim = descriptors.size();
sample_features = cv::Mat::zeros(PosSamNum+NegSamNum,descriptor_dim,CV_32FC1);
sample_labels   = cv::Mat::zeros(PosSamNum+NegSamNum,1,CV_32SC1); //注意这里必须要32SC1,不能用32FC1
}

for(int i=0;i<descriptor_dim;i++){
sample_features.at<float>(num,i) = descriptors[i];
}
sample_labels.at<int>(num,0) = 1; //正样本类别为1,有人

std::cout<<"finish Pos "<<num<<" "<<image_name<<std::endl;

}

//获取训练数据的负样本
for(int num=0;num<NegSamNum && getline(train_neg_file,image_name);num++){
image_name = train_image_folder + image_name;
src = cv::imread(image_name,0);
if(src.empty()){
std::cout<<"no image in neg image path..."<<std::endl;
exit(0);
}
cv::resize(src,src,cv::Size(96,160));

hog.compute(src,descriptors,cv::Size(8,8));

for(int i=0;i<descriptor_dim;i++){
sample_features.at<float>(num+PosSamNum,i) = descriptors[i];
}
sample_labels.at<int>(num+PosSamNum,0) = -1; //正样本类别为-1,没有人

std::cout<<"finish Neg "<<num<<" "<<image_name<<std::endl;
}

//训练SVM分类器
std::cout<<"start svm training..."<<std::endl;
cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
svm->setType(cv::ml::SVM::C_SVC);
svm->setKernel(cv::ml::SVM::LINEAR);
svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));
svm->train(sample_features,cv::ml::ROW_SAMPLE,sample_labels);

//保存SVM分类器
std::cout<<"start saving svm file..."<<std::endl;
svm->save("test_svm.xml");

std::cout<<"finish training..."<<std::endl;
return;
}

void test(std::string test_image_name){
std::cout<<"start testing..."<<std::endl;

//加载图片
cv::Mat test_image = cv::imread(test_image_name,0);
if(test_image.empty()){
std::cout<<"Input test image path is error!"<<std::endl;
return;
}

//获取特征并组织为单行的格式
cv::resize(test_image,test_image,cv::Size(96,160)); //训练样本的尺寸是(96,160),修改训练数据后,要同步修改
cv::HOGDescriptor hog(cv::Size(64,128),cv::Size(16,16),cv::Size(8,8),cv::Size(8,8),9);
std::vector<float> descriptors;
hog.compute(test_image,descriptors,cv::Size(8,8));
cv::Mat test_feature = cv::Mat::zeros(1,descriptors.size(),CV_32FC1);
for(int i=0;i<descriptors.size();i++){
test_feature.at<float>(0,i) = descriptors[i];
}

//加载SVM
cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
svm = cv::ml::SVM::load("./test_svm.xml");
//如果文件不存在则先训练
if(svm.empty()){
train();
}
//输出结果
cv::Mat result;
svm->predict(test_feature,result);
float res = result.at<float>(0,0);
if(res==1){
std::cout<<"Result: 1, 有人!"<<std::endl;
}else if(res==-1){
std::cout<<"Result: -1, 没有人!"<<std::endl;
}
return;

}

int main(int argc,char* argv[]){
if(strcmp(argv[1],"train")==0){
train();
return 0;
}
if(strcmp(argv[1],"test")==0){
if(argc<3){
std::cout<<"please input test image file."<<std::endl;
return 1;
}
test(argv[2]);
return 0;
}
}
命令行训练和测试数据:

编译:g++ -o test_svm  test_svm.cpp -lopencv_ml -lopencv_objdetect -lopencv_core -lopencv_imgproc -lopencv_imgcodecs -lopencv_highgui -std=c++11

生成了可执行文件test_svm

训练:./test_svm train

测试:./test_svm test '/home/junny/Desktop/opencv/course/seven/train/neg/00000030a.png'

结果:



大功告成!

资源下载地址:http://download.csdn.net/detail/leonis_v/9770849
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opencv svm 行人识别