码迷,mamicode.com
首页 > 其他好文 > 详细

基于SVM+HOG的花生品种识别

时间:2015-01-19 22:45:29      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

早在大二时,导师做过一个花生品种识别的程序,但当时用于品种识别的特征是自定义特征;而我的当初的本科毕业设计则是基于SVM + HOG的人脸识别;在后来的工作学习中,又用到了HOG特征,想着是不是之前的花生品种的识别也能用Hog特征进行识别;正所谓学以致用,也能巩固下刚刚所学的知识;

所谓的Hog特征与SVM网上资料一大堆,而且讲解得非常详细,在这里不在做过多的讲解;


本程序的开发环境,主要是依赖于VS2013 + OpenCV2.4.9,开发环境,请自行配置,那么,下面贴出代码,不足之处,请各位大侠不吝批评指正:

特征提取功能的实现:

	CvMat* dataMat = NULL;
	Book* book = xlCreateBook();
	Sheet* sheet = book->addSheet("Sheet1");

	for (int j = 1; j <= 13; ++ j)
	{
		CString strLoadPath = "SubImage\\";
		CString strFile;
		strFile.Format("s%d", j);
		strLoadPath = strLoadPath + strFile + "\\";

		for (int i = 1; i <= 45; ++i)
		{
			CString loadPath = strLoadPath;
			CString stri;
			stri.Format("%d.jpg", i);
			loadPath = loadPath + stri;

			IplImage* srcImage = cvLoadImage(loadPath);
			IplImage* grayImage = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_8U, 1);
			IplImage* hogImage = cvCreateImage(cvSize(96, 64), IPL_DEPTH_8U, 1);		//用于提取Hog特征的图像

			cvCvtColor(srcImage, grayImage, CV_RGB2GRAY);

			cvResize(grayImage, hogImage, CV_INTER_LINEAR);   //线性插值

			std::vector<float> vfDescriptors;
			//vfDescriptors.resize(hogImage->width * hogImage->height);
			cv::Ptr<cv::HOGDescriptor> hog = new cv::HOGDescriptor(cvSize(hogImage->width, hogImage->height), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
			hog->compute(hogImage, vfDescriptors, cv::Size(1, 1), cv::Size(0, 0));		//使用计算函数进行计算

			//CvMat* mat = cvCreateMat(45 * 13, vfDescriptors.size(), CV_32FC1);
			//cvZero(mat);

			int cols = 0;

			for (auto it = vfDescriptors.begin(); it != vfDescriptors.end(); ++it)
			{
				if (sheet)
				{
					sheet->writeNum(45 * (j-1) + (i - 1), cols++, *it);    //把Hog数据存储到Excel 中
				}
			}

			//释放内存
			cvReleaseImage(&srcImage);
			srcImage = NULL;
			cvReleaseImage(&grayImage);
			grayImage = NULL;
			cvReleaseImage(&hogImage);
			hogImage = NULL;

		}// 内层 for 循环

	}
	
	book->save("Hog.xls");
	book->release();

SVM训练的实现代码:

