OPENCV ANN(類神經網路) 手寫數字辨識 (opencv249_ann_digital_number) ~ opencv249_ann_digital_number01-彩色轉灰階imread、改變圖像解析度resize、灰階轉二值化threshold、二維數據轉一維數據reshape、影像數據轉ML運算數據convertTo、類神經CvANN_MLP、取出ML運算結果minMaxLoc

OPENCV ANN(類神經網路) 手寫數字辨識 (opencv249_ann_digital_number) ~ opencv249_ann_digital_number01-彩色轉灰階imread、改變圖像解析度resize、灰階轉二值化threshold、二維數據轉一維數據reshape、影像數據轉ML運算數據convertTo、類神經CvANN_MLP、取出ML運算結果minMaxLoc

OPENCV ANN(類神經網路) 手寫數字辨識 (opencv249_ann_digital_number) ~ opencv249_ann_digital_number01-彩色轉灰階imread、改變圖像解析度resize、灰階轉二值化threshold、二維數據轉一維數據reshape、影像數據轉ML運算數據convertTo、類神經CvANN_MLP、取出ML運算結果minMaxLoc


資料來源:https://blog.csdn.net/cherrywish/article/details/78761411

https://blog.csdn.net/qq_15947787/article/details/51385861


GITHUB: https://github.com/jash-git/opencv249_ann_digital_number

opencv249_ann_digital_number01-彩色轉灰階imread、改變圖像解析度resize、灰階轉二值化threshold、二維數據轉一維數據reshape、影像數據轉ML運算數據convertTo、類神經CvANN_MLP、取出ML運算結果minMaxLoc

  目前訓練結果-128,128*2,10

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ml/ml.hpp>

#include <iostream>
#include <cstdio>
#include <cstdlib> //srand() ,rand() ,system()
#include <ctime>   //time()

#include <sys/timeb.h>
#if defined(WIN32)
    #define  TIMEB    _timeb
    #define  ftime    _ftime
    typedef __int64 TIME_T;
#else
    #define TIMEB timeb
    typedef long long TIME_T;
#endif

using namespace cv;
using namespace std;

void Pause()
{
    printf("Press Enter key to continue...");
    fgetc(stdin);
}
int Rand_M2N(int intstart,int intrange)
{
    srand(time(NULL));
    return intstart+(rand()%intrange);
}
int main()
{
    const int image_cols = 8;
	const int image_rows = 16;
    char ad[128]={0};
    Mat traindata ,trainlabel;
    //读取训练数据 4000张
    for (int i = 0; i < 10; i++)
    {
        for (int j =0;j<500;j++)
        {
             sprintf(ad, "data\\%d\\%d.jpg",i,j);
             Mat srcImage = imread(ad,0);
             Mat resizeImage;
             Mat trainImage;
             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);

             /*
                Mat::reshape( ) 
                只是在逻辑上改变矩阵的行列数或者通道数,没有任何的数据的复制,也不会增减任何数据,因此这是一个O(1)的操作,它要求矩阵是连续的。
                C++: Mat Mat::reshape(int cn, int rows=0 const)
                cn:目标通道数,如果是0则保持和原通道数一致;
                rows:目标行数,同上是0则保持不变;
                改变后的矩阵要满足 rows*cols*channels  跟原数组相等,所以如果原来矩阵是单通道3*3的,调用Reshape(0,2)是会报错的,因为3*3*1不能被2*1整除。
             */
             trainImage = trainImage.reshape(1,1);
             traindata.push_back(trainImage);//将元素添加到矩阵的底部。(在为mat增加一行的时候,用到push_back)

             float responses[10]={0,0,0,0,0,0,0,0,0,0};
             responses[i]=1;
             Mat responsesMat(1, 10, CV_32FC1, responses);
             trainlabel.push_back(responsesMat);//将元素添加到矩阵的底部。(在为mat增加一行的时候,用到push_back)
        }
    }

    traindata.convertTo(traindata,CV_32F);
    trainlabel.convertTo(trainlabel,CV_32F);

	CvANN_MLP_TrainParams params(
        cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 1000, 0.00001),    //终止条件
        CvANN_MLP_TrainParams::BACKPROP,    // BACKPROP算法
        0.1, 0.1);    //激活函数的两个参数
    //4层MLP,输入层有400个神经元,隐藏层01有400个神经元,隐藏层02有400个神经元,输出层有10个神经元
	Mat layerSizes = (Mat_<int>(1,3) << 128, 128*2, 10);

	CvANN_MLP bp;    //实例化MLP
    //创建MLP模型,选用的激励函数为对称SIGMOID函数
    bool bnload=true;
    if(!bnload)
    {
        bp.create(layerSizes,CvANN_MLP::SIGMOID_SYM);
        bool check=bp.train(traindata, trainlabel, Mat(),Mat(), params);  //训练MLP模型
        if(check==true)
        {
            bp.save("ann_param");
            cout << "train ok\n";
        }
    }
    else
    {
        bp.load("ann_param");
    }


    /*
    RNG rng;
    int digital=rng.uniform(0, 9);
    int index=rng.uniform(400, 499);
    */
    int digital=Rand_M2N(0,(9-0));
    int index=Rand_M2N(0,(499-0));
    sprintf(ad, "data\\%d\\%d.jpg",digital,index);
    cout << "test image path : " << ad << endl;

    Mat testdata = imread(ad,0);
    Mat showdata=testdata.clone();
    resize(testdata, testdata, Size(image_cols, image_rows), (0, 0), (0, 0), CV_INTER_AREA);
    threshold(testdata, testdata, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);


    testdata = testdata.reshape(1,1);
    testdata.convertTo(testdata,CV_32F);

    Mat p_output_01;
    bp.predict(testdata, p_output_01);
    cout << "output:" << endl << p_output_01 << endl << endl;

	Point maxLoc;
	double maxVal = 0;
	minMaxLoc(p_output_01, NULL, &maxVal, NULL, &maxLoc);
	cout << "ANS:" << maxLoc.x << "\t" << maxVal * 100 << "%" << endl;

    namedWindow(ad, CV_WINDOW_NORMAL);
    imshow(ad,showdata);

    waitKey(0);
    Pause();
    return 0;
}

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *