【opencv】神经网络识别数字

本文参考了http://blog.csdn.net/qq_15947787/article/details/51385861
这位大神的文章,在此基础上稍作改进,可以跨平台运行。

程序在opencv2.4.9+VS2013环境下完美运行,能够实现数字0-9的识别

#include <iostream>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <stdio.h>
using namespace cv;
using namespace std;
#define TRAIN true    //是否进行训练,true表示重新训练,false表示读取xml文件中的ann模型

int main()
{
    //  const string fileform = "*.png";
    //  const string perfileReadPath ;

    const int sample_mun_perclass = 20;//训练字符每类数量
    const int class_mun = 10;//训练字符类数

    const int image_cols = 8;
    const int image_rows = 16;
    const string fileForm = ".txt";
    const string fileReadName = "D:/Opencv2.4.9/VS2013Project/myAnn/myAnn/myCharPic/";
    string fileReadPath;
    string txtName;
    char tmp[10];
    string ImgName;
    float trainingData[class_mun*sample_mun_perclass][image_rows*image_cols] = { { 0 } };//每一行一个训练样本
    float labels[class_mun*sample_mun_perclass][class_mun] = { { 0 } };//训练样本标签
    CvANN_MLP bp;
    //ifstream fin(txtName);//正样本图片的文件名列表

    if (TRAIN)
    {
        for (int i = 0; i<class_mun; ++i)//不同类
        {
            //读取每个类文件夹下所有图像
            sprintf(tmp, "%d", i);
            cout << "文件夹" << i << endl;
            txtName = tmp + fileForm;
            ifstream fin(txtName);//正样本图片的文件名列表
            for (int j = 1; j <= sample_mun_perclass; j++)
            {
                getline(fin, ImgName);
                cout << "处理:" << ImgName << endl;
                fileReadPath = fileReadName + tmp + "/" + ImgName;
                Mat srcImage = imread(fileReadPath, 0);//读取图片
                Mat resizeImage;
                Mat trainImage;
                Mat result;

                resize(srcImage, resizeImage, Size(image_cols, image_rows), (0, 0), (0, 0), CV_INTER_AREA);//使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现
                threshold(resizeImage, trainImage, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

                for (int k = 0; k<image_rows*image_cols; ++k)
                {
                    trainingData[i*sample_mun_perclass + (j - 1)][k] = (float)trainImage.data[k];
                    //trainingData[i*sample_mun_perclass+(j-1)][k] = (float)trainImage.at<unsigned char>((int)k/8,(int)k%8);//(float)train_image.data[k];
                    //cout<<trainingData[i*sample_mun_perclass+(j-1)][k] <<" "<< (float)trainImage.at<unsigned char>(k/8,k%8)<<endl;
                }

            } //如果设置读入的图片数量,则以设置的为准,如果图片不够,则读取文件夹下所有图片

        }

        // Set up training data Mat
        Mat trainingDataMat(class_mun*sample_mun_perclass, image_rows*image_cols, CV_32FC1, trainingData);
        cout << "trainingDataMat——OK!" << endl;

        // Set up label data 
        for (int i = 0; i <= class_mun - 1; ++i)
        {
            for (int j = 0; j <= sample_mun_perclass - 1; ++j)
            {
                for (int k = 0; k<class_mun; ++k)
                {
                    if (k == i)
                        labels[i*sample_mun_perclass + j][k] = 1;
                    else labels[i*sample_mun_perclass + j][k] = 0;
                }
            }
        }
        Mat labelsMat(class_mun*sample_mun_perclass, class_mun, CV_32FC1, labels);
        cout << "labelsMat:" << endl;
        cout << labelsMat << endl;
        cout << "labelsMat——OK!" << endl;

        //训练代码

        cout << "training start...." << endl;

        // Set up BPNetwork's parameters
        CvANN_MLP_TrainParams params;
        params.train_method = CvANN_MLP_TrainParams::BACKPROP;
        params.bp_dw_scale = 0.001;
        params.bp_moment_scale = 0.1;
        params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10000, 0.0001);  //设置结束条件
        //params.train_method=CvANN_MLP_TrainParams::RPROP;
        //params.rp_dw0 = 0.1;
        //params.rp_dw_plus = 1.2;
        //params.rp_dw_minus = 0.5;
        //params.rp_dw_min = FLT_EPSILON;
        //params.rp_dw_max = 50.;

        //Setup the BPNetwork
        Mat layerSizes = (Mat_<int>(1, 5) << image_rows*image_cols, 128, 128, 128, class_mun);
        bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM, 1.0, 1.0);//CvANN_MLP::SIGMOID_SYM
        //CvANN_MLP::GAUSSIAN
        //CvANN_MLP::IDENTITY
        cout << "training...." << endl;
        bp.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

        bp.save("../bpcharModel.xml"); //save classifier
        cout << "training finish...bpModel1.xml saved " << endl;
    }
    else //若TRAIN为false,从XML文件读取训练好的分类器
    {
        bp.load("../bpcharModel.xml");//从XML文件读取训练好的SVM模型
    }

    //测试神经网络
    cout << "测试:" << endl;
    Mat test_image = imread("test2.png", CV_LOAD_IMAGE_GRAYSCALE);
    Mat test_temp;
    resize(test_image, test_temp, Size(image_cols, image_rows), (0, 0), (0, 0), CV_INTER_AREA);//使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现
    threshold(test_temp, test_temp, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
    Mat_<float>sampleMat(1, image_rows*image_cols);
    for (int i = 0; i<image_rows*image_cols; ++i)
    {
        sampleMat.at<float>(0, i) = (float)test_temp.at<uchar>(i / 8, i % 8);
    }

    Mat responseMat;
    bp.predict(sampleMat, responseMat);
    Point maxLoc;
    double maxVal = 0;
    minMaxLoc(responseMat, NULL, &maxVal, NULL, &maxLoc);
    cout << "识别结果:" << maxLoc.x << "    相似度:" << maxVal * 100 << "%" << endl;
    imshow("test_image", test_image);
    waitKey(0);

    return 0;
}

完整的工程以上传百度云。链接:https://pan.baidu.com/s/1dFwDvPJ 密码:ehjb
希望对需要学习的小伙伴有用。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值