OPENCV KNN 手寫數字辨識 ~ opencv249_knn_digital_number02[從訓練圖檔實現KNN手寫數字辨識]-把圖形資料從RGB變成32F的格式convertTo、把M*N的圖像變成一維數列reshape、KNN分類器CvKNearest

OPENCV KNN 手寫數字辨識 ~ opencv249_knn_digital_number02[從訓練圖檔實現KNN手寫數字辨識]-把圖形資料從RGB變成32F的格式convertTo、把M*N的圖像變成一維數列reshape、KNN分類器CvKNearest

OPENCV KNN 手寫數字辨識 ~ opencv249_knn_digital_number02[從訓練圖檔實現KNN手寫數字辨識]-把圖形資料從RGB變成32F的格式convertTo、把M*N的圖像變成一維數列reshape、KNN分類器CvKNearest


資料來源:

https://blog.csdn.net/chaipp0607/article/details/77966888
https://blog.csdn.net/akadiao/article/details/79243651
https://blog.csdn.net/akadiao/article/details/79236458


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

https://github.com/jash-git/CB_OpenCV249_ML

#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)
{
    int i;
    srand(time(NULL));
    return intstart+(rand()%intrange);
}
int main()
{
    char ad[128]={0};
    Mat traindata ,trainlabel;
    int k=5,testnum=0,truenum=0;
    //读取训练数据 4000张
    for (int i = 0; i < 10; i++)
    {
        for (int j =0;j<400;j++)
        {
             sprintf(ad, "data\\%d\\%d.jpg",i,j);
             Mat srcimage = imread(ad);
             /*
                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整除。
             */
             srcimage = srcimage.reshape(1,1);
             traindata.push_back(srcimage);//将元素添加到矩阵的底部。(在为mat增加一行的时候,用到push_back)
             trainlabel.push_back(i);//将元素添加到矩阵的底部。(在为mat增加一行的时候,用到push_back)
        }
    }


    traindata.convertTo(traindata,CV_32F);
    CvKNearest knn( traindata, trainlabel, cv::Mat(), false, k);


    /*
    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(400,(499-400));
    sprintf(ad, "data\\%d\\%d.jpg",digital,index);
    cout << "test image path : " << ad << endl;

    Mat testdata = imread(ad);
    Mat showdata=testdata.clone();

    testdata = testdata.reshape(1,1);
    testdata.convertTo(testdata,CV_32F);
    cv::Mat nearests( 1, k, CV_32F);
    int  response = knn.find_nearest(testdata,k,0,0,&nearests,0);

    if(digital==response)
    {
        cout << "test is " << digital << endl;
        cout << "ANS : "<< response << " is OK" << endl;
    }
    else
    {
        cout << "test is " << digital << endl;
        cout << "ANS : "<< response << " is faill" << endl;
    }

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

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

發表迴響

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