精华内容
下载资源
问答
  • svm模型训练
    千次阅读
    2021-02-22 21:19:19

    在调用sklearn的SVM时,如果设置verbose=True,模型训练结束后会显示一些训练过程的说明信息,如下(以下是OCSVM的返回结果):

    *
    optimization finished, # iter = 32
    obj = 192.154077, rho = 19.244379
    nSV = 26, nBSV = 15
    [LibSVM]

    以上各参数各代表什么含义呢?

    1. # iter 代表迭代次数
    2. obj 为 SVM 的最优目标值 (对于OCSVM来说是最核心处样本到边界的距离? )
    3. rho  为决策函数sgn(w^Tx - rho)中的偏置项 (是否可以理解为边界的厚度?)
    4. nSV  为支持向量个数
    5. nBSV 为边界上的支持向量个数

    参考:

    Verbose log abbriviations meaning in SVC, scikit-learn

    svm模型训练后的参数说明


    为了防止网页内容丢失,这里对Verbose log abbriviations meaning in SVC, scikit-learn进行了一个网页截图

    更多相关内容
  • opencv C++ SVM模型训练与分类实现

    千次阅读 2022-06-13 14:07:58
    我用的是opencv 4.5.1版本,...最近想学习一下分类算法的内容,恰好opencv有SVM的函数,故先从这个下手。找了许多资料,发现要么是opencv2、3的,要么就没有具体实现代码,学习还是把代码与原理一起结合来看比较好。...

    最近想学习一下分类算法的内容,恰好opencv有SVM的函数,故先从这个下手。找了许多资料,发现要么是opencv2、3的,要么就没有具体实现代码,学习还是把代码与原理一起结合来看比较好。

    其中,我主要参考的是这一篇文章:

    学习SVM(一) SVM模型训练与分类的OpenCV实现icon-default.png?t=M4ADhttps://blog.csdn.net/chaipp0607/article/details/68067098写得非常好!但是是2017年发布的文章,其中许多内容都做了更新,我用的是opencv 4.5.1版本,win10系统,vs2019作开发工具。具体opencv配置不说了,我对上面那篇文章的代码进行了更新。

    步骤一样.

    一、数据准备

    首先找到opencv库自带的digits图片,我的电脑上路径在:D:\app\opencv4.5.1\opencv\opencv\sources\samples\data\digits.png

    然后在D盘建立如下文件夹:

    只需新建命名就好了,不用往里面放东西。接下来建立vs2019项目工程,新建源文件

    复制如下代码:

    #include <windows.h>
    #include <iostream>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/core/utils/logger.hpp>
    #include <thread>
    #include <time.h>
    //#include <stdio.h>
    #include <string.h>
    
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	char ad[128] = { 0 };
    	int  filename = 0, filenum = 0;
    	Mat img = imread("digits.png");
    	Mat gray;
    	cvtColor(img, gray, COLOR_BGR2GRAY);
    	int b = 20;
    	int m = gray.rows / b;   //原图为1000*2000
    	int n = gray.cols / b;   //裁剪为5000个20*20的小图块
    
    	for (int i = 0; i < m; i++)
    	{
    		int offsetRow = i * b;  //行上的偏移量
    		if (i % 5 == 0 && i != 0)
    		{
    			filename++;
    			filenum = 0;
    		}
    		for (int j = 0; j < n; j++)
    		{
    			int offsetCol = j * b; //列上的偏移量
    			sprintf_s(ad, "D:\\data\\%d\\%d.jpg", filename, filenum++);
    			//截取20*20的小块
    			Mat tmp;
    			gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
    			imwrite(ad, tmp);
    		}
    	}
    	return 0;
    
    
    }
    
    

     运行结束后,在刚刚新建的文件夹中,0、1文件夹内各有500张分割好的图片。

    最后在test_image、train_image分别新建0、1文件夹。

    把data\0中的0-399复制到data\test_image\0,399-499复制到data\train_image\0;

    把data\1中的0-399复制到data\test_image\1,399-499复制到data\train_image\1。第一步完成。

    --D:
      --data
        --0
        --1
        --train_image
          --0(400张)
          --1(400张)
        --test_image
          --0(100张)
          --1(100张)
    

     二、模型训练

     再新建一个源文件:SVM模型训练.cpp,将第一步的SVM数据准备文件从项目中移除。

    复制上如下代码,其中最主要的就是opencv4中的SVM函数改变很大,配置参数上与原文完全不同

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    
    #include <iostream> 
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include "opencv2/imgcodecs.hpp"
    #include <opencv2/core/utils/logger.hpp>
    #include <opencv2/ml/ml.hpp>  
    #include <io.h>
    
    using namespace std;
    using namespace cv;
    using namespace cv::ml;
    
    void getFiles(string path, vector<string>& files);
    void get_1(Mat& trainingImages, vector<int>& trainingLabels);
    void get_0(Mat& trainingImages, vector<int>& trainingLabels);
    
    int main()
    {
    	//获取训练数据
    	Mat classes;
    	Mat trainingData;
    	Mat trainingImages;
    	vector<int> trainingLabels;
    	get_1(trainingImages, trainingLabels);
    	//waitKey(2000);
    	get_0(trainingImages, trainingLabels);
    	Mat(trainingImages).copyTo(trainingData);
    	trainingData.convertTo(trainingData, CV_32FC1);
    	Mat(trainingLabels).copyTo(classes);
    	//配置SVM训练器参数
    	Ptr<SVM> svm = SVM::create();
    	svm->setType(SVM::C_SVC);
    	svm->setKernel(SVM::LINEAR);
    	svm->setDegree(0);
    	svm->setGamma(1);
    	svm->setCoef0(0);
    	svm->setC(1);
    	svm->setNu(0);
    	svm->setP(0);
    	svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 1000, 0.01));
    	//训练
    	svm->train(trainingData, ROW_SAMPLE, classes );
    	//保存模型
    	svm->save("svm.xml");
    	
    	cout << "训练好了!!!" << endl;
    
    	getchar();
    	return 0;
    }
    void getFiles(string path, vector<string>& files)
    {
    	long long  hFile = 0;
    	struct _finddata_t fileinfo;
    	string p;
    	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
    	{
    		do
    		{
    			if ((fileinfo.attrib & _A_SUBDIR))
    			{
    				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
    					getFiles(p.assign(path).append("\\").append(fileinfo.name), files);
    			}
    			else
    			{
    				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
    			}
    		} while (_findnext(hFile, &fileinfo) == 0);
    
    		_findclose(hFile);
    	}
    }
    
    void get_1(Mat& trainingImages, vector<int>& trainingLabels)
    {
    	string filePath = "D:\\data\\train_image\\1";
    	cout << "获取D:\\data\\1" << endl;
    	vector<string> files;
    	getFiles(filePath, files);
    	int number = files.size();
    	for (int i = 0; i < number; i++)
    	{
    		Mat  SrcImage = imread(files[i].c_str());
    		SrcImage = SrcImage.reshape(1, 1);
    		trainingImages.push_back(SrcImage);
    		trainingLabels.push_back(1);
    	}
    }
    void get_0(Mat& trainingImages, vector<int>& trainingLabels)
    {
    	string filePath = "D:\\data\\train_image\\0";
    	cout << "获取D:\\data\\0" << endl;
    	vector<string> files;
    	getFiles(filePath, files);
    	int number = files.size();
    	for (int i = 0; i < number; i++)
    	{
    		Mat  SrcImage = imread(files[i].c_str());
    		SrcImage = SrcImage.reshape(1, 1);
    		trainingImages.push_back(SrcImage);
    		
    		trainingLabels.push_back(0);
    	}
    }
    

     训练完毕后,在这个解决方案文件夹下就生成了一个.xml文件,即是我们训练出来的模型。

    训练时还可以选择自动训练,会自己寻找最优参数,效果也很好。

    //训练
    	svm->trainAuto(trainingData, ROW_SAMPLE, classes );

    三、加载模型实现分类

    同样的,新建一个源文件:

    复制如下代码:

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    
    #include <iostream> 
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include "opencv2/imgcodecs.hpp"
    #include <opencv2/core/utils/logger.hpp>
    #include <opencv2/ml/ml.hpp>  
    #include <io.h>
    
    using namespace std;
    using namespace cv;
    using namespace cv::ml;
    
    void getFiles(string path, vector<string>& files);
    int main()
    {
    	int result = 0;
    	string filePath = "D:\\data\\test_image\\1";
    	vector<string> files;
    	getFiles(filePath, files);
    	int number = files.size();
    	cout << number << endl;
    	string modelpath = "svm.xml";
    	cv::Ptr<cv::ml::SVM> svm;
    	svm = cv::Algorithm::load<cv::ml::SVM>(modelpath);
    
    
    	/*CvSVM svm;
    	svm.clear();
    	string modelpath = "svm.xml";
    	FileStorage svm_fs(modelpath, FileStorage::READ);
    	if (svm_fs.isOpened())
    	{
    		svm.load(modelpath.c_str());
    	}*/
    	for (int i = 0; i < number; i++)
    	{
    		Mat inMat = imread(files[i].c_str());
    		Mat p = inMat.reshape(1, 1);
    		p.convertTo(p, CV_32FC1);
    		int response = (int)svm->predict(p);
    		if (response == 1)//要预测1,如果用0来做测试集就改成response == 0
    		{
    			result++;
    		}
    		else
    		{
    			cout << files[i] << endl;
    		}
    	}
    	cout << result << endl;
    	getchar();
    	return  0;
    }
    void getFiles(string path, vector<string>& files)
    {
    	long long   hFile = 0;
    	struct _finddata_t fileinfo;
    	string p;
    	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
    	{
    		do
    		{
    			if ((fileinfo.attrib & _A_SUBDIR))
    			{
    				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
    					getFiles(p.assign(path).append("\\").append(fileinfo.name), files);
    			}
    			else
    			{
    				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
    			}
    		} while (_findnext(hFile, &fileinfo) == 0);
    		_findclose(hFile);
    	}
    }
    

     如果想要检测0的分类准确率就让第46行的response == 0。

     可以看到,100张1有99张被识别出来,有一张452没有识别成功。100张0都识别出来了。

    展开全文
  • SVM学习(一)SVM模型训练与分类

    万次阅读 多人点赞 2019-03-08 17:27:04
    SVM模型训练与分类 支持向量机(SVM): 一个能够将不同类样本在样本空间分隔的超平面。换句话说,给定一些标记好的训练本(监督式学习),SVM算法输出一个最优化的超分隔平面。本次利用VS2015+OpenCV3.4.1实现SVM...

    SVM模型训练与分类

    支持向量机(SVM):
    一个能够将不同类样本在样本空间分隔的超平面。换句话说,给定一些标记好的训练本(监督式学习),SVM算法输出一个最优化的超分隔平面。本次利用VS2015+OpenCV3.4.1实现SVM算法,完成数据集的训练,生成XML文件,然后通过调用XML文件来实现图片的识别分类。即为分三个步骤:数据集的准备、数据集的模型训练以及利用训练好的模型进行测试分类。

    目的:利用SVM算法实现手写体0和1的图片的识别分类。

    步骤1:数据集的准备

    在OpenCV的安装路径下,搜索digits,可以得到一张图片,图片大小为1000*2000,有0-9的10个数字,每5行为一个数字,总共50行,共有5000个手写数字,每个数字块大小为20×20。 下面将把这些数字中的0和1作为二分类的准备数据。其中0有500张,1有500张。
    在这里插入图片描述
    用下面的代码将图片准备好,在写入路径提前建立好文件夹:

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	char ad[128] = { 0 };
    	int  filename = 0, filenum = 0;
    	Mat img = imread("F:\\Opencv3_4_1\\opencv\\sources\\samples\\data\\digits.png");
    	Mat gray;
    	cvtColor(img, gray, CV_BGR2GRAY);
    	int b = 20;
    	int m = gray.rows / b;   //原图为1000*2000
    	int n = gray.cols / b;   //裁剪为5000个20*20的小图块
    	for (int i = 0; i < m; i++)
    	{
    		int offsetRow = i*b;  //行上的偏移量
    		if (i % 5 == 0 && i != 0)
    		{
    			filename++;
    			filenum = 0;
    		}
    		for (int j = 0; j < n; j++)
    		{
    			int offsetCol = j*b; //列上的偏移量
    			sprintf_s(ad, "D:\\data\\%d\\%d.jpg", filename, filenum++);
    			//截取20*20的小块
    			Mat tmp;
    			gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
    			imwrite(ad, tmp);
    		}
    	}
    	return 0;
    }
    

    最后可以得到这样的结果
    准备好的数据
    将以上图片可以进行分类成训练集和测试集,方便后期进行训练和测试。要注意:训练中的图片不包含测试集合中的图片。
    在这里插入图片描述
    训练数据800张,0,1各400张;测试数据200张,0,1各100张

    步骤2:模型的训练

    数据准备完成之后,就可以用下面的代码训练了:

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    #include <opencv/cv.h>  
    #include <iostream> 
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/ml/ml.hpp>  
    #include <io.h> //查找文件相关函数
    
    using namespace std;
    using namespace cv;
    using namespace cv::ml;
    
    void getFiles(string path, vector<string>& files);
    void getBubble(Mat& trainingImages, vector<int>& trainingLabels);
    void getNoBubble(Mat& trainingImages, vector<int>& trainingLabels);
    int main()
    {
    	//获取训练数据
    	Mat classes;
    	Mat trainingData;
    	Mat trainingImages;
    	vector<int> trainingLabels;
    	//getBubble()与getNoBubble()将获取一张图片后会将图片(特征)写入
    	//  到容器中,紧接着会将标签写入另一个容器中,这样就保证了特征
    	//  和标签是一一对应的关系push_back(0)或者push_back(1)其实就是
    	//  我们贴标签的过程。
    	getBubble(trainingImages, trainingLabels);
    	getNoBubble(trainingImages, trainingLabels);
    	//在主函数中,将getBubble()与getNoBubble()写好的包含特征的矩阵拷贝给trainingData,将包含标签的vector容器进行类
    	//型转换后拷贝到trainingLabels里,至此,数据准备工作完成,trainingData与trainingLabels就是我们要训练的数据。
    	Mat(trainingImages).copyTo(trainingData);
    	trainingData.convertTo(trainingData, CV_32FC1);
    	Mat(trainingLabels).copyTo(classes);
    	// 创建分类器并设置参数
    	Ptr<SVM> SVM_params = SVM::create();
    	SVM_params->setType(SVM::C_SVC);
    	SVM_params->setKernel(SVM::LINEAR);  //核函数
    	SVM_params->setDegree(0);
    	SVM_params->setGamma(1);
    	SVM_params->setCoef0(0);
    	SVM_params->setC(1);
    	SVM_params->setNu(0);
    	SVM_params->setP(0);
    	SVM_params->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, 0.01));
    	Ptr<TrainData> tData = TrainData::create(trainingData, ROW_SAMPLE, classes);
    	// 训练分类器
    	SVM_params->train(tData);
    	//保存模型
    	SVM_params->save("svm.xml");//将训练好的模型保存在此文件中。
    	cout << "训练好了!!!" << endl;
    	getchar();
    	return 0;
    }
    void getFiles(string path, vector<string>& files)//用来遍历文件夹下的所有文件。
    {
    	intptr_t   hFile = 0;
    	struct _finddata_t fileinfo;
    	string p;
    	int i = 30;
    	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
    	{
    		do
    		{
    			if ((fileinfo.attrib &  _A_SUBDIR))
    			{
    				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
    					getFiles(p.assign(path).append("\\").append(fileinfo.name), files);
    			}
    			else
    			{
    				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
    			}
    
    		} while (_findnext(hFile, &fileinfo) == 0);
    
    		_findclose(hFile);
    	}
    }
    //获取正样本
    //并贴标签为1
    void getBubble(Mat& trainingImages, vector<int>& trainingLabels)
    {
    	char * filePath = "D:\\data\\train_image\\1"; //数字1样本路径
    	vector<string> files;
    	getFiles(filePath, files);
    	int number = files.size();
    	for (int i = 0; i < number; i++)
    	{
    		Mat  SrcImage = imread(files[i].c_str());
    		SrcImage = SrcImage.reshape(1, 1);
    		trainingImages.push_back(SrcImage);
    		trainingLabels.push_back(1);//该样本为数字1
    	}
    
    }
    //获取负样本
    //并贴标签为0
    void getNoBubble(Mat& trainingImages, vector<int>& trainingLabels)
    {
    	char * filePath = "D:\\data\\train_image\\0"; //数组0样本路径
    	vector<string> files;
    	getFiles(filePath, files);
    	int number = files.size();
    	for (int i = 0; i < number; i++)
    	{
    		Mat  SrcImage = imread(files[i].c_str());
    		SrcImage = SrcImage.reshape(1, 1);
    		trainingImages.push_back(SrcImage);
    		trainingLabels.push_back(0); //该样本是数字0
    	}
    }
    

    注意:此过程的主要目的是生成xml文件,此文件保存在该工程项目的根目录下。

    步骤3:加载模型进行分类识别

    将上一步生成的XML文件复制一份到该工程根目录下,否则无法加载。
    在这里插入图片描述
    测试代码如下所示:

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    #include <opencv/cv.h>  
    #include <iostream> 
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/ml/ml.hpp>  
    #include <io.h>
    using namespace std;
    using namespace cv;
    //using namespace ml;
    
    void getFiles(string path, vector<string>& files);
    int main()
    {
    	int result0 = 0;
    	int result1 = 0;
    	char * filePath = "D:\\data\\test_image\\0";
    	vector<string> files;
    	getFiles(filePath, files);
    	int number = files.size();
    	cout <<"共有测试图片"<< number<<"张\n" << endl;
    	Ptr<ml::SVM>svm = ml::SVM::load("svm.xml");
    	
    	for (int i = 0; i < number; i++)
    	{
    		Mat inMat = imread(files[i].c_str());
    		Mat p = inMat.reshape(1, 1);
    		p.convertTo(p, CV_32FC1);
    		int response = (int)svm->predict(p);
    		cout << "识别的数字为:" << response << endl;
    		if (response == 0)
    		{
    			result0++;
    		}
    		else 
    		{
    			result1++;
    		}
    
    	}
    	cout << "识别的数字0的个数为:" << result0 << endl;
    	cout << "识别的数字1的个数为:" << result1 << endl;
    	getchar();
    	return  0;
    }
    void getFiles(string path, vector<string>& files)  //用来遍历文件夹下所有文件
    {
    	intptr_t   hFile = 0;
    	/*long   hFile = 0;*/
    	struct _finddata_t fileinfo;
    	string p;
    	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
    	{
    		do
    		{
    			if ((fileinfo.attrib &  _A_SUBDIR))
    			{
    				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
    					getFiles(p.assign(path).append("\\").append(fileinfo.name), files);
    			}
    			else
    			{
    				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
    			}
    		} while (_findnext(hFile, &fileinfo) == 0);
    		_findclose(hFile);
    	}
    }
    

    本次的测试图片共100张,其中0有94张,1有6张。
    在这里插入图片描述
    下面展示测试效果:
    在这里插入图片描述
    可以看出测试效果还不错!

    展开全文
  • 学习SVM(一) SVM模型训练与分类的OpenCV实现

    万次阅读 多人点赞 2017-03-29 21:47:52
    学习SVM(一) SVM模型训练与分类的OpenCV实现 学习SVM(二) 如何理解支持向量机的最大分类间隔 学习SVM(三)理解SVM中的对偶问题 学习SVM(四) 理解SVM中的支持向量(Support Vector)Andrew Ng 在斯坦福大学...

    简介

    学习SVM(一) SVM模型训练与分类的OpenCV实现
    学习SVM(二) 如何理解支持向量机的最大分类间隔
    学习SVM(三)理解SVM中的对偶问题
    学习SVM(四) 理解SVM中的支持向量(Support Vector)
    学习SVM(五)理解线性SVM的松弛因子

    Andrew Ng 在斯坦福大学的机器学习公开课上这样评价支持向量机:
    support vector machines is the supervised learning algorithm that many people consider the most effective off-the-shelf supervised learning algorithm.That point of view is debatable,but there are many people that hold that point of view.

    可见,在监督学习算法中支持向量机有着非常广泛的应用,而且在解决图像分类问题时有着优异的效果。

    OpenCV集成了这种学习算法,它被包含在ml模块下的CvSVM类中,下面我们用OpenCV实现SVM的数据准备模型训练加载模型实现分类,为了理解起来更加直观,我们用三个工程来实现。

    数据准备

    在OpenCV的安装路径下,搜索digits,可以得到一张图片,图片大小为10002000,有0-9的10个数字,每5行为一个数字,总共50行,共有5000个手写数字,每个数字块大小为2020。 下面将把这些数字中的0和1作为二分类的准备数据。其中0有500张,1有500张。
    用下面的代码将图片准备好,在写入路径提前建立好文件夹:

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
    	char ad[128]={0};
    	int  filename = 0,filenum=0; 
    	Mat img = imread("digits.png");
    	Mat gray;
    	cvtColor(img, gray, CV_BGR2GRAY);
    	int b = 20;
    	int m = gray.rows / b;   //原图为1000*2000
    	int n = gray.cols / b;   //裁剪为5000个20*20的小图块
    
    	for (int i = 0; i < m; i++)
    	{
    		int offsetRow = i*b;  //行上的偏移量
    		if(i%5==0&&i!=0)
    		{
    			filename++;
    			filenum=0;
    		}
    		for (int j = 0; j < n; j++)
    		{
    			int offsetCol = j*b; //列上的偏移量
    			sprintf_s(ad, "D:\\data\\%d\\%d.jpg",filename,filenum++);
    			//截取20*20的小块
    			Mat tmp;
    			gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
    			imwrite(ad,tmp);
    		}
    	}
    	return 0;
    }
    

    最后可以得到这样的结果:
    这里写图片描述
    组织的二分类数据形式为:

    --D:
      --data
        --train_image
          --0(400张)
          --1(400张)
        --test_image
          --0(100张)
          --1(100张)
    

    这里写图片描述
    训练数据800张,0,1各400张;测试数据200张,0,1各100张

    模型训练

    数据准备完成之后,就可以用下面的代码训练了:

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    #include <opencv/cv.h>  
    #include <iostream> 
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/ml/ml.hpp>  
    #include <io.h>
    
    using namespace std;
    using namespace cv;
    
    void getFiles( string path, vector<string>& files);
    void get_1(Mat& trainingImages, vector<int>& trainingLabels);
    void get_0(Mat& trainingImages, vector<int>& trainingLabels);
    
    int main()
    {
    	//获取训练数据
    	Mat classes;
    	Mat trainingData;
    	Mat trainingImages;
    	vector<int> trainingLabels;
    	get_1(trainingImages, trainingLabels);
    	get_0(trainingImages, trainingLabels);
    	Mat(trainingImages).copyTo(trainingData);
    	trainingData.convertTo(trainingData, CV_32FC1);
    	Mat(trainingLabels).copyTo(classes);
    	//配置SVM训练器参数
    	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, 1000, 0.01);
    	//训练
    	CvSVM svm;
    	svm.train(trainingData, classes, Mat(), Mat(), SVM_params);
    	//保存模型
    	svm.save("svm.xml");
    	cout<<"训练好了!!!"<<endl;
    	getchar();
    	return 0;
    }
    void getFiles( string path, vector<string>& files )  
    {  
    	long   hFile   =   0;  
    	struct _finddata_t fileinfo;  
    	string p;  
    	if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
    	{  
    		do  
    		{  
    			if((fileinfo.attrib &  _A_SUBDIR))  
    			{  
    				if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)  
    					getFiles( p.assign(path).append("\\").append(fileinfo.name), files );  
    			}  
    			else  
    			{  
    				files.push_back(p.assign(path).append("\\").append(fileinfo.name) );  
    			}  
    		}while(_findnext(hFile, &fileinfo)  == 0);  
    
    		_findclose(hFile);  
    	}  
    } 
    void get_1(Mat& trainingImages, vector<int>& trainingLabels)
    {
    	char * filePath = "D:\\data\\train_image\\1"; 
    	vector<string> files;  
    	getFiles(filePath, files );  
    	int number = files.size();  
    	for (int i = 0;i < number;i++)  
    	{  
    		Mat  SrcImage=imread(files[i].c_str());
    		SrcImage= SrcImage.reshape(1, 1);
    		trainingImages.push_back(SrcImage);
    		trainingLabels.push_back(1);
    	}  
    }
    void get_0(Mat& trainingImages, vector<int>& trainingLabels)
    {
    	char * filePath = "D:\\data\\train_image\\0"; 
    	vector<string> files;  
    	getFiles(filePath, files );  
    	int number = files.size();  
    	for (int i = 0;i < number;i++)  
    	{  
    		Mat  SrcImage=imread(files[i].c_str());
    		SrcImage= SrcImage.reshape(1, 1);
    		trainingImages.push_back(SrcImage);
    		trainingLabels.push_back(0);
    	}  
    }
    

    整个训练过程可以分为一下几个部分:
    数据准备:
    该例程中一个定义了三个子程序用来实现数据准备工作:
    getFiles()用来遍历文件夹下所有文件,可以参考:
    http://blog.csdn.net/chaipp0607/article/details/53914954
    getBubble()用来获取有气泡的图片和与其对应的Labels,该例程将Labels定为1。
    getNoBubble()用来获取没有气泡的图片与其对应的Labels,该例程将Labels定为0。
    getBubble()与getNoBubble()将获取一张图片后会将图片(特征)写入到容器中,紧接着会将标签写入另一个容器中,这样就保证了特征和标签是一一对应的关系push_back(0)或者push_back(1)其实就是我们贴标签的过程。

    trainingImages.push_back(SrcImage);
    trainingLabels.push_back(0);
    

    在主函数中,将getBubble()与getNoBubble()写好的包含特征的矩阵拷贝给trainingData,将包含标签的vector容器进行类型转换后拷贝到trainingLabels里,至此,数据准备工作完成,trainingData与trainingLabels就是我们要训练的数据。

    	Mat classes;
    	Mat trainingData;
    	Mat trainingImages;
    	vector<int> trainingLabels;
    	getBubble(trainingImages, trainingLabels);
    	getNoBubble(trainingImages, trainingLabels);
    	Mat(trainingImages).copyTo(trainingData);
    	trainingData.convertTo(trainingData, CV_32FC1);
    	Mat(trainingLabels).copyTo(classes);
    

    特征选取
    其实特征提取和数据的准备是同步完成的,我们最后要训练的也是正负样本的特征。本例程中同样在getBubble()与getNoBubble()函数中完成特征提取工作,只是我们简单粗暴将整个图的所有像素作为了特征,因为我们关注更多的是整个的训练过程,所以选择了最简单的方式完成特征提取工作,除此中外,特征提取的方式有很多,比如LBP,HOG等等。

      SrcImage= SrcImage.reshape(1, 1);
    

    我们利用reshape()函数完成特征提取,原型如下:

     Mat reshape(int cn, int rows=0) const;
    

    可以看到该函数的参数非常简单,cn为新的通道数,如果cn = 0,表示通道数不会改变。参数rows为新的行数,如果rows = 0,表示行数不会改变。我们将参数定义为reshape(1, 1)的结果就是原图像对应的矩阵将被拉伸成一个一行的向量,作为特征向量。
    参数配置
    参数配置是SVM的核心部分,在Opencv中它被定义成一个结构体类型,如下:

    struct CV_EXPORTS_W_MAP CvSVMParams
    {
        CvSVMParams();
        CvSVMParams(  
        int svm_type, 
        int kernel_type,
        double degree, 
        double coef0,
        double Cvalue, 
        double p,
        CvMat* class_weights, 
        CvTermCriteria term_crit );
        CV_PROP_RW int         svm_type;
        CV_PROP_RW int         kernel_type;
        CV_PROP_RW double      degree; // for poly
        CV_PROP_RW double      gamma;  // for poly/rbf/sigmoid
        CV_PROP_RW double      coef0;  // for poly/sigmoid
        CV_PROP_RW double      C;  // for CV_SVM_C_SVC,       CV_SVM_EPS_SVR and CV_SVM_NU_SVR
        CV_PROP_RW double      nu; // for CV_SVM_NU_SVC, CV_SVM_ONE_CLASS, and CV_SVM_NU_SVR
        CV_PROP_RW double      p; // for CV_SVM_EPS_SVR
        CvMat*      class_weights; // for CV_SVM_C_SVC
        CV_PROP_RW CvTermCriteria term_crit; // termination criteria
    };
    

    所以在例程中我们定义了一个结构体变量用来配置这些参数,而这个变量也就是CVSVM类中train函数的第五个参数,下面对参数进行说明。
    SVM_params.svm_type :SVM的类型:
    C_SVC表示SVM分类器,C_SVR表示SVM回归
    SVM_params.kernel_type:核函数类型
    线性核LINEAR:
    d(x,y)=(x,y)
    多项式核POLY:
    d(x,y)=(gamma*(x’y)+coef0)degree
    径向基核RBF:
    d(x,y)=exp(-gamma*|x-y|^2)
    sigmoid核SIGMOID:
    d(x,y)= tanh(gamma*(x’y)+ coef0)

    SVM_params.degree:核函数中的参数degree,针对多项式核函数;
    SVM_params.gama:核函数中的参数gamma,针对多项式/RBF/SIGMOID核函数;
    SVM_params.coef0:核函数中的参数,针对多项式/SIGMOID核函数;
    SVM_params.c:SVM最优问题参数,设置C-SVCEPS_SVRNU_SVR的参数;
    SVM_params.nu:SVM最优问题参数,设置NU_SVCONE_CLASSNU_SVR的参数;
    SVM_params.p:SVM最优问题参数,设置EPS_SVR 中损失函数p的值.
    训练模型

    CvSVM svm;
    svm.train(trainingData, classes, Mat(), Mat(), SVM_params);
    

    通过上面的过程,我们准备好了待训练的数据和训练需要的参数,**其实可以理解为这个准备工作就是在为svm.train()函数准备实参的过程。**来看一下svm.train()函数,Opencv将SVM封装成CvSVM库,这个库是基于台湾大学林智仁(Lin Chih-Jen)教授等人开发的LIBSVM封装的,由于篇幅限制,不再全部粘贴库的定义,所以一下代码只是CvSVM库中的一部分数据和函数:

    class CV_EXPORTS_W CvSVM : public CvStatModel
    {
    public:
    virtual bool train( 
      const CvMat* trainData, 
      const CvMat* responses,
      const CvMat* varIdx=0, 
      const CvMat* sampleIdx=0,
      CvSVMParams params=CvSVMParams() );
    virtual float predict( 
      const CvMat* sample, 
      bool returnDFVal=false ) const;
    

    我们就是应用类中定义的train函数完成模型训练工作。
    保存模型

    svm.save("svm.xml");
    

    保存模型只有一行代码,利用save()函数,我们看下它的定义:

        CV_WRAP virtual void save( const char* filename, const char* name=0 ) const;
    

    该函数被定义在CvStatModel类中,CvStatModel是ML库中的统计模型基类,其他 ML 类都是从这个类中继承。

    **总结:**到这里我们就完成了模型训练工作,可以看到真正用于训练的代码其实很少,OpenCV最支持向量机的封装极大地降低了我们的编程工作。

    加载模型实现分类

    #include <stdio.h>  
    #include <time.h>  
    #include <opencv2/opencv.hpp>  
    #include <opencv/cv.h>  
    #include <iostream> 
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/ml/ml.hpp>  
    #include <io.h>
    
    using namespace std;
    using namespace cv;
    
    void getFiles( string path, vector<string>& files );
    
    int main()
    {
    	int result = 0;
    	char * filePath = "D:\\data\\test_image\\0"; 
    	vector<string> files;  
    	getFiles(filePath, files );  
    	int number = files.size();  
    	cout<<number<<endl;
    	CvSVM svm;
    	svm.clear();
    	string modelpath = "svm.xml";
    	FileStorage svm_fs(modelpath,FileStorage::READ);
    	if(svm_fs.isOpened())
    	{
    		svm.load(modelpath.c_str());
    	}
    	for (int i = 0;i < number;i++)  
    	{  
    		Mat inMat = imread(files[i].c_str());
    		Mat p = inMat.reshape(1, 1);
    		p.convertTo(p, CV_32FC1);
    		int response = (int)svm.predict(p);
    		if (response == 0)
    		{
    			result++;
    		}
    	}
    	cout<<result<<endl;
    	getchar();
    	return  0;
    }
    void getFiles( string path, vector<string>& files )  
    {  
    	long   hFile   =   0;  
    	struct _finddata_t fileinfo;  
    	string p;  
    	if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) !=  -1)  
    	{  
    		do  
    		{  
    			if((fileinfo.attrib &  _A_SUBDIR))  
    			{  
    				if(strcmp(fileinfo.name,".") != 0  &&  strcmp(fileinfo.name,"..") != 0)  
    					getFiles( p.assign(path).append("\\").append(fileinfo.name), files );  
    			}  
    			else  
    			{  		files.push_back(p.assign(path).append("\\").append(fileinfo.name) );  
    			}  
    		}while(_findnext(hFile, &fileinfo)  == 0);  
    		_findclose(hFile);  
    	}  
    } 
    

    在上面我们把该介绍的都说的差不多了,这个例程中只是用到了load()函数用于模型加载,加载的就是上面例子中生成的模型,load()被定义在CvStatModel这个基类中:

    	svm.load(modelpath.c_str());
    

    load的路径是string modelpath = "svm.xml",这意味着svm.mxl文件应该在测试工程的根目录下面,但是因为训练和预测是两个独立的工程,所以必须要拷贝一下这个文件。最后用到predict()函数用来预测分类结果,predict()被定义在CVSVM类中。

    注意:

    1.为什么要建立三个独立的工程呢?
    主要是考虑写在一起话,代码量会比较大,逻辑没有分开清晰,当跑通上面的代码之后,就可以随意的改了。
    2.为什么加上数据准备?
    之前有评论说道数据的问题,提供数据后实验能更顺利一些,因为本身代码没有什么含金量,这样可以更顺利的运行起来工程,并修改它。
    3.一些容易引起异常的情况:
    (1):注意生成的.xml记得拷贝到预测工程下;
    (2):注意准备好数据路径和代码是不是一致;
    (3):注意训练的特征要和测试的特征一致;

    展开全文
  • 车牌识别SVM,已经训练好的样本集,直接可用于车牌识别。包括两个文件,svm.dat和svmchinese.dat,其中前一个文件用于识别字母和数字;后一个文件用于识别汉字。
  • 现简单对屏幕回显信息进行说明: #iter为迭代次数, nu与前面的操作参数-n nu...训练后的模型保存为文件*.model,用记事本打开其内容如下: svm_type c_svc%训练所采用的svm类型,此处为C- SVC kernel_type rbf...
  • 学习SVM(一) SVM模型训练与分类的OpenCV实现 学习SVM(二) 如何理解支持向量机的最大分类间隔 学习SVM(三)理解SVM中的对偶问题 学习SVM(四) 理解SVM中的支持向量(Support Vector) 学习SVM(五)理解...
  • svm模型训练后的参数说明

    千次阅读 2017-12-08 20:44:20
    现简单对屏幕回显信息进行说明: #iter 为迭代次数, nu 与前面的操作参数 -n nu 相同, obj 为 SVM 文件转换为的二次规划求解得到的...训练后的模型保存为文件 *.model ,用记事本打开其内容如下: svm
  • 在matlab中进行SVM模型训练,通常有两种选择: 注意: a、如果matlab安装了LibSVM,在使用matlab自带的SVM时,需要进行搜索路径重新设定  路径重新设定方法:在matlab软件主窗口中【主页】--【设置路径】移除...
  • 1、SVM模型训练 2、SVM模型参数输出 3、SVM模型保存与读取 二、交叉验证与网络搜索 1、交叉验证 1)、k折交叉验证(Standard Cross Validation) 2)、留一法交叉验证(leave-one-out) 3)、打乱划分交叉...
  • 在opencv3.3.0中通过SVM模型训练

    千次阅读 2018-02-08 20:37:00
    训练代码是基于车牌识别的正样本和负样本的模型训练,正确的返回1,错误的返回0。 代码是在linux下运行的,由于opencv3.0以上的版本做了很大的改动,SVM类中的函数也不例外,下面贴出代码: #include #include #...
  • python svm 怎么训练模型

    千次阅读 2020-11-20 18:52:54
    展开全部支持2113向量机SVM(Support Vector Machine)是有监督的分类预测模型,本篇文章5261使用机器学习库scikit-learn中的手写数字数4102据集介绍使用Python对SVM模型进行1653训练并对手写数字进行识别的过程。...
  • SVM 模型训练到social LSTM

    千次阅读 2019-05-09 15:25:45
    之前看过台大李宏毅的SVM介绍,我寻思我没看到...但是有关于SVM模型介绍是有点少的。 最近看到一篇paper The relation probabilities are determined by a probabilistic SVM trained on 3D motion indicator f...
  • 睁闭眼状态检测——SVM模型训练

    千次阅读 热门讨论 2019-07-09 19:04:00
    svm训练模型相当简单,难的是提取特征这一步,这里介绍了一个睁闭眼检测功能从提取特征到预测的全过程。 首先,需要准备数据,我这里有睁眼和闭眼的照片各3000张,传统的机器学习方法都需要提取特征,这里检测特征...
  • SVM模型详解

    千次阅读 2022-03-25 08:53:21
    一、SVM定义与解决目标 SVM是一个二类分类器。其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化成一个凸二次规划问题的求解。即找到一个超平面,使两类数据离超平面越远越...
  • SVM算法练习

    2021-11-17 18:46:05
    一、前言 libSVM简介 LIBSVM是台湾大学林智仁(Lin Chih-Jen)教授等开发设计的一个简单、易于使用和快速有效的SVM模式识别与回归的软件包,他不但提供了...该软件可以解决C-SVM、ν-SVM、ε-SVR和ν-SVR等问题,...
  • mo_3.m_lbp特征提取,fitcecoc训练svm模型,predict预测,人脸分类。使用fitcecoc函数训练一个多分类的SVM模型,使用predict函数利用训练出的模型对测试数据进行预测,将得到的类标预测值与测试数据真实的类标进行...
  • SVM代码和模型.zip

    2021-08-06 10:58:49
    SVM+Sift+K-means实现图像分类(python)的代码部分,包含训练和测试代码,以及训练好的模型
  • svm_C++_SVM_

    2021-10-03 10:01:43
    此代码是用C写的,用于进行支持向量机(SVM)的训练代码的C文件格式。
  • 最新代码Github地址:...所以又尝试通过hard negative mining优化训练SVM模型。原理大概就是先用原始训练训练出一个模型,然后对所有负样本滑窗预测。如果该窗口预测结果为正,那么...
  • SVM模型训练时命令行窗口参数意义

    千次阅读 2017-05-27 16:01:18
    nu = 0.909091 SVC,one-class-SVM,SVR参数 obj = -108.333321 二次规划的最小值 rho = -0.166667 决策函数常数项 nSV = 220 支持向量数 nBSV = 100 边界上支持向量数 Total nSV = 220 支持向量总数 Accur
  • SVM算法训练的分类器

    2016-04-24 11:11:13
    模式识别课上的SVM分类器训练及测试程序(Matlab),带训练集和测试集,可直接使用,计算正确率,好用
  • clf.model svm训练模型

    2021-04-15 10:22:54
    svm训练模型
  • #太小可能会降低你的准确率,太大的尺寸会花费更多的时间进行模型训练。 三、运行hog_svm.py,使用hog_svm模型进行训练和测试; 或者您可以运行 train.py 和 test.py 以使用基于 tensorflow 的 ML 模型进行训练和...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 67,534
精华内容 27,013
关键字:

svm模型训练