opencv 手写选择题阅卷 (三)训练分类器

opencv 手写选择题阅卷 (三)训练分类器

1,分类器选择:SVM

本来一开始用的KNN分类器,但这个分类器目前没有实现保存训练数据的功能,所以选择了SVN分类器;

2,样本图像的预处理和特征提取代码与识别代码中使用一样的代码.

3,训练时的输入数据主要为两个矩阵,一个矩阵保存所有样本的特征数据,每一行一个图像,另一个矩阵保存每个样本所属的类别,比如 1.0代表A,2.0代表B,0代表空白.

4,所有样本分别保存在5个文件夹中(一个是空白,四个字母ABCD),用批处理生成一个文本文件包括所有样本文件文件名和分类:

目前只使用了四个人书写的60个字母和几个空白样本,后期再增加更多人的更多样本,文本文件内容如下样式:

1 A\2016072316013018.png
1 A\2016072316013022.png
1 A\2016072316013026.png
2 B\2016072316010401.png
2 B\2016072316010405.png
2 B\2016072316010409.png

int n_img = 0;//每个字符多个个图片

    FILE * pf = fopen(listname,"r");
    if (pf == NULL){
        printf("没有发现样本列表文件;\n");
        return;
    }
    char line[1024];
    while (1){
        if (NULL == fgets(line, 1024, pf))
            break;
        if (strlen(line) == 0)
            continue;
        n_img++;
    }

    HOGDescriptor *hog = new HOGDescriptor(cvSize(32, 32), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
    int nw = hog->getDescriptorSize();
    CvMat * trainData = cvCreateMat(n_img, nw, CV_32FC1); 
    CvMat * trainClasses = cvCreateMat(n_img, 1, CV_32FC1);

    //每个样本都要提取特征,写入到训练矩阵
    char path[512] = "";
    strcpy(path, listname);
    int path_len = strlen(listname);
    for (int i = path_len; i > 0; i--){
        if (path[i] == '\\'){
            path[i+1] = '\0';
            break;
        }
    }
    fseek(pf, 0, SEEK_SET);
    int nItem = 0;//训练数据中的第N个
    while (1){
        if (NULL == fgets(line, 1024, pf))
            break;
        if (strlen(line) == 0)
            continue;

        char * str_lable = line;
        char * str_imgname = NULL;
        int line_len = strlen(line);
        for (int i = 0; i < line_len; i++)
        {
            if (line[i] == ' '){
                line[i] == '\0';
                str_imgname = line + i + 1;
                break;
            }
        }
        if (str_imgname == NULL)
            continue;

        char img_name[512] = "";
        strcpy(img_name, path);
        strcat(img_name, str_imgname);
        img_name[strlen(img_name) - 1] = '\0';

        IplImage* src = cvLoadImage(img_name, 0);
        if (src == NULL)
        {
            printf("打开样本图片出错:%s;\n", img_name);
            continue;
        }

        IplImage* train_img = cvCreateImage(cvSize(32, 32), 8, 1);
        preproc_img(src, train_img);

        vector<float> descriptors;//存放结果
        hog->compute(train_img, descriptors, Size(1, 1), Size(0, 0)); //Hog特征计算
        int n = 0;
        for (vector<float>::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++)
        {
            cvmSet(trainData, nItem, n, *iter);//存储HOG特征
            n++;
        }

        double val = strtod(str_lable, NULL);
        cvmSet(trainClasses, nItem, 0, val);

        cvReleaseImage(&src);
        cvReleaseImage(&train_img);

        nItem++;
    }
    if (nItem != n_img){
        printf("实际样本数据与列表中样本数据不同;\n");
    }
    fclose(pf);

    CvSVM svm;//新建一个SVM
    CvSVMParams param;//这里是SVM训练相关参数
    CvTermCriteria criteria;
    criteria = cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);
    param = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria);
    svm.train(trainData, trainClasses, NULL, NULL, param);//训练数据
    //保存训练好的分类器
    svm.save("HOG_SVM_DATA.xml");

    cvReleaseMat(&trainData);
    cvReleaseMat(&trainClasses);

}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值