(OpenCV3.2.0)基于HOG特征的SVM训练与测试实例

来源:互联网 发布:网络教育本科学费 编辑:程序博客网 时间:2024/05/29 19:23

本人作为一个机器学习的小菜鸟,在学习相关知识的过程中,CSDN博客给了我很大的帮助,作为回馈,我也来写点博客为后来者铺路。微笑微笑微笑

注意:在程序前需要包含一些必要的OpenCV头文件,我是将这些头文件写在了CvHeadFiles.h文件之中


#include "CvHeadFiles.h"      
#include <iostream>   
#include <fstream>   
#include <string>   
#include <vector> 
using namespace cv;
using namespace cv::ml;
using namespace std;
int main(int argc, char** argv)
{
        //--------------准备训练数据--------------------
        //定义相关变量
        int ImgWidht = 24;
        int ImgHeight = 24;
        vector<string> img_path;
        vector<int> img_catg;
        int nLine = 0;
        string buf;
        int lab;
        ifstream svm_data("SVM_DATA.txt");  
        unsigned long n;
        //依次读入样本的名和标签
        for(;;)
        {
               nLine++;
               if (nLine % 2)
               {
                       svm_data >> buf;
                       if (buf == "end")
                              break;
                       img_path.push_back(buf);//图像路径  
               }
               else
               {
                       svm_data >> lab;
                       img_catg.push_back(lab);
               }
        }
        svm_data.close();//关闭文件   
        //定义相关变量
        Mat data_mat, res_mat;
        int nImgNum = (nLine-1)/2;            //读入样本数量    
        res_mat = Mat::zeros(nImgNum, 1, CV_32SC1);
        Mat src;
        Mat trainImg = Mat::zeros(ImgHeight, ImgWidht, CV_8UC3);  //需要分析的图片   
        //依次提取样本的HOG特征
        for (string::size_type i = 0; i != img_path.size(); i++)
        {
               //读入样本
               src = imread(img_path[i].c_str(), 1);  //依次读入样本图片
               cout << " processing " << img_path[i].c_str() << endl;
               resize(src, trainImg, cv::Size(ImgWidht, ImgHeight), 0, 0, INTER_CUBIC);   //将样本图片调整为标准大小
               
               //对样本提取HOG特征向量
               HOGDescriptor *hog = new HOGDescriptor(cvSize(ImgWidht, ImgHeight), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);  //具体意思见参考文章1,2      
               vector<float> descriptors;  //存放提取HOG特征向量的结果数组 
               hog->compute(trainImg, descriptors, Size(1, 1), Size(0, 0)); //对读入的样本图片提取HOG特征向量 
               if (i == 0)
               {
                       data_mat = Mat::zeros(nImgNum, descriptors.size(), CV_32FC1); //根据输入图片大小进行分配空间  
               }
               cout << "HOG dims: " << descriptors.size() << endl;
               //存储所提取的样本的HOG特征值
               n = 0;
               for (vector<float>::iterator iter = descriptors.begin();iter != descriptors.end();iter++)
               {
                       data_mat.at<float>(i, n) = *iter;
                       n++;
               }
               
               //存储样本的标签
               res_mat.at<int>(i, 0) = img_catg[i];
               cout << " end processing " << img_path[i].c_str() << " " << img_catg[i] << endl;
        }
        
        //----------------------------设置SVM参数---------------------------------
        cout << "\n------------------------------------------------------------\n";
        cout << "Starting training process" << endl;
        Ptr<SVM> svm = SVM::create();
        svm->setType(SVM::C_SVC);
        svm->setC(10);
        svm->setKernel(SVM::RBF);
        svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 10000, 1e-6));
        
        //-------------------------------训练SVM------------------------------------------      
        svm->train(data_mat, ROW_SAMPLE, res_mat);   //注意此处data_mat和res_mat的类型
        //利用训练数据和确定的学习参数,进行SVM学习      
        svm->save("SVM_DATA.xml");
        cout << "Finished training process" << endl;
        //--------------------------------检测样本---------------------------------------   
        //依次读入测试样本名
        vector<string> img_tst_path;
        ifstream img_tst("SVM_TEST.txt");
        for(;;)
        {
               img_tst >> buf;
               if (buf == "end")
                       break;
               img_tst_path.push_back(buf);
        }
        img_tst.close();
        //定义相关变量
        Mat test;
        int pos=0, neg=0,sum=0;
        char line[512];
        ofstream predict_txt("SVM_PREDICT.txt");
        for (string::size_type j = 0; j < img_tst_path.size(); j++)
        {
               //依次读入测试样本
               test = imread(img_tst_path[j].c_str(), 1);   //读入图像    
               resize(test, trainImg, cv::Size(ImgWidht, ImgHeight), 0, 0, INTER_CUBIC);   //要搞成同样的大小才可以检测到        
               
               //提取测试样本的HOG特征
               HOGDescriptor *hog = new HOGDescriptor(cvSize(ImgWidht, ImgHeight), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);  
               vector<float>descriptors;//结果数组      
               hog->compute(trainImg, descriptors, Size(1, 1), Size(0, 0)); //调用计算函数开始计算  
               cout << "The Detection Result:" << endl;
               cout << "HOG dims: " << descriptors.size() << endl;
               //存储所提取的特征
               Mat SVMtrainMat = Mat::zeros(1, descriptors.size(), CV_32FC1);
               n = 0;
               for (vector<float>::iterator iter = descriptors.begin();iter != descriptors.end();iter++)
               {
                       SVMtrainMat.at<float>(0, n) = *iter;
                       n++;
               }
               //对提取的特征进行检验
               int ret = svm->predict(SVMtrainMat);
               if (ret == 1)
                       pos++;
               else
                       neg++;
               std::sprintf(line, "%s %d\r\n", img_tst_path[j].c_str(), ret);
               printf("%s %d\r\n", img_tst_path[j].c_str(), ret);
               //getchar();
               predict_txt << line;
        }
        sum = neg + pos;
        cout << "neg=" << neg << "\n";
        cout << "pos=" << pos << "\n";
        cout << "sum=" << sum << "\n";
        predict_txt.close();
        system("pause");
        return 0;
}


原创粉丝点击