早在大二时,导师做过一个花生品种识别的程序,但当时用于品种识别的特征是自定义特征;而我的当初的本科毕业设计则是基于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
时间: 2024-11-05 06:25:17