简单HOG+SVM mnist手写数字分类

使用工具 :VS2013 + OpenCV 3.1

数据集:minst

训练数据:60000张  测试数据:10000张  输出模型:HOG_SVM_DATA.xml

数据准备

train-images-idx3-ubyte.gz:  training set images (9912422 bytes) 
train-labels-idx1-ubyte.gz:  training set labels (28881 bytes) 
t10k-images-idx3-ubyte.gz:   test set images (1648877 bytes) 
t10k-labels-idx1-ubyte.gz:   test set labels (4542 bytes)

首先我们利用matlab将数据转换成 .bmp 图片格式

fid_image=fopen(‘train-images.idx3-ubyte‘,‘r‘);
fid_label=fopen(‘train-labels.idx1-ubyte‘,‘r‘);
% Read the first 16 Bytes
magicnumber=fread(fid_image,4);
size=fread(fid_image,4);
row=fread(fid_image,4);
col=fread(fid_image,4);
% Read the first 8 Bytes
extra=fread(fid_label,8);
% Read labels related to images
imageIndex=fread(fid_label);
Num=length(imageIndex);
% Count repeat times of 0 to 9
cnt=zeros(1,10);
for k=1:Num
    image=fread(fid_image,[max(row),max(col)]);     % Get image data
    val=imageIndex(k);      % Get value of image
    for i=0:9
        if val==i
            cnt(val+1)=cnt(val+1)+1;
        end
    end
    if cnt(val+1)<10
        str=[num2str(val),‘_000‘,num2str(cnt(val+1)),‘.bmp‘];
    elseif cnt(val+1)<100
        str=[num2str(val),‘_00‘,num2str(cnt(val+1)),‘.bmp‘];
    elseif cnt(val+1)<1000
        str=[num2str(val),‘_0‘,num2str(cnt(val+1)),‘.bmp‘];
    else
        str=[num2str(val),‘_‘,num2str(cnt(val+1)),‘.bmp‘];
    end
    imwrite(image‘,str);
end
fclose(fid_image);
fclose(fid_label);

然后使用cmd指令写入图片路径: dir /b/s/p/w *.bmp > num.txt  添加标签,如下图

然后打乱样本顺序。

训练