Book* book = xlCreateBook();

	if (book->load("Hog.xls"))
	{
		Sheet* sheet = book->getSheet(0);

		if (sheet)
		{

			CvMat* dataMat = cvCreateMat(sheet->lastRow(), sheet->lastCol(), CV_32FC1);		//存储导入的数据

			for (int i = 0; i < sheet->lastRow(); ++ i)
			{
				for (int j = 0; j < sheet->lastCol(); ++ j)
				{
					double temp = sheet->readNum(i, j);
					cvSetReal2D(dataMat, i, j, temp);
				}
			}
			
			MessageBox("数据导入完成");

			CvMat* lableMat = cvCreateMat(sheet->lastRow(), 1, CV_32FC1);
			cvZero(lableMat);

			for (int i = 0; i < 13; ++ i)
			{
				for (int j = 0; j < 45; ++ j)
				{
					cvSetReal2D(lableMat, i * 45 + j, 0, i + 1);
				}
			}

			CvSVM svm;
			CvSVMParams svmParams;						//向量机参数
			CvTermCriteria  svmCriteria;				//迭代中止条件
			svmCriteria = cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);

			svmParams = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, svmCriteria);

			//利用训练数据和确定的学习参数,进行SVM学习
			svm.train(dataMat, lableMat, NULL, NULL, svmParams);
			svm.save("svm.xml");

			//以下代码用于SVM识别
			CvMat* svmResult = cvCreateMat(sheet->lastRow(), 1, CV_32FC1);
			CvMat* svmRow = NULL;

			for (int i = 0; i < sheet->lastRow(); ++ i)
			{
				svmRow = cvCreateMat(1, sheet->lastCol(), CV_32FC1);

				for (int j = 0; j < sheet->lastCol(); ++ j)
				{
					float temp = cvGetReal2D(dataMat, i, j);
					cvSetReal2D(svmRow, 0, j, temp);
				}

				unsigned int ret = 0;
				ret = svm.predict(svmRow);
				cvSetReal2D(svmResult, i, 0, ret);

				cvReleaseMat(&svmRow);
				svmRow = NULL;
			}

			int nCount = 0;

			for (int i = 0; i < 13; ++i)
			{
				for (int j = 0; j < 45; ++ j)
				{
					int ret = cvGetReal2D(svmResult, i * 45 + j, 0);
					if (ret == (i + 1))
					{
						++nCount;
					}
				}
			}

			float recognize = 100 * nCount / 13 / 45;

			CString str;
			str.Format("SVM 识别率为: %f", recognize);
			str = str + "%";
			MessageBox(str);

		}
	}

测试功能的实现代码:

CvSVM svm;
	svm.load("svm.xml");

	CFileDialog dlg(TRUE, NULL, NULL, 0, "图片文件(*.jpg)|*.jpg||");
	if (dlg.DoModal() == IDOK)
	{
		IplImage* testImage = cvLoadImage(dlg.GetPathName());
		IplImage* grayImage = cvCreateImage(cvGetSize(testImage), IPL_DEPTH_8U, 1);
		IplImage* hogImage = cvCreateImage(cvSize(96, 64), IPL_DEPTH_8U, 1);

		cvCvtColor(testImage, grayImage, CV_RGB2GRAY);
		cvResize(grayImage, hogImage, CV_INTER_LINEAR);

		std::vector<float> vfDescriptors;
		//vfDescriptors.resize(hogImage->width * hogImage->height);
		cv::Ptr<cv::HOGDescriptor> hog = new cv::HOGDescriptor(cvSize(hogImage->width, hogImage->height), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
		hog->compute(hogImage, vfDescriptors, cv::Size(1, 1), cv::Size(0, 0));		//使用计算函数进行计算
	
		CvMat* mat = cvCreateMat(1, 256, CV_32FC1);

		int cols = 0;

		for (auto it = 0; it < 256; ++it)
		{
			cvSetReal2D(mat, 0, it, vfDescriptors[it]);
		}

	
		int  ret = svm.predict(mat);
		CString str;
		switch (ret)
		{
		case 1:
			str = "品种1:P12";
			break;
		case 2:
			str = "品种2:矮2";
			break;
		case 3:
			str = "品种3:花玉22";
			break;
		case 4:
			str = "品种4:花玉25";
			break;
		case 5:
			str = "品种5:冀花2号";
			break;
		case 6:
			str = "品种6:冀花4号";
			break;
		case 7:
			str = "品种7:冀花5号";
			break;
		case 8:
			str = "品种8:鲁花9号";
			break;
		case 9:
			str = "品种9:青花6号";
			break;
		case 10:
			str = "品种10:天府3号";
			break;
		case 11:
			str = "品种11:维花8号";
			break;
		case 12:
			str = "品种12:小白沙";
			break;
		case 13:
			str = "品种13:中农108";
			break;
		}
		AfxMessageBox(str);
		//cvReleaseMat(&mat);
	}//end if	

相关的程序代码,用于测试的图像样本及程序中用到的操作 Excel 的类,已经打包上传到CSDN,请自行下载:http://download.csdn.net/detail/lingtianyulong/8377461


基于SVM+HOG的花生品种识别

标签:

原文地址:http://blog.csdn.net/lingtianyulong/article/details/42882607

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!