KNN算法识别数字

  • 一、KNN原理
    • 1.1 KNN原理介绍
    • 1.2 KNN的关键参数
  • 二、KNN算法识别手写数字
    • 2.1 训练过程代码详解
    • 2.2 预测分类的实现过程
  • 三、KNN算法识别印刷数字
    • 2.1 训练过程

一、KNN原理

1.1 KNN原理介绍

  KNN算法,即K最近邻算法,顾名思义其原理是当要预测一个新的值x的时候,根据离他最近的K个点大多属于什么类别来判断x属于哪个类别

zzzzMing -大数据技术-深入浅出KNN算法  K=3时,x最近的三个图形包括两个三角形、一个圆形,因为2>1,所以x更有可能是三角形。

  K=5时,x最近的五个图形包括两个三角形、三个圆形,因为3>2,所以x更有可能是圆形。

  同理类比到图像识别方面,使用KNN算法前我们需要有大量的训练样本,并且知道每个样本所属的类别。(例如大量的数字图片,并且知道每个图片代表数字几)。当我们要识别数字时,本质上就是在训练样本中找与要识别的图像最接近的K个样本,然后统计出K个样本中出现最多的数字是哪个,那就是要识别的数字。

1.2 KNN的关键参数

① 寻找多少最近邻样本 - K的选择

  K值决定着图像识别过程中,寻找的最近邻的图像个数,由上面的例子可以看出,选择不同的K,识别结果可能完全不同,因此K值是KNN算法中最关键的参数之一,它直接影响着模型的性能。

  K值如果过小,那么此时识别结果就会很受样本质量的影响。如果训练样本存在某些错误或噪音,而寻找最近邻样本时正好找到了这些项,那么识别结果一定是错的,而增大K值,多寻找样本,会有效降低样本噪音的影响。

  K值如果过大,假设K值等于训练样本数,那么无论要识别的图片是什么,识别结果都是样本中最多的那个类别。

  那么K值应该如何选择呢?理论上来说K值与识别准确率的关系是存在一个极值的,可以通过多次实验,根据结果选择一个最好的K值。(例如K=3时准确率72;K=5时准确率91;K=8时准确率81,那么选择K=5会是一个相对较好的选择)

② 如何判断“接近”程度 - 距离的计算
  距离计算函数一般使用曼哈顿距离或欧氏距离。

  曼哈顿距离就是样本特征每一个维度的差值之合。(对应于图像,就是两图像每个像素做差)

  欧式距离是样本特征在每一个维度上差值的平方和的根。

二、KNN算法识别手写数字

KNN算法识别手写数字的源程序 - 点此下载
注:只包括KNN算法部分,关于图片ROI区域截取请参考《一文详解opencv摄像头数字识别》

2.1 训练过程代码详解

  首先,我们要获得训练样本。OpenCV安装目录中给我们提供了手写数字的样本图片opencv\sources\samples\data\digits.png。这个图片中每个数字有5x100个样本,并且每个数字所占的像素均为20x20,因此可以从这个图片中提取我们需要的训练样本。

  我们按列裁剪样本图片,每裁剪一个样本,就将其添加到data中,并同时将对应的数字添加到lable中。这样一来,我们就获得了图片和数字一一对应的data和lable数据。

 Mat img = imread("E:/Program/OpenCV/vcworkspaces/knn_test/images/data/digits.png");Mat gray;cvtColor(img, gray, COLOR_BGR2GRAY);int b = 20;int m = gray.rows / b;   //原图为1000*2000int n = gray.cols / b;   //裁剪为5000个20*20的小图块Mat data, labels;   //特征矩阵for (int i = 0; i < n; i++){int offsetCol = i * b; //列上的偏移量for (int j = 0; j < m; j++){int offsetRow = j * b;  //行上的偏移量//截取20*20的小块Mat tmp;gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);//reshape  0:通道不变  其他数字,表示要设置的通道数//reshape  表示矩阵行数,如果设置为0,则表示保持原有行数不变,如果设置为其他数字,表示要设置的行数data.push_back(tmp.reshape(0, 1));  //序列化后放入特征矩阵labels.push_back((int)j / 5);  //对应的标注}}

  利用这个训练样本就可以创建KNN模型了。

  如果需要测试模型的识别准确度,可以从刚才获得的5000个样本中,选择前3000个样本作为训练数据,后2000个作为测试数据。用KNN模型计算测试数据的在样本中的识别正确情况。

 data.convertTo(data, CV_32F); //uchar型转换为cv_32fint samplesNum = data.rows;int trainNum = 500;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);model = KNearest::create();model->setDefaultK(K);model->setIsClassifier(true);model->train(tData);//预测分类double train_hr = 0, test_hr = 0;Mat response;// compute prediction error on train and test datafor (int i = 0; i < samplesNum; i++){Mat sample = data.row(i);float r = model->predict(sample);   //对所有行进行预测//预测结果与原结果相比,相等为1,不等为0r = std::abs(r - labels.at<int>(i)) <= FLT_EPSILON ? 1.f : 0.f;if (i < trainNum)train_hr += r;  //累积正确数elsetest_hr += r;}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.);

