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

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)训练的数据要有两及个以上的类型,不然它会应为你太过分就不干活啦,哈哈哈。
(4)不学习可不行,没有源码,看完开头链接的代码也就不需要源码了
(5)叶子图片的话马路边的绿化带里有很多,200张照片用不了一个小时

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值