今天来介绍一下KNN+HOG手写体数字识别,首先贴出图片,这是opencv自带的一张图片,
E:\opencv\opencv\sources\samples\data,在此文件夹里,我们会发现一张手写体的图片
之前单纯用像素点训练,他的准确率是这样的
发现准确率有点低,于是我们改用KNN+HOG来进行训练,可以看到识别数字的准确率提高了很多
接下来贴出代码
#include<opencv2\opencv.hpp> #include<iostream> using namespace std; using namespace cv; using namespace cv::ml; int main() { Mat img = imread("digits.png"); Mat gray; cvtColor(img, gray, CV_BGR2GRAY); int b = 20; int rows = gray.rows / b; //原图为1000*2000 int cols = gray.cols / b; //裁剪为5000个20*20的小图块 cout << "rows :" << rows << endl; cout << "cols :" << cols << endl; Mat data(5000, 576, CV_32FC1); Mat labels; //特征矩阵 //创建HOG HOGDescriptor detector(Size(20, 20), Size(8, 8), Size(4, 4), Size(4, 4), 9); vector<float> descriptor; for (int col = 0; col < cols; col++) { int offsetCol = col*b; //列上的偏移量 for (int row = 0; row < rows; row++) { int offsetRow = row*b; //行上的偏移量 //截取20*20的小块 Mat tmp; gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp); imshow("t", tmp); detector.compute(tmp, descriptor); for (int k = 0;k < descriptor.size();k++) { data.at<float>(col*rows + row, k) = descriptor[k]; } labels.push_back((int)row / 5); //对应的标注 } } data.convertTo(data, CV_32F); //uchar型转换为cv_32f int samplesNum = data.rows; cout << "samplesNum :" <<samplesNum; int trainNum = 3000; Mat trainData, trainLabels; trainData = data(Range(0, trainNum), Range::all()); //前3000个样本为训练数据 trainLabels = labels(Range(0, trainNum), Range::all()); //使用KNN算法 int K = 5; Ptr<TrainData> tData = TrainData::create(trainData, ROW_SAMPLE, trainLabels); Ptr<KNearest> model = KNearest::create(); //Ptr<KNearest> model = StatModel::load<KNearest>("KNN.xml"); model->setDefaultK(K); model->setIsClassifier(true); model->train(tData); model->save("KNN+HOG.xml"); //预测分类 double train_hr = 0, test_hr = 0; Mat response; // compute prediction error on train and test data for (int i = 0; i < samplesNum; i++) { Mat sample = data.row(i); float r = model->predict(sample); //对所有行进行预测 //预测结果与原结果相比,相等为1,不等为0 r = std::abs(r - labels.at<int>(i)) <= FLT_EPSILON ? 1.f : 0.f; if (i < trainNum) train_hr += r; //累积正确数 else test_hr += r; } cout << "train_hr :" << train_hr << endl << "test_hr :" << test_hr << endl; test_hr /= samplesNum - trainNum; train_hr = trainNum > 0 ? train_hr / trainNum : 1.; printf("accuracy: train = %.1f%%, test = %.1f%%\n", train_hr*100., test_hr*100.); waitKey(0); return 0; }
然后就就会发现工程目录下生成了KNN+HOG.xml的文件
扫描二维码关注公众号,回复:
997586 查看本文章
然后就用Algorithm类的load方法加载图片,进行手写体图片的预测了
识别有误差主要还是训练集的问题,可以在该基础上不断添加数据集进行训练,成功率会更高。