SVM与OpenCV

SVM是一个成熟经典的技术,被用在很多分类问题中,比如早期的人脸识别问题,很多是HOG+SVM。最近在做识别魔方颜色的时候,研究了OpenCV中的SVM分类器。

首先还是来看官方文档

https://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html#introductiontosvms

https://docs.opencv.org/3.4/d1/d73/tutorial_introduction_to_svm.html

两个教程例子都比较直观,给定一些二维点的坐标(x,y)和标签label(人为指定,-1和1),进行SVM的训练,然后调用训练模型进行预测,并将结果做了直观显示。

opencv2跟3中的训练样本有细微差别,主要是样本数据为CV_32SC1和CV_32FC1的差别

https://blog.csdn.net/wfh2015/article/details/51163890

    //cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
	//svm->setType(cv::ml::SVM::Types::C_SVC);
	//svm->setKernel(cv::ml::SVM::KernelTypes::LINEAR);
	//svm->setDegree(0.0);
	//svm->setGamma(1.0);
	//svm->setCoef0(0.0);
	//svm->setC(1.0);
	//svm->setNu(0.0);
	//svm->setP(0.0);
	//svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS , 20000, 0.001));
	// svm->train(trainingData, cv::ml::SampleTypes::ROW_SAMPLE, classes);
	 
	//cv::Ptr<cv::ml::TrainData> &&trainDataSet = cv::ml::TrainData::create(trainingData, cv::ml::ROW_SAMPLE, classes);
	//svm->trainAuto(trainDataSet);
	//svm.train(trainingData, classes, Mat(), Mat(), SVM_params);

	CvSVMParams SVM_params;
	SVM_params.svm_type = CvSVM::C_SVC;
	SVM_params.kernel_type = CvSVM::LINEAR;
	SVM_params.degree = 0;
	SVM_params.gamma = 1;
	SVM_params.coef0 = 0;
	SVM_params.C = 1;
	SVM_params.nu = 0;
	SVM_params.p = 0;
	SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER + cv::TermCriteria::EPS, 20000, 0.001);

	CvSVM svm;
	svm.train_auto(trainingData, classes, Mat(), Mat(), SVM_params);
	
	//保存模型
	svm.save("D:\\opencv_work\\cubeSolver\\svm.xml");
	//svm->save("D:\\opencv_work\\cubeSolver\\svm.xml");

学习的时候,我跟着这个教程( https://blog.csdn.net/chaipp0607/article/details/68067098 )做了一遍 。因为手写数字集的图片opencv本身就带有,而且作者还手把手带着做了一遍,包括图片分割,样本数据集的建立,最后利用训练的模型识别手写数字0和1。注意的地方是,数字图片的文件夹事先建立好,不然以为它没有把图片分割成功。另外,训练集合测试集自己拷贝好,训练集每个数字400张图片,测试集每个数字100张图片。D:\opencv_work\cubeSolver\cv_solver\ConsoleApplication1\trainSaveTest_cv2.0.cpp

 

1的测试数据集 100张识别正确99张,有一个没识别对,可以从上图中看到,1写的还是很怪的。0的识别完成正确。

总结下, 官方例子的特征向量为二维点x和y,label为-1和1。width*height=2*4, label的维度width*height=1*4。

0,1手写数字识别的特征向量为大小20x20,3通道的图片,每个像素点都是特征参数。每张图片有20*20*3=1200个特征,0和1的图片共有800张,因此训练用的特征向量的维度为width*height=1200*800,label的维度width*height=1*800,0和1的label各一半,各四百个。从这两个例子看到,label的第二维和data的第二维相等,通俗理解就是有多少个样本就有多少条label。cv::ml::SampleTypes::ROW_SAMPLE样本为行排列,一行为一个样本。

魔方颜色SVM 

有了上面的例子的经验,就可以看看魔方的颜色识别的例子了,一般的三阶魔方有6个颜色,每个颜色,考虑到光照的影响,这里将RGB三通道和HSV三通道一共六个数据作为特征。一个行样本就是这6个数据,标签lable就是颜色值,这里将颜色值与数字123456相对应,便于程序计算。

猜你喜欢

转载自blog.csdn.net/yaked/article/details/84850510