几个法国十一大的学生过来交流,被实验室老师分配带两个做点小项目,要简单点。行吧,理论物理也带不动,拿出去年学习opencv时做的车牌分割和识别来做。不过他们俩真的是懒,只好代码写好给他们学习再自己做点修改,最后把学院老师糊弄过去。既然又写了一次,那就记录下来吧。
SVM用opencv写的,数据集是mnist
#include
#include
#include
#include
#include
#include
using namespace cv;
using namespace cv::ml;
using namespace std;
int imgVectorLen, nrows, ncols;
int trainImgsNum, trainLbsNum, testImgsNum,testLbsNum;
Mat trainFeatures, trainLabels, testFeatures, testLabels, predict_mat;
String trainImage = "train-images.idx3-ubyte";
String trainLabel = "train-labels.idx1-ubyte";
String testImage = "t10k-images.idx3-ubyte";
String testLabel = "t10k-labels.idx1-ubyte";
mnist数据集存储方式为大端方式,而Intel为小端处理器,因此我们要进行大小端的变换。
int reverseInt(int i)
{
unsigned char c1, c2, c3, c4;
c1 = i & 255;
c2 = (i >> 8) & 255;
c3 = (i >> 16) & 255;
c4 = (i >> 24) & 255;
return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}
读取训练集
void readTrainingImages(string trainImage, int mode = ios::binary)
{
//load train set
ifstream if_trainImages(trainImage, ios::binary);
//if load failed
if (if_trainImages.fail())
{
cout << "please check the path of file" << endl;
return;
}
int magic_num, trainImgsNum;
//read magic number,check if the file is broken
if_trainImages.read((char*)&magic_num, sizeof(magic_num));
magic_num = reverseInt(magic_num);
cout << "the magic number of train-images is: " << magic_num << endl;
//read total number of train-images
if_trainImages.read((char*)&trainImgsNum, sizeof(trainImgsNum));
trainImgsNum = reverseInt(trainImgsNum);
cout << "the total number of train-images is: " << trainImgsNum << endl;
//read the rows of train-images
if_trainImages.read((char*)&nrows, sizeof(nrows));
nrows = reverseInt(nrows);
cout << "the rows of training-image is: " << nrows << endl;
//read the cols of train-images
if_trainImages.read((char*)&ncols, sizeof(ncols));
ncols = reverseInt(ncols);
cout << "the cols of training-image is: " << ncols << endl;
//read the training images
imgVectorLen = nrows * ncols;
trainFeatures = Mat::zeros(trainImgsNum, imgVectorLen, CV_32FC1);
Mat temp = Mat::zeros(nrows, ncols, CV_8UC1);
for (int i = 0; i < trainImgsNum; i++)
{
if_trainImages.read((char*)temp.data, imgVectorLen);
Mat tempFloat;
//SVM input should be CV_32FC1
temp.convertTo(tempFloat, CV_32FC1);
memcpy(trainFeatures.data + i*imgVectorLen * sizeof(float), tempFloat.data, imgVectorLen * sizeof(float));
}
//normalization
trainFeatures = trainFeatures / 255;
cout << endl << "read the training-images successfully" << endl;
}
void readTrainingLabels(string trainLabel, int mode = ios::binary)
{
//load the label of training-set
ifstream if_trainLabels(trainLabel, ios::binary);
//if read failed
if (if_trainLabels.fail())
{
cout << "please check the path of file train-labels.idx1-ubyte" << endl;
return;
}
int magic_num_2;
//read the magic number
if_trainLabels.read((char*)&magic_num_2, sizeof(magic_num_2));
magic_num_2 = reverseInt(magic_num_2);
//read the number of Labels
if_trainLabels.read((char*)&trainLbsNum, sizeof(trainLbsNum));
trainLbsNum = reverseInt(trainLbsNum);
cout << "the total number of train-labels is: " << trainLbsNum << endl;
//SVM input label should be CV_32SC1
trainLabels = Mat::zeros(trainLbsNum, 1, CV_32SC1);
Mat readLabels = Mat::zeros(trainLbsNum, 1, CV_8UC1);
if_trainLabels.read((char*)readLabels.data, trainLbsNum * sizeof(char));
readLabels.convertTo(trainLabels, CV_32SC1);
cout << endl << "read the training labels successfully!" << endl;
}
检测读取训练集的结果
void test_train_read()
{
for (int i = 0; i < 5; i++)
{
int index;
cout << "input the index of the training image" << endl;
cin >> index;
Mat show_mat = Mat::zeros(nrows, ncols, CV_32FC1);
memcpy(show_mat.data, trainFeatures.data + index*imgVectorLen * sizeof(float), imgVectorLen * sizeof(float));
namedWindow("test");
resize(show_mat, show_mat, Size(200, 200));
imshow("test", show_mat);
waitKey(10);
cout << "the label ls: " << trainLabels.at(index) << endl;
}
}
训练SVM
void train_SVM()
{
//init
Ptr svm = SVM::create();
//multiclass
svm->setType(SVM::C_SVC);
//kernal we select RBF
svm->setKernel(SVM::RBF);
//set parameter
svm->setGamma(0.01);
svm->setC(10.0);
//set terminate condition
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 200, FLT_EPSILON));
//start training
svm->train(trainFeatures, ROW_SAMPLE, trainLabels);
cout << "over, write xml: " << endl;
svm->save("mnist.xml");
cout << "write xml successfully" << endl << "mnist.xml";
}
读取测试集
void readTestImages(string testImage, int mode = ios::binary)
{
ifstream if_testImages(testImage, mode);
if (if_testImages.fail())
{
cout << "Please check the path of file t10k-images-idx3-ubyte" << endl;
return;
}
int magic_num;
if_testImages.read((char*)&magic_num, sizeof(magic_num));
magic_num = reverseInt(magic_num);
cout << "the magic number of test-set is: " << magic_num << endl;
if_testImages.read((char*)&testImgsNum, sizeof(testImgsNum));
testImgsNum = reverseInt(testImgsNum);
cout << "the total number of test-set is: " << testImgsNum << endl;
if_testImages.read((char*)&nrows, sizeof(nrows));
nrows = reverseInt(nrows);
cout << "the rows of testImages is: " << nrows << endl;
if_testImages.read((char*)&ncols, sizeof(ncols));
ncols = reverseInt(ncols);
cout << "the cols of test-images is: " << ncols << endl;
imgVectorLen = ncols * nrows;
testFeatures = Mat::zeros(testImgsNum, imgVectorLen, CV_32FC1);
cout << "imgVectorLen is: " << imgVectorLen << endl;
cout << "testFeatures size1 is:" << testFeatures.size() << endl;
Mat temp = Mat::zeros(nrows, ncols, CV_8UC1);
for (int i = 0; i < testImgsNum; i++)
{
if_testImages.read((char*)temp.data, imgVectorLen);
Mat tempFloat;
temp.convertTo(tempFloat, CV_32FC1);
memcpy(testFeatures.data + i * imgVectorLen * sizeof(float), tempFloat.data, imgVectorLen * sizeof(float));
}
cout << "testFeatures.size" <
void readTestLabels(string testLabel, int mode = ios::binary)
{
//load the label of training-set
ifstream if_testLabels(testLabel, ios::binary);
//if read failed
if (if_testLabels.fail())
{
cout << "please check the path of file train-labels.idx1-ubyte" << endl;
return;
}
int magic_num_2;
//read the magic number
if_testLabels.read((char*)&magic_num_2, sizeof(magic_num_2));
magic_num_2 = reverseInt(magic_num_2);
//read the number of Labels
if_testLabels.read((char*)&testLbsNum, sizeof(testLbsNum));
testLbsNum = reverseInt(testLbsNum);
cout << "the total number of test-labels is: " << testLbsNum << endl;
//SVM input label should be CV_32SC1
testLabels = Mat::zeros(testLbsNum, 1, CV_32SC1);
Mat readLabels = Mat::zeros(testLbsNum, 1, CV_8UC1);
if_testLabels.read((char*)readLabels.data, testLbsNum * sizeof(char));
readLabels.convertTo(testLabels, CV_32SC1);
cout << endl << "read the test labels successfully!" << endl;
}
检测读取测试集的结果
void test_test_read()
{
for (int i = 0; i < 5; i++)
{
int index;
cout << "input the index of the test image" << endl;
cin >> index;
Mat show_mat = Mat::zeros(nrows, ncols, CV_32FC1);
memcpy(show_mat.data, testFeatures.data + index*imgVectorLen * sizeof(float), imgVectorLen * sizeof(float));
namedWindow("test");
resize(show_mat, show_mat, Size(200, 200));
imshow("test", show_mat);
waitKey(10);
cout << "the label ls: " << testLabels.at(index) << endl;
}
}
SVM预测
void predict_SVM()
{
Ptr svm = SVM::load("mnist.xml");
int sum = 0;
for (int i = 0; i < testLbsNum; i++)
{
predict_mat = Mat::zeros(1, imgVectorLen, CV_32FC1);
Mat predict = Mat::zeros(nrows, ncols, CV_32FC1);
memcpy(predict_mat.data, testFeatures.data + i*imgVectorLen * sizeof(float), imgVectorLen * sizeof(float));
memcpy(predict.data, testFeatures.data + i*imgVectorLen * sizeof(float), imgVectorLen * sizeof(float));
//cout << "size of predict: " << predict_mat.size() << endl;
float predict_label = svm->predict(predict_mat);
float truth_label = testLabels.at(i);
if ((int)predict_label == (int)truth_label)
{
sum++;
}
if (i % 100 == 0)
{
cout << i << "/" << testImgsNum << endl;
cout << "predict_label: " << predict_label << endl;
cout << "truth_label: " << truth_label << endl;
//cout << "the size of predict" << predict.size() << endl;
resize(predict, predict, Size(200, 200));
string mat = "mat" + to_string(i);
imshow("mat", predict);
waitKey(10);
}
}
cout << "the accuracy is: " << (double)sum / testLbsNum << endl;
}
主函数
int main()
{
//readTrainingImages(trainImage);
//readTrainingLabels(trainLabel);
//train_SVM();
readTestImages(testImage);
readTestLabels(testLabel);
predict_SVM();
//test_read();
//test_test_read();
waitKey(0);
return 0;
}
最后的运行结果