Opencv - SVM

    几个法国十一大的学生过来交流,被实验室老师分配带两个做点小项目,要简单点。行吧,理论物理也带不动,拿出去年学习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;
}

最后的运行结果

Opencv - SVM_第1张图片


你可能感兴趣的:(opencv)