2.2 预测分类的实现过程

  训练样本制作完毕后,预测分类就非常简单了,将要识别的图像读取进来,进行二值化处理,然后调整大小到与样本图片一样大(20x20)。将处理好的图片push到test中,就可以直接使用刚才创建的KNN模型进行预测了。

    //预测分类Mat img = imread("E:/Program/OpenCV/vcworkspaces/knn_test/images/test/4.jpg");cvtColor(img, img, COLOR_BGR2GRAY);//threshold(src, src, 0, 255, CV_THRESH_OTSU);imshow("Image", img);resize(img, img, Size(20, 20));Mat test;test.push_back(img.reshape(0, 1));test.convertTo(test, CV_32F);int result = model->predict(test);cout << "识别数字:" << result << endl;

三、KNN算法识别印刷数字

KNN算法识别印刷数字的源程序 -点此下载

注:只包括KNN算法部分,关于图片ROI区域截取请参考《一文详解opencv摄像头数字识别》

2.1 训练过程

  识别印刷体数字与识别手写数字的原理相同,只是训练样本有区别。这里我制作了1000张不同字体的训练样本,加载方式例如:

 //训练结果不存在,重新训练int add_image_num = 1000;   //扩充训练数据的文件夹个数int filenum = 0;Mat data, labels;   //特征矩阵for (int i = 0; i < add_image_num; i++){Mat addimg = imread("E:/Program/OpenCV/vcworkspaces/knn_test/images/data/" + to_string(filenum) + ".jpg");cvtColor(addimg, addimg, COLOR_BGR2GRAY);//threshold(src, src, 0, 255, CV_THRESH_OTSU);resize(addimg, addimg, Size(20, 20));data.push_back(addimg.reshape(0, 1));  //序列化后放入特征矩阵labels.push_back((int)((filenum++) % 10));  //对应的标注}

  训练样本加载完毕后,使用与上面相同的方式创建KNN模型,然后进行预测识别即可。

