OpenCV中的SVM

    #include "stdafx.h"
    #include <opencv2/opencv.hpp>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <math.h>
    #include <vector>
    #include <windows.h>
    #include <io.h>
    #include <time.h>

    using namespace cv;
    using namespace std;

    #define HORIZONTAL    1
    #define VERTICAL    0

    CvSVM svm;

    const char strCharacters[] = { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘,     ‘6‘, ‘7‘, ‘8‘, ‘9‘ };
    const int numCharacter = 10;

    const int numNeurons = 40;
    const int predictSize = 10;

    void generateRandom(int n, int test_num, int min, int max, vector<int>*mark_samples)
    {
        int range = max - min;
        int index = rand() % range + min;
        if (mark_samples->at(index) == 0)
        {
            mark_samples->at(index) = 1;
            n++;
        }

        if (n < test_num)
            generateRandom(n, test_num, min, max, mark_samples);

    }

    vector<string> getFiles(const string &folder,
        const bool all /* = true */) {
        vector<string> files;
        list<string> subfolders;
        subfolders.push_back(folder);

        while (!subfolders.empty()) {
            string current_folder(subfolders.back());

            if (*(current_folder.end() - 1) != ‘/‘) {
                current_folder.append("/*");
            }
            else {
                current_folder.append("*");
            }

            subfolders.pop_back();

            struct _finddata_t file_info;
            long file_handler = _findfirst(current_folder.c_str(), &file_info);

            while (file_handler != -1) {
                if (all &&
                    (!strcmp(file_info.name, ".") || !strcmp(file_info.name, ".."))) {
                    if (_findnext(file_handler, &file_info) != 0) break;
                    continue;
                }

                if (file_info.attrib & _A_SUBDIR) {
                    // it‘s a sub folder
                    if (all) {
                        // will search sub folder
                        string folder(current_folder);
                        folder.pop_back();
                        folder.append(file_info.name);

                        subfolders.push_back(folder.c_str());
                    }
                }
                else {
                    // it‘s a file
                    string file_path;
                    // current_folder.pop_back();
                    file_path.assign(current_folder.c_str()).pop_back();
                    file_path.append(file_info.name);

                    files.push_back(file_path);
                }

                if (_findnext(file_handler, &file_info) != 0) break;
            }  // while
            _findclose(file_handler);
        }

        return files;
    }

    void AppendText(string filename, string text)
    {
        fstream ftxt;
        ftxt.open(filename, ios::out | ios::app);
        if (ftxt.fail())
        {
            cout << "创建文件失败!" << endl;
            getchar();
        }
        ftxt << text << endl;
        ftxt.close();
    }

    // !获取垂直和水平方向直方图
    Mat ProjectedHistogram(Mat img, int t)
    {
        int sz = (t) ? img.rows : img.cols;
        Mat mhist = Mat::zeros(1, sz, CV_32F);

        for (int j = 0; j<sz; j++) {
            Mat data = (t) ? img.row(j) : img.col(j);
            mhist.at<float>(j) = countNonZero(data);    //统计这一行或一列中,非零元素的个数,并保存到mhist中
        }

        //Normalize histogram
        double min, max;
        minMaxLoc(mhist, &min, &max);

        if (max>0)
            mhist.convertTo(mhist, -1, 1.0f / max, 0);//用mhist直方图中的最大值,归一化直方图

        return mhist;
    }

    Mat features(Mat in, int sizeData)
    {

        Mat lowData;
        resize(in, lowData, Size(sizeData, sizeData));

        //Last 10 is the number of moments components
        int numCols =  lowData.cols*lowData.cols;
        //int numCols = vhist.cols + hhist.cols;
        Mat out = Mat::zeros(1, numCols, CV_32F);
        //Asign values to feature,ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量
        int j = 0;

        for (int x = 0; x<lowData.cols; x++)
        {
            for (int y = 0; y<lowData.rows; y++) {
                out.at<float>(j) = (float)lowData.at<unsigned char>(x, y);
                j++;
            }
        }
        //if(DEBUG)
        //  cout << out << "\n===========================================\n";
        return out;
    }

    Mat features2(Mat in, int sizeData)
    {
        //Histogram features

        Mat vhist = ProjectedHistogram(in, VERTICAL);
        Mat hhist = ProjectedHistogram(in, HORIZONTAL);
        //Low data feature
        Mat lowData;
        resize(in, lowData, Size(sizeData, sizeData));

        //Last 10 is the number of moments components
        int numCols = vhist.cols + hhist.cols + lowData.cols*lowData.cols;
        //int numCols = vhist.cols + hhist.cols;
        Mat out = Mat::zeros(1, numCols, CV_32F);
        //Asign values to feature,ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量
        int j = 0;
        for (int i = 0; i<vhist.cols; i++)
        {
            out.at<float>(j) = vhist.at<float>(i);
            j++;
        }
        for (int i = 0; i<hhist.cols; i++)
        {
            out.at<float>(j) = hhist.at<float>(i);
            j++;
        }
        for (int x = 0; x<lowData.cols; x++)
        {
            for (int y = 0; y<lowData.rows; y++) {
                out.at<float>(j) = (float)lowData.at<unsigned char>(x, y);
                j++;
            }
        }
        //if(DEBUG)
        //  cout << out << "\n===========================================\n";
        return out;
    }

    void Svm_Train(Mat TrainData, Mat classes, int sizeData)
    {
        CvTermCriteria criteria;
        criteria = cvTermCriteria(CV_TERMCRIT_EPS, 10000, FLT_EPSILON);
        CvSVMParams SVM_params;
        SVM_params = CvSVMParams(CvSVM::C_SVC, CvSVM::LINEAR, 0, 1, 0, 1, 0, 0, NULL, criteria);
        //SVM_params  = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, criteria);
        svm.train(TrainData, classes, Mat(), Mat(), SVM_params);
        /*svm.train_auto(TrainData, classes, cv::Mat(),
            cv::Mat(),
            SVM_params,
            10,
            CvSVM::get_default_grid(CvSVM::C),
            CvSVM::get_default_grid(CvSVM::GAMMA),
            CvSVM::get_default_grid(CvSVM::P),
            CvSVM::get_default_grid(CvSVM::NU),
            CvSVM::get_default_grid(CvSVM::COEF),
            CvSVM::get_default_grid(CvSVM::DEGREE),
            true);*/
        string file_path;
        stringstream ss(stringstream::in | stringstream::out);
        ss << "train/" << sizeData;
        file_path = ss.str();

        FileStorage fsTo(file_path, cv::FileStorage::WRITE);
        svm.write(*fsTo, "svm");

    }

    int recog(Mat features)
    {
        int result = -1;

        result = svm.predict(features);

        return result;
    }

    float SVM_test(Mat samples_set, Mat sample_labels)
    {
        int correctNum = 0;
        float accurate = 0;
        for (int i = 0; i < samples_set.rows; i++)
        {
            int result = recog(samples_set.row(i));
            if (result == sample_labels.at<int>(i))
                correctNum++;
        }
        accurate = (float)correctNum / samples_set.rows;
        return accurate;
    }

    int saveTrainData()
    {
        cout << "Begin saveTrainData" << endl;
        Mat classes;
        Mat trainingDataf5;
        Mat trainingDataf10;
        Mat trainingDataf15;
        Mat trainingDataf20;

        vector<int> trainingLabels;
        string path = "charSamples";

        for (int i = 0; i < numCharacter; i++)
        {
            cout << "Character: " << strCharacters[i] << "\n";
            stringstream ss(stringstream::in | stringstream::out);
            ss << path << "/" << strCharacters[i];

            auto files = getFiles(ss.str(), 1);

            int size = files.size();
            for (int j = 0; j < size; j++)
            {
                cout << files[j].c_str() << endl;
                Mat img = imread(files[j].c_str(), 0);
                Mat f5 =  features(img, 5);
                Mat f10 = features(img, 10);
                Mat f15 = features(img, 15);
                Mat f20 = features(img, 20);

                trainingDataf5.push_back(f5);
                trainingDataf10.push_back(f10);
                trainingDataf15.push_back(f15);
                trainingDataf20.push_back(f20);
                trainingLabels.push_back(i);            //每一幅字符图片所对应的字符类别索引下标
            }
        }

        trainingDataf5.convertTo(trainingDataf5, CV_32FC1);
        trainingDataf10.convertTo(trainingDataf10, CV_32FC1);
        trainingDataf15.convertTo(trainingDataf15, CV_32FC1);
        trainingDataf20.convertTo(trainingDataf20, CV_32FC1);
        Mat(trainingLabels).copyTo(classes);

        FileStorage fs("train/features_data.xml", FileStorage::WRITE);
        fs << "TrainingDataF5" << trainingDataf5;
        fs << "TrainingDataF10" << trainingDataf10;
        fs << "TrainingDataF15" << trainingDataf15;
        fs << "TrainingDataF20" << trainingDataf20;
        fs << "classes" << classes;
        fs.release();

        cout << "End saveTrainData" << endl;

        return 0;
    }

    void SVM_Cross_Train_and_Test(int Imagsize)
    {

        String training;
        Mat TrainingData;
        Mat Classes;

        FileStorage fs;
        fs.open("train/features_data.xml", FileStorage::READ);

        cout << "Begin to SVM_Cross_Train_and_Test " << endl;

        char *txt = new char[50];
        sprintf(txt, "交叉训练,特征维度%d,", 40 + Imagsize * Imagsize);
        AppendText("output.txt", txt);
        cout << txt << endl;
        stringstream ss(stringstream::in | stringstream::out);
        ss << "TrainingDataF" << Imagsize;
        training = ss.str();

        fs[training] >> TrainingData;
        fs["classes"] >> Classes;
        fs.release();

        float result = 0.0;

        srand(time(NULL));

        vector<int> markSample(TrainingData.rows, 0);

        generateRandom(0, 50, 0, TrainingData.rows - 1, &markSample);

        Mat train_set, train_labels;
        Mat sample_set, sample_labels;

        for (int i = 0; i < TrainingData.rows; i++)
        {
            if (markSample[i] == 1)
            {
                sample_set.push_back(TrainingData.row(i));
                sample_labels.push_back(Classes.row(i));
            }
            else
            {
                train_set.push_back(TrainingData.row(i));
                train_labels.push_back(Classes.row(i));
            }
        }

        Svm_Train(train_set, train_labels);

        result = SVM_test(sample_set, sample_labels);

        sprintf(txt, "正确率%f\n", result);
        cout << txt << endl;
        AppendText("output.txt", txt);

        cout << "End the SVM_Cross_Train_and_Test" << endl;

        cout << endl;

    }

    void SVM_saveModel(int sizeData)
    {
        FileStorage fs;
        fs.open("train/features_data.xml", FileStorage::READ);

        Mat TrainingData;
        Mat Classes;

        string training;
        if (1)
        {
            stringstream ss(stringstream::in | stringstream::out);
            ss << "TrainingDataF" << sizeData;
            training = ss.str();
        }

        fs[training] >> TrainingData;
        fs["classes"] >> Classes;

        cout << "Begin to saveModelChar predictSize:" << sizeData
            << endl;

        Svm_Train(TrainingData, Classes);

        cout << "End the saveModelChar" << endl;

        string model_name = "train/svm.xml";

        FileStorage fsTo(model_name, cv::FileStorage::WRITE);
        svm.write(*fsTo, "svm");
    }

    void test_img(const string& filename)
    {
        Mat src_img = imread(filename, 0);
        Mat feat = features(src_img, 10);
        int ret = svm.predict(feat);
        cout << ret << endl;
    }
    int main()
    {

        int DigitSize[4] = { 5, 10, 15, 20};
        cout << "To be begin." << endl;

        saveTrainData();

        for (int i = 0; i < 4; i++)
        {
            SVM_Cross_Train_and_Test(DigitSize[i]);
        }

        cout << "To be end." << endl;

        /*SVM_saveModel(10);
        svm.load("train/svm_auto_rbf.xml");
        test_img("91.jpg");
    */

        return 0;
    }
