opencv C++ SVM模型训练与分类实现

这篇具有很好参考价值的文章主要介绍了opencv C++ SVM模型训练与分类实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

学习SVM(一) SVM模型训练与分类的OpenCV实现https://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盘建立如下文件夹:

opencv C++ SVM模型训练与分类实现

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

opencv C++ SVM模型训练与分类实现

复制如下代码:

#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张分割好的图片。

opencv C++ SVM模型训练与分类实现

最后在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数据准备文件从项目中移除。

opencv C++ 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 );

三、加载模型实现分类

同样的,新建一个源文件:opencv C++ 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);
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。

opencv C++ SVM模型训练与分类实现

 可以看到,100张1有99张被识别出来,有一张452没有识别成功。100张0都识别出来了。文章来源地址https://www.toymoban.com/news/detail-487017.html

到了这里,关于opencv C++ SVM模型训练与分类实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python机器学习——分类模型评估 & 分类算法(k近邻,朴素贝叶斯,决策树,随机森林,逻辑回归,svm)

    交叉验证:为了让被评估的模型更加准确可信 交叉验证:将拿到的数据,分为训练和验证集。以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果。又称5折交叉验证。 通常情

    2024年02月03日
    浏览(52)
  • 【模型部署 01】C++实现分类模型(以GoogLeNet为例)在OpenCV DNN、ONNXRuntime、TensorRT、OpenVINO上的推理部署

    深度学习领域常用的基于CPU/GPU的推理方式有OpenCV DNN、ONNXRuntime、TensorRT以及OpenVINO。这几种方式的推理过程可以统一用下图来概述。整体可分为模型初始化部分和推理部分,后者包括步骤2-5。 以GoogLeNet模型为例,测得几种推理方式在推理部分的耗时如下: 结论: GPU加速首选

    2024年02月06日
    浏览(42)
  • 机械学习模型训练常用代码(随机森林、聚类、逻辑回归、svm、线性回归、lasso回归,岭回归)

    更多pandas操作请参考添加链接描述pandas对于文件数据基本操作 导入的包sklearn 字符串编码处理,LabelEncoder TfidfVectorizer结合TruncatedSVD 排除某一列,例如 如果需要用到回归则换成RandomForestRegressor 数据在dc_matrix里面 绘制距离 #加入到表里面 师范,保存文本模型,使用其转换,调

    2023年04月14日
    浏览(35)
  • 分类模型训练pil、torchvision.transforms和opencv的resize

    参考:https://blog.csdn.net/weixin_41012399/article/details/126049885 https://www.cnpython.com/qa/1291644 https://blog.csdn.net/weixin_44966641/article/details/125084573 https://blog.csdn.net/IEEE_FELLOW/article/details/115536987 训练时用pil读取图片,使用torchvision.transforms.Resize 进行数据处理。因为transforms.Resize当输入为PIL图像

    2024年02月09日
    浏览(36)
  • python机器学习决策树和SVM向量机算法实现红酒分类

    经典的红酒分类数据集是指UCI机器学习库中的Wine数据集。该数据集包含178个样本,每个样本有13个特征,可以用于分类任务。 具体每个字段的含义如下: alcohol:酒精含量百分比 malic_acid:苹果酸含量(克/升) ash:灰分含量(克/升) alcalinity_of_ash:灰分碱度(以mEq/L为单位)

    2024年02月08日
    浏览(29)
  • 深度学习(16)--基于经典网络架构resnet训练图像分类模型

    目录 一.项目介绍 二.项目流程详解 2.1.引入所需的工具包 2.2.数据读取和预处理 2.3.加载resnet152模型 2.4.初始化模型 2.5.设置需要更新的参数 2.6.训练模块设置 2.7.再次训练所有层 2.8.测试网络效果 三.完整代码 使用PyTorch工具包调用经典网络架构resnet训练图像分类模型,用于分辨

    2024年02月20日
    浏览(33)
  • PyTorch 分类模型的转换和使用 OpenCV C++ 启动

    在本教程中,您将学习如何: 将 PyTorch 分类模型转换为 ONNX 格式 使用 OpenCV C/C++ API 运行转换后的 PyTorch 模型 提供模型推理 我们将以 ResNet-50 架构为例来探讨上述几点。 让我们简要回顾一下使用 OpenCV API 进行 PyTorch 模型转换的管道中涉及的关键概念。将 PyTorch 模型转换为 

    2024年02月21日
    浏览(25)
  • TensorFlow学习:使用官方模型和自己的训练数据进行图片分类

    教程来源:清华大佬重讲机器视觉!TensorFlow+Opencv:深度学习机器视觉图像处理实战教程,物体检测/缺陷检测/图像识别 注: 这个教程与官网教程有些区别,教程里的api比较旧,核心思想是没有变化的。 上一篇文章 TensorFlow学习:使用官方模型进行图像分类、使用自己的数据

    2024年02月08日
    浏览(36)
  • 使用PyTorch解决多分类问题:构建、训练和评估深度学习模型

    💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢迎在文章下方留下你的评论和反馈。我期待着与你分享知识、互

    2024年02月07日
    浏览(34)
  • 机器学习实战-SVM模型实现人脸识别

    首先进行导包 我们加载sklearn已经帮我们收集好的人脸数据 查看结果: 我们取出其中的数据进行查看: 运行结果: 我们随机选取一个人的图片并通过索引获取名字: 结果展示: 由于原来的数据很大,而且数据量多,我们首先对原始数据进行PCA降维 结果展示: 然后对降维后

    2024年02月04日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包