#include <iostream> /<iostream>
#include <fstream> /<fstream>
#include <opencv2> /<opencv2>
#include <opencv2> /<opencv2>
#include <opencv2> /<opencv2>
#include <opencv2> /<opencv2>
#include <opencv2> /<opencv2>
#define PosSamNum 100 //正樣本個數
#define NegSamNum 100 //負樣本個數
std::string train_image_folder = "./";
std::string test_image_folder = "./";
void train(){
std::cout<
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描述子向量/<float>
cv::Mat sample_features; //所有訓練樣本的特徵向量組成的矩陣,行數等於所有樣本的個數,列數等於HOG描述子維數
cv::Mat sample_labels; //訓練樣本的類別向量,行數等於所有樣本的個數,列數等於1;1表示有人,-1表示無人
//獲取訓練數據的正樣本
for(int num=0; num<possamnum>
{
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<
exit(0);
}
hog.compute(src,descriptors,cv::Size(8,8));
if(num==0){
std::cout<
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>
sample_features.at<float>(num,i) = descriptors[i];/<float>
}
sample_labels.at
std::cout<
}
//獲取訓練數據的負樣本
for(int num=0;num<negsamnum>
image_name = train_image_folder + image_name;
src = cv::imread(image_name,0);
if(src.empty()){
std::cout<
exit(0);
}
cv::resize(src,src,cv::Size(96,160));
hog.compute(src,descriptors,cv::Size(8,8));
for(int i=0;i<descriptor>
sample_features.at<float>(num+PosSamNum,i) = descriptors[i];/<float>
}
sample_labels.at
std::cout<
}
//訓練SVM分類器
std::cout<
cv::Ptr<: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<
svm->save("test_svm.xml");
std::cout<
return;
}
void test(std::string test_image_name){
std::cout<
//加載圖片
cv::Mat test_image = cv::imread(test_image_name,0);
if(test_image.empty()){
std::cout<
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;/<float>
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>
test_feature.at<float>(0,i) = descriptors[i];/<float>
}
//加載SVM
cv::Ptr<: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);/<float>
if(res==1){
std::cout<
}else if(res==-1){
std::cout<
}
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<
return 1;
}
test(argv[2]);
return 0;
}
}
"/<descriptors.size>/<descriptor>/<negsamnum>/<descriptor>/<possamnum>閱讀更多 好先生Vlog 的文章