ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【OpenCV学习记录】HOG+SVM叶片病斑识别

2019-09-14 21:36:46  阅读:410  来源: 互联网

标签:HOG svm mat OpenCV SVM size data Size


1.从哪哪都不知道到会用
(1)找了官方的实例代码,因为本人代码阅读能力有限,因此将代码部分下载下来,边查边记就看懂了,再敲一遍(opencv2.x和opencv3.x有些用法不太一样要自己改一改)

链接
1 支持向量机线性可分数据的处理
2 支持向量机对线性不可分数据的处理

(2)找了一些应用的例子,打印,看懂,仿照着敲代码,就成啦

链接
1 以整个图像为特征的手写数字SVM识别
2 小狮子识别
3 车标识别
4 视频识别

2.准备数据
(1)准备了50幅病斑的图片然后通过旋转翻转等操作扩充到480幅(可以大小不一样,因为代码部分会重置图片大小)
在这里插入图片描述
(2)准备了120幅正常叶子的图片,扩充到480幅(可以大小不一样,因为代码部分会重置图片大小)
在这里插入图片描述
(3)生成样本描述文件,方便读取

  • 将病斑图像与正常叶子图像信息写在同一TXT文件中,一行路径,一行标签
    在这里插入图片描述
    在这里插入图片描述
    怎么生成这个文件呐,用法术呀
    在这里插入图片描述
    3.训练SVM
    咋训练*~*
    当然是敲代码喽

(1)用了如此多的头文件和命名空间咱也不知道哪个没用,反正都用上没出错

#include"stdafx.h"//这个是VS一定要让我用的
#include"SVM_CucumberRotShiBie.h"//这个是我这个.cpp的.h
#include<iostream>//输入输出
#include<fstream>//文件流
//下面这几个你们试试哪个用不上告诉我呀
#include<opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/ml/ml.hpp>
//这个都用得上
using namespace std;
using namespace cv;
using namespace ml;

(2)然后定义了一些路径和关键数值

int DescriptorDim=900;//Hog训练结果维数,通过descriptors.size()得到
string address = "img_SVM/train/decribeTxt.txt";//描述文件路径
string address_result = "img_SVM/train/SVM_HOG.xml";//训练结果存储路径
string address_classification = "img_SVM/test/124.jpg";//测试图像路径

(3)这是我没什么用,但是又不能少的主函数

int cucumberRotShiBie() {
	//1.准备数据
	//2.生成描述文件
	//3.训练SVM
	trainingSVM();
	//4.测试
	SvmHogClassification();
	//完
	return 0;
}

(4)训练

