其实训练代码还是比较简单的,设置完HOG和SVM的参数就可以开始训练了。需要训练时就不用注释#define TRAIN,若想运行之前已经训练好的模型则需将其注释掉,并修改模型名。
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <fstream>
#include <iostream>
#include <opencv2/ml/ml.hpp>
#define TRAIN
using namespace std;
using namespace cv::ml;
using namespace cv;
Size imageSize = Size(96, 128);
void coumputeHog(const Mat& src, vector<float> &descriptors){
//winsize blocksize blockStride cellsize bins
HOGDescriptor myHog = HOGDescriptor(imageSize, Size(96, 64), Size(96, 32), Size(48, 32), 4);
myHog.compute(src.clone(),descriptors,Size(1,1),Size(0,0));
}
int main(int argc, char** argv){
ifstream inLabels("myImageLabels1.txt"), inImages("myImageList1.txt"),inTestimage("myImagetest1.txt");
string imageName;
signed imageLabel;
vector<Mat> vecImages;
vector<int> vecLabels;
vector<float> vecDescriptors;
#ifdef TRAIN
Ptr<SVM> mySVM = SVM::create();
mySVM->setType(SVM::C_SVC);
mySVM->setKernel(SVM::LINEAR);
mySVM->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS,1500, 0.01));
mySVM->setC(450);
while ((inImages>>imageName)&&(inLabels>>imageLabel))
{
Mat src = imread(imageName, 0);
resize(src, src, imageSize);
vecImages.push_back(src);
vecLabels.push_back(imageLabel);
}
inLabels.close();
inImages.close();
Mat dataDescriptors;
Mat dataResponse = (Mat)vecLabels;
for (size_t i = 0; i < vecImages.size(); i++)
{
Mat src = vecImages[i];
Mat tempRow;
coumputeHog(src, vecDescriptors);
cout<<vecDescriptors.size()<<endl;
if (i == 0)
{
dataDescriptors = Mat::zeros(vecImages.size(), vecDescriptors.size(), CV_32FC1);
}
tempRow = ((Mat)vecDescriptors).t();
tempRow.row(0).copyTo(dataDescriptors.row(i));
}
Ptr<TrainData> tData = TrainData::create(dataDescriptors, ROW_SAMPLE, dataResponse);
mySVM->train(tData);
string svmName = to_string(1) + "_hogsvm.xml";
mySVM->save(svmName.c_str());
#endif
#ifndef TRAIN
Ptr<ml::SVM> mySVM = Algorithm::load<ml::SVM>("0hogsvm.xml");
#endif
string testPath;
while (inTestimage >> testPath){
Mat test = imread(testPath, 0);
resize(test, test, imageSize);
vector<float> imageDescriptor;
coumputeHog(test, imageDescriptor);
Mat testDescriptor = Mat::zeros(1, imageDescriptor.size(), CV_32FC1);
for (size_t i = 0; i < imageDescriptor.size(); i++){
testDescriptor.at<float>(0, i) = imageDescriptor[i];
}
float label = mySVM->predict(testDescriptor);
cout << label << endl;
imshow("test image", test);
//waitKey(0);
}
inTestimage.close();
delete mySVM;
return 0;
}
myImageLabels1.txt 训练图片对应的标签
myImageList1.txt 训练图片对应的路径
myImagetest1.txt 测试图片对应的路径
如果路径和标签过多的话,txt里面的内容那就得靠代码帮你自动化完成了....