手写数字digits分类,这可是深度学习算法的入门练习。而且还有专门的手写数字MINIST库。opencv提供了一张手写数字图片给我们,先来看看

这是一张密密麻麻的手写数字图:图片大小为1000*2000,有0-9的10个数字,每5行为一个数字,总共50行,共有5000个手写数字。在opencv3.0版本中,图片存放位置为

/opencv/sources/samples/data/digits.png

我们首先要做的,就是把这5000个手写数字,一个个截取出来,每个数字块大小为20*20。直接将每个小图块进行序列化,因此最终得到一个5000*400的特征矩阵。样本数为5000,维度为400维。取其中前3000个样本进行训练。

注意:截取的时候,是按列截取。不然取前3000个样本进行训练就会出现后几个数字训练不到。

具体代码:

#include "stdafx.h"
#include "opencv2\opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml; int main()
{
Mat img = imread("E:/opencv/opencv/sources/samples/data/digits.png");
Mat gray;
cvtColor(img, gray, CV_BGR2GRAY);
int b = ;
int m = gray.rows / b; //原图为1000*2000
int n = gray.cols / b; //裁剪为5000个20*20的小图块
Mat data,labels; //特征矩阵
for (int i = ; i < n; i++)
{
int offsetCol = i*b; //列上的偏移量
for (int j = ; j < m; j++)
{
int offsetRow = j*b; //行上的偏移量
//截取20*20的小块
Mat tmp;
gray(Range(offsetRow, offsetRow + b), Range(offsetCol, offsetCol + b)).copyTo(tmp);
data.push_back(tmp.reshape(,)); //序列化后放入特征矩阵
labels.push_back((int)j / ); //对应的标注
} }
data.convertTo(data, CV_32F); //uchar型转换为cv_32f
int samplesNum = data.rows;
int trainNum = ;
Mat trainData, trainLabels;
trainData = data(Range(, trainNum), Range::all()); //前3000个样本为训练数据
trainLabels = labels(Range(, trainNum), Range::all()); //使用KNN算法
int K = ;
Ptr<TrainData> tData = TrainData::create(trainData, ROW_SAMPLE, trainLabels);
Ptr<KNearest> model = KNearest::create();
model->setDefaultK(K);
model->setIsClassifier(true);
model->train(tData); //预测分类
double train_hr = , test_hr = ;
Mat response;
// compute prediction error on train and test data
for (int i = ; 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 ? .f : .f; if (i < trainNum)
train_hr += r; //累积正确数
else
test_hr += r;
} test_hr /= samplesNum - trainNum;
train_hr = trainNum > ? train_hr / trainNum : .; printf("accuracy: train = %.1f%%, test = %.1f%%\n",
train_hr*., test_hr*.);
waitKey();
return ;
}

根据经验,利用最近邻算法对手写数字进行分类,会有很高的精度,因此在本文中我们采用的是knn算法。

最终结果:

训练精度为95.9%, 测试精度为92.6%。如果对手写数字识别准确率达不到90%以上,就没有什么实际作用了。如果调整训练样本数,这个精度应该会有所改变。

