人工智能是当下很热门的话题,手写识别是一个典型的应用。为了进一步了解这个领域,我阅读了大量的论文,并借助opencv完成了对28x28的数字图片(预处理后的二值图像)的识别任务。

  预处理一张图片:

  首先采用opencv读取图片的构造函数读取灰度的图片,再采用大津法求出图片的二值化的阈值,并且将图片二值化。

 int otsu(const IplImage* src_image) {
double sum = 0.0;
double w0 = 0.0;
double w1 = 0.0;
double u0_temp = 0.0;
double u1_temp = 0.0;
double u0 = 0.0;
double u1 = 0.0;
double delta_temp = 0.0;
double delta_max = 0.0; int pixel_count[] = { };
float pixel_pro[] = { };
int threshold = ;
uchar* data = (uchar*)src_image->imageData;
for (int i = ; i < src_image->height; i++) {
for (int j = ; j < src_image->width; j++) {
pixel_count[(int)data[i * src_image->width + j]]++;
sum += (int)data[i * src_image->width + j];
}
}
for (int i = ; i < ; i++) {
pixel_pro[i] = (float)pixel_count[i] / (src_image->height * src_image->width);
}
for (int i = ; i < ; i++) {
w0 = w1 = u0_temp = u1_temp = u0 = u1 = delta_temp = ;
for (int j = ; j < ; j++) {
if (j <= i) {
w0 += pixel_pro[j];
u0_temp += j * pixel_pro[j];
}
else {
w1 += pixel_pro[j];
u1_temp += j * pixel_pro[j];
}
}
u0 = u0_temp / w0;
u1 = u1_temp / w1;
delta_temp = (float)(w0 *w1* pow((u0 - u1), ));
if (delta_temp > delta_max) {
delta_max = delta_temp;
threshold = i;
}
}
return threshold;
}

大津法

 void imageBinarization(IplImage* src_image) {
IplImage* binImg = cvCreateImage(cvGetSize(src_image), src_image->depth, src_image->nChannels);
CvScalar s;
int ave = ;
int binThreshold = otsu(src_image); for (int i = ; i < src_image->height; i++) {
for (int j = ; j < src_image->width; j++) {
s = cvGet2D(src_image, i, j);
ave = (s.val[] + s.val[] + s.val[]) / ;
if (ave < binThreshold) {
s.val[] = s.val[] = s.val[] = 0xff;
cvSet2D(src_image, i, j, s);
}
else {
s.val[] = s.val[] = s.val[] = 0x00;
cvSet2D(src_image, i, j, s);
}
}
}
cvCopy(src_image, binImg);
cvSaveImage(bined, binImg);
//cvShowImage("binarization", binImg);
//waitKey(0);
}