时间: 2024-11-08 17:59:05

OpenCV中的SVM的相关文章

OpenCV中的SVM参数优化

OpenCV中的SVM参数优化 标签: svm参数优化opencv SVMSVR参数优化CvSVMopencv CvSVM 2014-08-19 10:31 2995人阅读 评论(8) 收藏 举报  分类: 机器学习(11)  opencv(18)  版权声明:本文为博主原创文章,未经博主允许不得转载. SVM(支持向量机)是机器学习算法里用得最多的一种算法.SVM最常用的是用于分类,不过SVM也可以用于回归,我的实验中就是用SVM来实现SVR(支持向量回归). 对于功能这么强的算法,OpenC

opencv中的SVM图像分类(二)

opencv中的SVM图像分类(二) 标签: svm图像 2015-07-30 08:45 8296人阅读 评论(35) 收藏 举报  分类: [opencv应用](5)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 原创作品 转载请注明出http://blog.csdn.net/always2015/article/details/47107129 上一篇博文对图像分类理论部分做了比较详细的讲解,这一篇主要是对图像分类代码的实现进行分析.理论部分我们谈到了使用BOW

OpenCV中的SVM參数优化

SVM(支持向量机)是机器学习算法里用得最多的一种算法.SVM最经常使用的是用于分类,只是SVM也能够用于回归,我的实验中就是用SVM来实现SVR(支持向量回归). 对于功能这么强的算法,opencv中自然也是有集成好了,我们能够直接调用.OpenCV中的SVM算法是基于LibSVM软件包开发的,LibSVM是台湾大学林智仁(Lin Chih-Jen)等开发设计的一个简单.易于使用和高速有效的SVM模式识别与回归的软件包. 网上讲opencv中SVM使用的文章有非常多,但讲SVM參数优化的文章却

OpenCV 中使用SVM

分类器 分类器是一种计算机程序. 他的设计目标是在通过学习后,可自动将数据分到已知类别. 平面线性分类器 一个简单的分类问题,如图有一些圆圈和一些正方形,如何找一条最优的直线将他们分开? 我们可以找到很多种方法画出这条直线,但怎样的直线才是最优的呢? 距离样本太近的直线不是最优的,因为这样的直线对噪声敏感度高,泛化性较差. 因此我们的目标是找到一条直线,离最近的点距离最远. 怎么寻找距离最远的直线?枚举所有直线,然后计算其样本最小距离?这样显然不是一个好办法,这将产生大量的计算开销. 我们利用另

【OpenCV】opencv3.0中的SVM训练 mnist 手写字体识别

前言: SVM(支持向量机)一种训练分类器的学习方法 mnist 是一个手写字体图像数据库,训练样本有60000个,测试样本有10000个 LibSVM 一个常用的SVM框架 OpenCV3.0 中的ml包含了很多的ML框架接口,就试试了. 详细的OpenCV文档:http://docs.opencv.org/3.0-beta/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html mnist数据下载:http://yann.l

opencv中SVM的那些事

最近在搞人脸性别识别,用到了opencv中封装的SVM分类器,遇到了一些小问题,解决之后感觉对其理解更深一点了,总结下. 首先,理解下SVM得输入格式.SVM的train()函数主要包含两个输入数据:训练数据矩阵以及对应标签组成的矩阵.其中训练数据为行向量,标签矩阵为列向量.举个例子吧,比如在实验里一共用到300张图片作为训练数据,其中150张为正例样本,150张为负例样本,那么最终得到的训练数据矩阵大小应为150行n列,这里的n代表的就是每一张图片进行特征提取(包括下采样的方法)之后的特征维数