【OpenCV/C++】KNN算法识别数字的实现原理与代码详解相关推荐

  1. 人脸识别SeetaFace2原理与代码详解

    人脸识别SeetaFace2原理与代码详解 前言 一.人脸识别步骤 二.SeetaFace2基本介绍 三.seetaFace2人脸注册.识别代码详解 3.1 人脸注册 3.1.1 人脸检测 3.1.2 ...

  2. BilSTM 实体识别_NLP-入门实体命名识别(NER)+Bilstm-CRF模型原理Pytorch代码详解——最全攻略

    最近在系统地接触学习NER,但是发现这方面的小帖子还比较零散.所以我把学习的记录放出来给大家作参考,其中汇聚了很多其他博主的知识,在本文中也放出了他们的原链.希望能够以这篇文章为载体,帮助其他跟我一样 ...

  3. BilSTM 实体识别_NLP入门实体命名识别(NER)+BilstmCRF模型原理Pytorch代码详解——最全攻略...

    来自 | 知乎   作者 | seven链接 | https://zhuanlan.zhihu.com/p/79552594编辑 | 机器学习算法与自然语言处理公众号本文仅作学术分享,如有侵权,请联系 ...

  4. 干货 | OpenCV看这篇就够了,9段代码详解图像变换基本操作

    作者 | 王天庆,长期从事分布式系统.数据科学与工程.人工智能等方面的研究与开发,在人脸识别方面有丰富的实践经验.现就职某世界100强企业的数据实验室,从事数据科学相关技术领域的预研工作. 来源 |  ...

  5. 读书笔记-深度学习入门之pytorch-第五章(含循环实现手写数字识别)(LSTM、GRU代码详解)

    目录 1.RNN优点:(记忆性) 2.循环神经网络结构与原理 3.LSTM(长短时记忆网络) 4.GRU 5.LSTM.RNN.GRU区别 6.收敛性问题 7.循环神经网络Pytorch实现 (1)R ...

  6. KNN算法原理和代码详解

    原理 有这样一条河流like that,河流的左边是rich 人家,河流的右边是poor 人家,这时新搬来一家小甲,这个算法是看小甲是有钱人家还是没钱人家. 要解决这个问题,那么就可以说立着他最近的几 ...

  7. 【MATLAB】Parzen窗与K近邻算法原理与代码详解

    文章目录 1.非参数估计原理 2.Parzen窗 2.1.算法原理 2.2.Matlab实现与参数探究 3.K近邻 3.1.算法原理 3.2.Matlab实现与参数探究 1.非参数估计原理 \qqua ...

  8. 高能干货:OpenCV看这篇就够了,9段代码详解图像变换基本操作

    导读:OpenCV是一个以BSD许可证开源的.跨平台的计算机视觉库.它提供了Python.C++.Java.Matlab等多种编程语言接口.它集成了很多计算机视觉算法,具有非常强大的功能,是计算机视觉 ...

  9. K均值(K-means)聚类算法原理与代码详解

    0. 算法原理: 上述过程简单描述: a: 初始数据 b: 选择质点 c: 根据质点划分 d: 求均值,更新质心点 e: 划分 f: 更新质心点 1. 代码实现: # K means 教程# 0. 引 ...

最新文章

  1. Python标准库threading模块Condition原理浅析
  2. 我十年学习编程的历史
  3. 下载python后怎样打开-下载python后如何启动
  4. Streaming的算法Reservoir Sampling
  5. Java – 2012年回顾和未来预测
  6. LeetCode 97. 交错字符串(DP)
  7. 12.12 带触发器按钮的输入框
  8. php fpm 平滑重启,nginx、php-fpm平滑重启和重载配置
  9. 自动服务器批量装机,PXE高效批量网络装机
  10. 6月第二周国内域名解析商Top10:万网份额突破21%
  11. android自定义View之曲线图
  12. android View使用shape作为背景不能指定单边圆角的xml
  13. NonEmpty和Hierarchize嵌套的bug
  14. MTK平台上电话黑名单功能总结
  15. 联想Y7000装双系统win10+Ubuntu16.04后在Ubuntu上Wifi被禁用的解决办法
  16. JS编写 简易网页音乐播放器
  17. 网站速度和性能测试工具
  18. 积分商城开发及小程序积分商城功能介绍
  19. MFC中关于char[]转换成LPCWSTR的问题
  20. 【XSY2808】董先生的休闲方案 组合数学

热门文章

  1. bzoj 4443: [Scoi2015]小凸玩矩阵(二分+二分匹配)
  2. opencv 图像基本操作 像素值的获取、图像大小、ROI、通道分割与合并等
  3. C++ STL vector容器的插入和删除
  4. [bug解决] Ubantu打不开Typora:typora error while loading shared libraries libXss.so.1
  5. [高光谱] 在开源项目Hyperspectral-Classification Pytorch中加入自己的网络
  6. c#软件操作-cmd命令全解
  7. Python:Numpy库中的invert()函数的用法
  8. A1136 | 字符串处理、大整数运算
  9. C#多线程之线程池篇1
  10. SQL2005安装及链接