int trainingSVM() {

	cout << "------------------准备数据---------------------" << endl;
	cout << "-----------------------------------------------" << endl;
	//读取描述文件内容
	vector<string> imgPath;//图像路径容器
	vector<int> imgCatg;//图像类别容器
	int nLine = 0;
	string buf;
	ifstream svm_data(address);
	if (!svm_data) { 
		int a = 0; cin >> a;
		return -1; 
	}
	unsigned long n;
	while (svm_data) {
		if (getline(svm_data,buf)) {
			nLine++;
			if (nLine % 2 == 0) {
				imgCatg.push_back(atoi(buf.c_str()));//图像类型
			}
			else {
				imgPath.push_back(buf);//图像路径
			}
		}
	}
	svm_data.close();

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//设置HOG检测器参数
	HOGDescriptor hog(Size(48, 48), Size(16, 16), Size(8, 8), Size(8, 8), 9);
	//训练数据、标志设置
	Mat data_mat, res_mat;
	int imgNum = nLine / 2;//图像数量,训练数据x维数
	Size data_mat_size(DescriptorDim, imgNum);//训练数据size    !!!size(列,行)!!!
	Size res_mat_size(1, imgNum);//标志size
	data_mat=Mat::zeros(data_mat_size, CV_32FC1);
	res_mat = Mat::zeros(res_mat_size, CV_32SC1);
	//统一图像尺寸的参数
	string s;//图像路径
	Size ssize(48, 48);
	Mat src;
	Mat dst(ssize, CV_8UC3);

	///////////////////////////////////////////////////////////////////////////////////
	cout << "-----------------处理HOG特征-------------------" << endl;
	cout << "-----------------------------------------------" << endl;
	for (int i = 0; i <imgNum; i++) {
		//获取图像
		s = imgPath[i].c_str();
		src = imread(s);
		if (src.empty()) {
			cout << "no image:" << s << endl;
			return -1;
		}
		cout << "处理:" << s << endl;
		//统一图像尺寸
		resize(src, dst,ssize);
		//存放HOG特征计算结果
		vector<float>descriptors;
		//计算HOG特征
		hog.compute(dst, descriptors, Size(1, 1),Size(0,0));
		//cout <<"size:"<< descriptors.size() << endl;//Hog特征维数
		//
		for (int j = 0;j<descriptors.size();j++) {
			data_mat.at<float>(i, j) = descriptors[j];
		}
		res_mat.at<float>(i, 0) = imgCatg[i];
	}
	/////////////////////////////////////////////////////////////////////////////////////
	cout << "-------------------训练SVM---------------------" << endl;
	cout << "-----------------------------------------------" << endl;
	//设置参数
	Ptr<SVM> svm = SVM::create();
	svm->setType(SVM::Types::C_SVC);
	svm->setKernel(SVM::KernelTypes::LINEAR);
	svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
	Ptr<TrainData>td = TrainData::create(data_mat, SampleTypes::ROW_SAMPLE, res_mat);
	svm->train(td);
	svm->save(address_result);
	cout << "完!" << endl;
	return 0;
}

(5)检测,输出的结果就是当前检测图像的标签

int SvmHogClassification() {

	//获取检测图像
	Mat src = imread(address_classification);
	if (src.empty()) {
		cout << "no image!" << endl;
		return -1;
	}
	//计算检测图像的HOG特征
	HOGDescriptor hog(Size(48, 48), Size(16, 16), Size(8, 8), Size(8, 8), 9);
	//统一图像尺寸的参数
	Size ssize(48, 48);
	Mat dst(ssize, CV_8UC3);
	//统一图像尺寸
	resize(src, dst, ssize);
	//存放HOG特征计算结果
	vector<float>descriptors;
	//计算HOG特征
	hog.compute(dst, descriptors, Size(1, 1), Size(0, 0));
	//转换计算结果格式
	Mat endImg = Mat::zeros(1, descriptors.size(), CV_32FC1);
	for (int i = 0; i < descriptors.size(); i++) {
		endImg.at<float>(0, i) = descriptors[i];
	}
	//SVM分类
	Ptr<SVM> svm = SVM::load(address_result);
	if (svm->empty()) {
		cout << "no load!" << endl;
		return -1;
	}
	float res = svm->predict(endImg);
	cout << res << endl;
	return 0;
}

4.总结
(1)敲线性不可分的官方代码时输出结果应该是那几个点被圈圈圈起来,但是那个圈却出现在原点附近
在这里插入图片描述
然后我就查啊查发现这不是BUG是什么我忘了
要改核函数这里

	Ptr<SVM> params=SVM::create();
	params->setType(SVM::C_SVC);
	params->setC(0.1);
	params->setKernel(SVM::POLY);//!!!!
	params->setDegree(1.0);//!!!!!
	params->setTermCriteria(TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6));

就好啦!
在这里插入图片描述
(2)我没有调参数,我没有调参数,我没有调参数
HOG的参数,,SVM的参数,,都没改
咱也不知道哪个数好,大家都说好,我就用了,待我那日调了参数,我再更新它
(3)训练的数据要有两及个以上的类型,不然它会应为你太过分就不干活啦,哈哈哈。

标签:HOG,svm,mat,OpenCV,SVM,size,data,Size
来源: https://blog.csdn.net/u014284965/article/details/100834594

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有