过程:
1.载入正样本图像
2.载入负样本图像
3.探测特征
4.提取特征
5. 将正样本特征和负样本特征合成训练样本特征矩阵
6. 输入训练矩阵和样本标签到SVM,进行训练
7. 保存SVM训练结果
问题:
对于surf特征的探测和提取均奏效,但是对于orb特征SVM训练会使程序崩溃,提示为“一个不可处理的异常产生在内存xxxxxxx ”。
比较两个代码所产生的训练矩阵发现,surf特征的训练矩阵为double类型,而orb特征的训练矩阵为uchar。将说char类型转换为
double类型,程序运行成功。
代码如下
/*
* @author smells2
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <time.h>
#include <assert.h>
#include <cmath>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/ml/ml.hpp>
using namespace std;
using namespace cv;
#define SVMTRAN 0
static void Help()
{
cout << "======================================================"<<endl;
cout << " This program is used to train matches with SVM" << endl;
cout << "======================================================"<<endl;
}
void getDescriptors(vector<string>& file_paths, vector<Mat>& descriptors_arry)
{
//using to store training images.
clock_t time_start = clock();
vector<Mat> img_objs;
for (size_t i = 0;i < file_paths.size();i++)
{
Mat temp_img = imread(file_paths[i],CV_LOAD_IMAGE_GRAYSCALE);
if (!temp_img.data)
{
cerr << "ERROR: open " << file_paths[i] <<" image is failed!" <<endl;
exit(0);
}
img_objs.push_back(temp_img);
cout << "file: " << file_paths[i] << " is loaded." << endl;
}
//get descriptors for each image
//!{
const int min_hessian = 400;
OrbFeatureDetector surf_hessian_detector( min_hessian );
OrbDescriptorExtractor surf_extractor;
//OrbDescriptorExtractor surf_extractor;
for (size_t i = 0;i < img_objs.size();i++)
{
vector<KeyPoint> keyPoints;
surf_hessian_detector.detect(img_objs[i],keyPoints);
Mat descriptors;
surf_extractor.compute(img_objs[i],keyPoints,descriptors);
descriptors_arry.push_back(descriptors);
cout << "file: " << file_paths[i] << " descriptors is extrated." << endl;
}
//!}
clock_t time_end = clock();
cout << "cost time: " << (float)(time_end - time_start)/1000 << " seconds." << endl;
}
int main(int arg, char** argv)
{
Help();
clock_t total_time_start = clock();
//Open train data configuration
#if _DEBUG
ifstream fin("../images/train_positive.txt");
#else
if (arg < 4)
{
cerr << "Usage: command <positive_samples_path> <negative_samples_path> <output_SVM_XML_path>" <<endl;
exit(0);
}
ifstream fin(argv[1]);
#endif
if (!fin)
{
#if _DEBUG
cerr << "file open failed!" << endl;
#else
cerr << argv[1] <<" open failed!" << endl;
#endif
exit(0);
}
string buf;
// file_paths is used to store files
vector<string> file_paths;
while(getline(fin,buf))
{
file_paths.push_back(buf);
buf.clear();
}
//close file_paths file fstream
fin.close();
vector<Mat> descriptors_positive;
getDescriptors(file_paths,descriptors_positive);
if (fin.is_open())
{
fin.close();
}
#if _DEBUG
fin.open("../images/train_negative.txt");
#else
fin.open(argv[2]);
#endif
if (!fin)
{
#if _DEBUG
cerr << "file open is failed, negative" << endl;
#else
cerr << argv[2] << "open failed." << endl;
#endif
exit(0);
}
vector<string> negative_file_paths;
buf.clear();
while(getline(fin,buf))
{
negative_file_paths.push_back(buf);
buf.clear();
}
vector<Mat> descriptors_negative;
getDescriptors(negative_file_paths,descriptors_negative);
//Merge training data
assert(descriptors_positive.size() > 0);
int train_mat_row = 0;
int train_mat_row_positive = 0;
int train_mat_row_negative = 0;
int train_mat_col = descriptors_positive[0].cols;
for (size_t i = 0; i < descriptors_positive.size();i++)
{
#if _DEBUG
cout << i << " rows: " << descriptors_positive[i].rows<< " col: "
<< descriptors_positive[i].cols << endl;
#endif
train_mat_row += descriptors_positive[i].rows;
train_mat_row_positive += descriptors_positive[i].rows;
}
for (size_t i = 0; i < descriptors_negative.size();i++)
{
#if _DEBUG
cout << i << " rows: " << descriptors_negative[i].rows<< " col: "
<< descriptors_negative[i].cols << endl;
#endif
train_mat_row += descriptors_negative[i].rows;
train_mat_row_negative += descriptors_negative[i].rows;
}
Mat train_samples;
float* _labels = new float[train_mat_row_positive+train_mat_row_negative];
for (int i = 0;i < train_mat_row_positive;i++)
{
_labels[i] = 1.0;
}
for (int i = train_mat_row_positive;i < train_mat_row_positive+train_mat_row_negative;i++)
{
_labels[i] = -1.0;
}
for (size_t i = 0; i < descriptors_positive.size(); i++)
{
Mat _t;
_t.create(descriptors_positive[i].rows,descriptors_positive[i].cols,CV_32FC1);
descriptors_positive[i].convertTo(_t,CV_32FC1);
train_samples.push_back(_t);
//train_samples.push_back(descriptors_positive[i]);
}
#if _DEBUG
//cout << train_samples << endl;
#endif
for (size_t i = 0; i< descriptors_negative.size(); i++)
{
Mat _t;
_t.create(descriptors_negative[i].rows,descriptors_negative[i].cols,CV_32FC1);
descriptors_negative[i].convertTo(_t,CV_32FC1);
train_samples.push_back(_t);
//train_samples.push_back(descriptors_negative[i]);
}
Mat train_lables(train_mat_row_positive+train_mat_row_negative,1,CV_32FC1,_labels);
#if _DEBUG
// cout << train_lables << endl;
#endif
//Train SVM
SVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
TermCriteria terminated(CV_TERMCRIT_ITER,1000,1e-6);
CvSVM SVM;
SVM.train(train_samples,train_lables,Mat(),Mat(),params);
#if _DEBUG
SVM.save("../images/train_SVM.xml");
#else
SVM.save(argv[3]);
#endif
#if _DEBUG //predict
vector<Mat> descriptor_predict;
vector<string> predict_path;
predict_path.push_back(string("../images/train/4.JPG"));
getDescriptors(predict_path,descriptor_predict);
Mat res;
Mat _t;
_t.create(descriptor_predict[0].rows,descriptor_predict[0].cols,CV_32FC1);
descriptor_predict[0].convertTo(_t,CV_32FC1);
SVM.predict(_t,res);
cout << res << endl;
#endif
//release memory
if (_labels)
{
delete _labels;
_labels = NULL;
}
clock_t total_time_end = clock();
cout << "total cost time: "<< (double)(total_time_end-total_time_start)/1000 << " seconds."<<endl;
}