手写数字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开发之保存照片到自己创建的相簿

    iOS开发之保存照片到自己创建的相簿 保存照片还可以用ALAssetsLibrary,ALAssetsLibrary提供了我们对iOS设备中的相片.视频的访问,是连接应用程序和相册之间访问的一个桥梁. ...

  2. javascript 的默认对象

    一.日期对象 格式 :   日期对象名称=new Date([日期参数]) 日期参数: 1.省略(最常用)                                      2.英文-参数格式 ...

  3. git 一般的开发流程中的代码管理

    一般的开发流程中的代码管理 1. 从版本库中下载代码 git clone ssh://wenbin@192.168.1.3:29418/mustang-web 2. 针对某个feature(比如ins ...

  4. java 根据 根节点及所有子成员 构造树tree

    实体类entity package com.ompa.biz.entity; import java.util.ArrayList; import java.util.List; public cla ...

  5. GMT与UTC简介

    一.简介 许多人都知道两地时间表简称为GMT或UTC,而世界时区表则通称为World Time ,那么GMT与UTC的实质原意又是为何?世界时区又是怎么区分的?面盘上密密麻麻的英文单字代表着什么意义与 ...

  6. Dreamweaver 制作图片热点之后,点击热点部分会有个提示框,怎么去掉

    可以这么写试试看<map name="Map"> <area shape="rect" coords="364,31,517,64& ...

  7. linux—【绝对路径与相对路径】与【【文件基本操作】】(4)

    [绝对路径与相对路径] 绝对路径:我们在获得一个文件的时候,从根目录到二级到更多级目录都写全了, 终才找到这个文件,这种方式就是“绝对路径” 相对路径:目标文件与我本身文件的相对位置 当前目录:./  ...

  8. Asp.net web form 动态生成控件的注意事项

    Asp.net页面生命周期 页面初始化          Page_Init   加载View State      LoadViewState    回发数据处理      LoadPostData ...

  9. 观nginx与lvs负载均衡的较量

    在技术工作者中,常用到的就是lvs负载均衡和Nginx负载均衡了.这两者也是比较普及的.那么,根据不同的需求,两者存在着不同的优势.具体选择哪一个,还要看您的要求了.那么我们在此为大家分享一篇文章,对 ...

  10. 【读书笔记《Android游戏编程之从零开始》】3.Android 游戏开发常用的系统控件(Button、Layout、ImageButton)

    3.1 Button Button这控件不用多说,就是一个按钮,主要是点击后进行相应事件的响应. 给组件添加ID属性:定义格式为 android:id="@+id/name",这里 ...