opencv中的 HOGDescriptor 类

其定义在  object.hpp中找到的: [cpp] view plain copy struct CV_EXPORTS_W HOGDescriptor { public: enum { L2Hys=0 }; enum { DEFAULT_NLEVELS=64 }; CV_WRAP HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8), cellSize(8,8), nbins(9), derivApertu

利用opencv的hog+svm实现细胞识别分类器

利用opencv的hog+svm实现细胞识别分类器 图像处理中的细胞识别和人脸识别可以这样来类比,图像中的一张张人脸就是一个个细胞. 模式识别的关键在于样本库的选取,识别率也只能在和样本库比较接近的环境下才能保证.主要工作是三部分一是特征提取,二是样本库的训练train,三是目标检测detect. 一.特征提取 特征提取采用的是HOG特征即HOG描述子,该特征在行人检测中效果非常好.而一般人脸识别采用的是haar特征,这在opencv中都有实现,并都给出了相应的分类器,效果都很不错. 首先采集了

OpenCV的HOG+SVM训练程序注意事项

行人训练:http://www.tuicool.com/articles/MvYfui 字符识别:http://www.haogongju.net/art/2328003 用OpenCV使用HOG特征进行SVM算法训练的大概流程是 1)设置训练样本集 需要两组数据,一组是数据的类别,一组是数据的向量信息. 2)设置SVM参数,参考<机器模式->libSVM之参数说明> 注意必须使用线性SVM进行训练,因为检测函数只支持线性检测!!! 3)使用HOGDescriptor计算hog特征 4)