在opencv3中实现机器学习算法之:利用最近邻算法(knn)实现手写数字分类的更多相关文章

  1. 在opencv3中实现机器学习之:利用逻辑斯谛回归(logistic regression)分类

    logistic regression,注意这个单词logistic ,并不是逻辑(logic)的意思,音译过来应该是逻辑斯谛回归,或者直接叫logistic回归,并不是什么逻辑回归.大部分人都叫成逻 ...

  2. 吴裕雄--天生自然python机器学习实战:K-NN算法约会网站好友喜好预测以及手写数字预测分类实验

    实验设备与软件环境 硬件环境:内存ddr3 4G及以上的x86架构主机一部 系统环境:windows 软件环境:Anaconda2(64位),python3.5,jupyter 内核版本:window ...

  3. TensorFlow.NET机器学习入门【5】采用神经网络实现手写数字识别(MNIST)

    从这篇文章开始,终于要干点正儿八经的工作了,前面都是准备工作.这次我们要解决机器学习的经典问题,MNIST手写数字识别. 首先介绍一下数据集.请首先解压:TF_Net\Asset\mnist_png. ...

  4. 在opencv3中实现机器学习之:利用svm(支持向量机)分类

    svm分类算法在opencv3中有了很大的变动,取消了CvSVMParams这个类,因此在参数设定上会有些改变. opencv中的svm分类代码,来源于libsvm. #include "s ...

  5. 在opencv3中实现机器学习之:利用正态贝叶斯分类

    opencv3.0版本中,实现正态贝叶斯分类器(Normal Bayes Classifier)分类实例 #include "stdafx.h" #include "op ...

  6. 在opencv3中的机器学习算法

    在opencv3.0中,提供了一个ml.cpp的文件,这里面全是机器学习的算法,共提供了这么几种: 1.正态贝叶斯:normal Bayessian classifier    我已在另外一篇博文中介 ...

  7. 机器学习(二)-kNN手写数字识别

    一.kNN算法是机器学习的入门算法,其中不涉及训练,主要思想是计算待测点和参照点的距离,选取距离较近的参照点的类别作为待测点的的类别. 1,距离可以是欧式距离,夹角余弦距离等等. 2,k值不能选择太大 ...

  8. 手写数字识别的k-近邻算法实现

    (本文为原创,请勿在未经允许的情况下转载) 前言 手写字符识别是机器学习的入门问题,k-近邻算法(kNN算法)是机器学习的入门算法.本文将介绍k-近邻算法的原理.手写字符识别问题分析.手写字符识别的k ...

  9. TensorFlow下利用MNIST训练模型识别手写数字

    本文将参考TensorFlow中文社区官方文档使用mnist数据集训练一个多层卷积神经网络(LeNet5网络),并利用所训练的模型识别自己手写数字. 训练MNIST数据集,并保存训练模型 # Pyth ...

随机推荐

  1. 在iOS 8中使用UIAlertController

    iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸 ...

  2. APP国际化

    1.app本地内容国际化 ①在项目中新建一个New File ---> iOS Resource -> String File ---> 命名为Localizable(之所以命名为L ...

  3. Entity Framework 异常档案

    1.异常 The model backing the 'DBContext' context has changed since the database was created.Consider u ...

  4. CListCtrl中删除多个不连续的行

    ==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...

  5. CSS中vw和vh单位的使用

    vw——viewpoint width,视窗宽度,1vw等于视窗宽度的1%: vh——viewpoint height,视窗高度,1vh等于视窗高度的1%:例子:http://tutorialzine ...

  6. java PKCS7Padding 加密Cannot find any provider supporting AES/CBC/PKCS7Padding 解决办法

    在java中用aes256进行加密,但是发现java里面不能使用PKCS7Padding,而java中自带的是PKCS5Padding填充,那解决办法是,通过BouncyCastle组件来让java里 ...

  7. linux64位android项目R文件无法生成以及Cannot run program adb

    1.本机kali2.0  64位,kali基于Debian. 2.android adb是32位,64位linux要安装32位依赖库,注意ia32-lib被lib32z1替代. 3.执行命令 sudo ...

  8. [转]Performance Analysis Using SQL Server 2008 Activity Monitor Tool

    本文转自:https://www.mssqltips.com/sqlservertip/1917/performance-analysis-using-sql-server-2008-activity ...

  9. 【ASP.NET 进阶】定时执行任务

    原理:利用全局应用程序类 Global.asax 和 System.Timers.Timer  类定时处理任务. 示例效果图: 其 Global.asax 类代码如下: using System; u ...

  10. HDU 3400 Line belt【三分套三分】

    从A出发到D,必定有从AB某个点E出发,从某个点F进入CD 故有E,F两个不确定的值. 在AB上行走的时间   f = AE / p 在其他区域行走的时间 g = EF / r 在CD上行走的时间   ...