int main0()
{
    vector<string> img_path;//输入文件名变量
    vector<int> img_catg;
    int nLine = 0;
    string line;
    size_t pos;
    ifstream svm_data("./train-images/random.txt");//训练样本图片的路径都写在这个txt文件中,使用bat批处理文件可以得到这个txt文件
    unsigned long n;
    while (svm_data)//将训练样本文件依次读取进来
    {
        if (getline(svm_data, line))
        {
            nLine++;
            pos = line.find_last_of(‘ ‘);
            img_path.push_back(line.substr(0, pos));//图像路径
            img_catg.push_back(atoi(line.substr(pos + 1).c_str()));//atoi将字符串转换成整型,标志(0,1,2,...,9),注意这里至少要有两个类别,否则会出错
        }
    }

    svm_data.close();//关闭文件
    int nImgNum = nLine; //nImgNum是样本数量,只有文本行数的一半,另一半是标签
    cv::Mat data_mat(nImgNum, 324, CV_32FC1);//第二个参数,即矩阵的列是由下面的descriptors的大小决定的,可以由descriptors.size()得到,且对于不同大小的输入训练图片,这个值是不同的
    data_mat.setTo(cv::Scalar(0));
    //类型矩阵,存储每个样本的类型标志
    cv::Mat res_mat(nImgNum, 1, CV_32S);
    res_mat.setTo(cv::Scalar(0));
    cv::Mat src;
    cv::Mat trainImg(cv::Size(28, 28), 8, 3);//需要分析的图片,这里默认设定图片是28*28大小,所以上面定义了324,如果要更改图片大小,可以先用debug查看一下descriptors是多少,然后设定好再运行      

    //处理HOG特征
    for (string::size_type i = 0; i != img_path.size(); i++)
    {
        src = cv::imread(img_path[i].c_str(), 1);
        if (src.data == NULL)//if (src == NULL)
        {
            cout << " can not load the image: " << img_path[i].c_str() << endl;
            continue;
        }

        //cout << " 处理: " << img_path[i].c_str() << endl;

        cv::resize(src, trainImg, trainImg.size());
        cv::HOGDescriptor *hog = new cv::HOGDescriptor(cv::Size(28, 28), cv::Size(14, 14), cv::Size(7, 7), cv::Size(7, 7), 9);
        vector<float>descriptors;//存放结果
        hog->compute(trainImg, descriptors, cv::Size(1, 1), cv::Size(0, 0)); //Hog特征计算
        //cout << "HOG dims: " << descriptors.size() << endl;
        n = 0;
        for (vector<float>::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++)
        {
            //cvmSet(data_mat, i, n, *iter);
            data_mat.at<float>(i, n) = *iter;//存储HOG特征
            n++;
        }
        //cvmSet(res_mat, i, 0, img_catg[i]);
        res_mat.at<int>(i, 0) = img_catg[i];
        //cout << " 处理完毕: " << img_path[i].c_str() << " " << img_catg[i] << endl;
    }
    cout << "computed features!" << endl;

    cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();//新建一个SVM
    svm->setType(cv::ml::SVM::C_SVC);
    svm->setKernel(cv::ml::SVM::LINEAR);
    svm->setC(1);
    //-------------------不使用参数优化-------------------------//
    svm->setTermCriteria(cv::TermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON));
    svm->train(data_mat, cv::ml::ROW_SAMPLE, res_mat);//训练数据
    //-------------------参数优化-------------------------//
    //svm->setTermCriteria = cv::TermCriteria(cv::TermCriteria::MAX_ITER, (int)1e7, 1e-6);
    //cv::Ptr<cv::ml::TrainData> td = cv::ml::TrainData::create(data_mat, cv::ml::ROW_SAMPLE, res_mat);
    //svm->trainAuto(td, 10);

    //保存训练好的分类器
    svm->save("HOG_SVM_DATA.xml");
    cout << "saved model!" << endl;
    //检测样本
    cv::Mat test;//IplImage *test;
    char result[512];
    vector<string> img_test_path;
    vector<int> img_test_catg;
    int coorect = 0;
    ifstream img_tst("./test-images/random.txt");  //加载需要预测的图片集合,这个文本里存放的是图片全路径,不要标签
    while (img_tst)
    {
        if (getline(img_tst, line))
        {
            pos = line.find_last_of(‘ ‘);
            img_test_catg.push_back(atoi(line.substr(pos + 1).c_str()));//atoi将字符串转换成整型,标志(0,1,2,...,9),注意这里至少要有两个类别,否则会出错
            img_test_path.push_back(line.substr(0, pos));//图像路径
        }
    }
    img_tst.close();

    ofstream predict_txt("SVM_PREDICT.txt");//把预测结果存储在这个文本中
    for (string::size_type j = 0; j != img_test_path.size(); j++)//依次遍历所有的待检测图片
    {
        test = cv::imread(img_test_path[j].c_str(), 1);
        if (test.data == NULL)//test == NULL
        {
            cout << " can not load the image: " << img_test_path[j].c_str() << endl;
            continue;
        }
        cv::Mat trainTempImg(cv::Size(28, 28), 8, 3);
        trainTempImg.setTo(cv::Scalar(0));
        cv::resize(test, trainTempImg, trainTempImg.size());
        cv::HOGDescriptor *hog = new cv::HOGDescriptor(cv::Size(28, 28), cv::Size(14, 14), cv::Size(7, 7), cv::Size(7, 7), 9);
        vector<float>descriptors;//结果数组
        hog->compute(trainTempImg, descriptors, cv::Size(1, 1), cv::Size(0, 0));
        //cout << "HOG dims: " << descriptors.size() << endl;
        cv::Mat SVMtrainMat(1, descriptors.size(), CV_32FC1);
        int 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 == img_test_catg[j])
            coorect++;
        sprintf(result, "%s  %d\r\n", img_test_path[j].c_str(), ret);
        predict_txt << result;  //输出检测结果到文本
    }
    predict_txt.close();
    cout << coorect*100 / img_test_path.size() << "%" << endl;
    return 0;
}

测试

int main(int argc, char* argv[])
{
    cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
    svm = cv::ml::SVM::load("HOG_SVM_DATA.xml");;//加载训练好的xml文件,这里训练的是10K个手写数字
    //检测样本
    cv::Mat test;
    char result[300]; //存放预测结果
    test = cv::imread("6.bmp", 1); //待预测图片,用系统自带的画图工具随便手写
    if (!test.data)
    {
        MessageBox(NULL, TEXT("待预测图像不存在!"), TEXT("提示"), MB_ICONWARNING);
        return -1;
    }
    cv::Mat trainTempImg(cv::Size(28, 28), 8, 3);
    trainTempImg.setTo(cv::Scalar(0));
    cv::resize(test, trainTempImg, trainTempImg.size());
    cv::HOGDescriptor *hog = new cv::HOGDescriptor(cv::Size(28, 28), cv::Size(14, 14), cv::Size(7, 7), cv::Size(7, 7), 9);
    vector<float>descriptors;//结果数组
    hog->compute(trainTempImg, descriptors, cv::Size(1, 1), cv::Size(0, 0));
    //cout << "HOG dims: " << descriptors.size() << endl;
    cv::Mat SVMtrainMat(1, descriptors.size(), CV_32FC1);
    int 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);//检测结果
    sprintf(result, "%d\r\n", ret);
    cv::namedWindow("dst", 0);
    cv::imshow("dst", test);
    MessageBox(NULL, result, TEXT("预测结果"), MB_OK);
    return 0;
}
时间: 2024-10-17 01:32:02

