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;
}