二值化

  由于是只进行简单的识别模拟,因此没有做像素断点的处理。获取minst提供的数据集,提取每个图片的hog特征,参数如下:

 HOGDescriptor *hog = new HOGDescriptor(
cvSize(ImgWidht, ImgHeight), cvSize(, ), cvSize(, ), cvSize(, ), );

  (9个方向换成18个可能会取得更准确的结果,这取决于对图片本身的复杂程度的分析

  之后即可训练knn分类器,进行分类了。

 void knnTrain() {
#ifdef SAVETRAINED
//knn training;
samples.clear();
dat_mat = Mat::zeros( * nImgNum, , CV_32FC1);
res_mat = Mat::zeros( * nImgNum, , CV_32FC1);
for (int i = ; i != ; i++) {
getFile(dirNames[i], i);
}
preTrain();
cout << "------ Training finished. -----" << endl << endl;
knn.train(dat_mat, res_mat, Mat(), false, ); #ifdef SAVEASXML
knn.save("./trained/knnTrained.xml");
#endif #else
knn.load("./trained/knnTrained.xml");
#endif //knn test
cout << endl << "--- KNN test mode : ---" << endl;
int tCnt = ;
int tAc = ;
selfknnTest(tCnt, tAc); cout << endl << endl << "Total number of test samples : " << tCnt << endl; cout << "Accuracy : " << float(float(tAc) / float(tCnt)) * << "%" << endl;
}

train

 训练结果如下,准确率还是很令人满意的。

opencv实现KNN手写数字的识别的更多相关文章

  1. OpenCV+TensorFlow图片手写数字识别(附源码)

    初次接触TensorFlow,而手写数字训练识别是其最基本的入门教程,网上关于训练的教程很多,但是模型的测试大多都是官方提供的一些素材,能不能自己随便写一串数字让机器识别出来呢?纸上得来终觉浅,带着这 ...

  2. 手把手教你使用LabVIEW OpenCV DNN实现手写数字识别(含源码)

    @ 目录 前言 一.OpenCV DNN模块 1.OpenCV DNN简介 2.LabVIEW中DNN模块函数 二.TensorFlow pb文件的生成和调用 1.TensorFlow2 Keras模 ...

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

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

  4. kaggle 实战 (1): PCA + KNN 手写数字识别

    文章目录 加载package read data PCA 降维探索 选择50维度, 拆分数据为训练集,测试机 KNN PCA降维和K值筛选 分析k & 维度 vs 精度 预测 生成提交文件 本 ...

  5. 用Keras搭建神经网络 简单模版(三)—— CNN 卷积神经网络(手写数字图片识别)

    # -*- coding: utf-8 -*- import numpy as np np.random.seed(1337) #for reproducibility再现性 from keras.d ...

  6. 10,knn手写数字识别

    # 导包 import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import KNeighborsClas ...

  7. KNN手写数字识别

    import numpy as np import matplotlib .pyplot as plt from sklearn.neighbors import KNeighborsClassifi ...

  8. caffe+opencv3.3dnn模块 完成手写数字图片识别

    最近由于项目需要用到caffe,学习了下caffe的用法,在使用过程中也是遇到了些问题,通过上网搜索和问老师的方法解决了,在此记录下过程,方便以后查看,也希望能为和我一样的新手们提供帮助. 顺带附上老 ...

  9. 用tensorflow求手写数字的识别准确率 (简单版)

    import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #载入数据集 mnist = in ...

随机推荐

  1. 打印xls注意事项

    1.ctrl+p 2.打印机选择 就绪的,不是脱机的,不要只看打印机的名字. 3.打印名单信息的话 要用横向打印 4.从数据库里导出来的数据xls可能在excel里没显示完全,比如学号.身份证号等(e ...

  2. Task相关

    1.Task的优势: 1)把任务当成变量来用,可以作为参数而传递: 2)可以捕获到异步操作中发生的异常. 2.开始异步 Task.Factory.StartNew(() => Thread.Sl ...

  3. Leetcode#148 Sort List

    原题地址 链表归并排序 真是恶心的一道题啊,哇了好多次才过. 代码: void mergeList(ListNode *a, ListNode *b, ListNode *&h, ListNo ...

  4. Sencha Touch xtype对应的class

    Sencha Touch 2的有效xtype xtype Class ----------------- --------------------- actionsheet Ext.ActionShe ...

  5. IE如何兼容placeholder属性

    在前端开发中,经常需要为input设置placeholder属性,但是placeholder是HTML5新属性,在IE10以下不兼容,那么如何完美兼容呢? 网上搜索了一下,其实也挺简单的,可以采用以下 ...

  6. 获取app版本号

    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; NSString *name = [infoDiction ...

  7. svn 分支与合并的使用

      在使用svn的时候我们往往有这样的需求.我们修改某些代码,因为对某项技术不是非常的熟悉,担心自己当前的修改(或者叫测试)会影响到服务器中版本库代码的崩溃等.传统做法我们会手动复制一份代码,然后修改 ...

  8. Linux中yum和apt-get用法及区别

    Linux中yum和apt-get用法及区别   一般来说著名的linux系统基本上分两大类:   1.RedHat系列:Redhat.Centos.Fedora等   2.Debian系列:Debi ...

  9. B股

    B股的正式名称是人民币特种股票.它是以人民币标明面值,以外币认购和买卖,在中国境内(上海.深圳)证券交易所上市交易的外资股.B股公司的注册地和上市地都在境内.

  10. JavaScript 堆内存分析新工具 OneHeap

    OneHeap 关注于运行中的 JavaScript 内存信息的展示,用可视化的方式还原了 HeapGraph,有助于理解 v8 内存管理. 背景 JavaScript 运行过程中的大部分数据都保存在 ...