简单HOG+SVM mnist手写数字分类的相关文章

MNIST手写数字分类simple版(03-2)

simple版本nn模型 训练手写数字处理 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #载入数据集 mnist=input_data.read_data_sets("MNIST_data", one_hot=True) #每个批次的大小 batch_size=100 #计算一共有多少批次 n_batch=mnist.train.num_examples // ba

Tensorflow实践 mnist手写数字识别

minst数据集                                         tensorflow的文档中就自带了mnist手写数字识别的例子,是一个很经典也比较简单的入门tensorflow的例子,非常值得自己动手亲自实践一下.由于我用的不是tensorflow中自带的mnist数据集,而是从kaggle的网站下载下来的,数据集有些不太一样,所以直接按照tensorflow官方文档上的参数训练的话还是踩了一些坑,特此记录. 首先从kaggle网站下载mnist数据集,一份是

基于MNIST手写数字数据集的数字识别小程序

30行代码奉上!(MNIST手写数字的识别,识别率大约在91%,简单尝试的一个程序,小玩具而已) 1 import tensorflow.examples.tutorials.mnist.input_data as input_data 2 import tensorflow as tf 3 mnist = input_data.read_data_sets('/temp/', one_hot=True) 4 5 #设置 6 x = tf.placeholder(tf.float32,[None

tensorflow 基础学习五:MNIST手写数字识别

MNIST数据集介绍: from tensorflow.examples.tutorials.mnist import input_data # 载入MNIST数据集,如果指定地址下没有已经下载好的数据,tensorflow会自动下载数据 mnist=input_data.read_data_sets('.',one_hot=True) # 打印 Training data size:55000. print("Training data size: {}".format(mnist.

MNIST手写数字数据库

手写数字库很容易建立,但是总会很浪费时间.Google实验室的Corinna Cortes和纽约大学柯朗研究所的Yann LeCun建有一个手写数字数据库,训练库有60,000张手写数字图像,测试库有10,000张. 请访问原站 http://yann.lecun.com/exdb/mnist/ 该数据库在一个文件中包含了所有图像,使用起来有所不便.如果我把每个图像分别保存,成了图像各自独立的数据库. 并在Google Code中托管. 如果你有需要,欢迎在此下载: http://yann.le

Pytorch入门实战一:LeNet神经网络实现 MNIST手写数字识别

记得第一次接触手写数字识别数据集还在学习TensorFlow,各种sess.run(),头都绕晕了.自从接触pytorch以来,一直想写点什么.曾经在2017年5月,Andrej Karpathy发表的一片Twitter,调侃道:l've been using PyTorch a few months now, l've never felt better, l've more energy.My skin is clearer. My eye sight has improved.确实,使用p

MNIST手写数字图片识别(线性回归、CNN方法的手工及框架实现)(未完待续)

0-Background 作为Deep Learning中的Hello World 项目无论如何都要做一遍的. 代码地址:Github 练习过程中将持续更新blog及代码. 第一次写博客,很多地方可能语言组织不清,请多多提出意见..谢谢~ 0.1 背景知识: Linear regression CNN LeNet-5 AlexNet ResNet VGG 各种regularization方式 0.2 Catalog 1-Prepare 2-MNIST 3-LinearRegression 1-P

简单的神经网络算法-手写数字识别

本文通过BP神经网络实现一个简单的手写识别系统. 一.基础知识 1环境 python2.7 需要numpy等库 可利用sudo apt-get install python-安装 2神经网络原理 http://www.hankcs.com/ml/back-propagation-neural-network.html 讲的特别清楚,本实验过程中涉及矩阵运算都用numpy库的函数 3.js的基础知识 http://www.w3school.com.cn/tags/html_ref_canvas.a

Tensorflow之MNIST手写数字识别:分类问题(2)

整体代码: #数据读取 import tensorflow as tf import matplotlib.pyplot as plt import numpy as np from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/",one_hot=True) #定义待输入数据的占位符 #mnist中每张照片共有28*28=784个像