opencv实现KNN手写数字的识别
人工智能是当下很热门的话题,手写识别是一个典型的应用。为了进一步了解这个领域,我阅读了大量的论文,并借助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手写数字的识别的更多相关文章
- OpenCV+TensorFlow图片手写数字识别(附源码)
初次接触TensorFlow,而手写数字训练识别是其最基本的入门教程,网上关于训练的教程很多,但是模型的测试大多都是官方提供的一些素材,能不能自己随便写一串数字让机器识别出来呢?纸上得来终觉浅,带着这 ...
- 手把手教你使用LabVIEW OpenCV DNN实现手写数字识别(含源码)
@ 目录 前言 一.OpenCV DNN模块 1.OpenCV DNN简介 2.LabVIEW中DNN模块函数 二.TensorFlow pb文件的生成和调用 1.TensorFlow2 Keras模 ...
- 机器学习(二)-kNN手写数字识别
一.kNN算法是机器学习的入门算法,其中不涉及训练,主要思想是计算待测点和参照点的距离,选取距离较近的参照点的类别作为待测点的的类别. 1,距离可以是欧式距离,夹角余弦距离等等. 2,k值不能选择太大 ...
- kaggle 实战 (1): PCA + KNN 手写数字识别
文章目录 加载package read data PCA 降维探索 选择50维度, 拆分数据为训练集,测试机 KNN PCA降维和K值筛选 分析k & 维度 vs 精度 预测 生成提交文件 本 ...
- 用Keras搭建神经网络 简单模版(三)—— CNN 卷积神经网络(手写数字图片识别)
# -*- coding: utf-8 -*- import numpy as np np.random.seed(1337) #for reproducibility再现性 from keras.d ...
- 10,knn手写数字识别
# 导包 import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import KNeighborsClas ...
- KNN手写数字识别
import numpy as np import matplotlib .pyplot as plt from sklearn.neighbors import KNeighborsClassifi ...
- caffe+opencv3.3dnn模块 完成手写数字图片识别
最近由于项目需要用到caffe,学习了下caffe的用法,在使用过程中也是遇到了些问题,通过上网搜索和问老师的方法解决了,在此记录下过程,方便以后查看,也希望能为和我一样的新手们提供帮助. 顺带附上老 ...
- 用tensorflow求手写数字的识别准确率 (简单版)
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #载入数据集 mnist = in ...
随机推荐
- BZOJ 2653 middle
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2653 题目大意:多组询问,求左右端点在规定范围内移动所能得到的最大中位数. [分析] 求中 ...
- 【转载】让c++ 函数返回一个数组
在c++中是不允许数组作为函数的返回值的 int [] someFunction( ); //ILLEGAL 要想实现函数返回一个数组,那返回对应数组里面类型的指针 you must return a ...
- Auto Layout - 使用总结
1.要开始使用AutoLayout,请先设置要约束的view的translatesAutoresizingMaskIntoConstraints属性为NO.在xib或者sb中勾选Use Auto La ...
- 连接ACCESS 数据库不能使用 '';文件已在使用中。
错误类型: Microsoft JET Database Engine (0x80004005) 不能使用 '':文件已在使用中. 对数据库的操作完之后,要 conn.close() 错误原因:解 ...
- 用CSS3制作的旋转六面体动画
这是用CSS3制作的旋转的六面体 请用火狐或谷歌浏览器预览,有些旋转角度做的不够好,请大神指教 top bottom left right front back
- VS调试Libevent流程
下载源码包: libevent--stable.tar.gz 第一:编译libevent 进入VS2010命令提示,切换到libevent的所在目录 nmake /f Makefile.nmake 编 ...
- 用vs2010 编写C语言程序,VS2010 C++编译报错LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
编译mongodb-src-r2.2.2出现以下问题 LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 这个是由于日志文件引起的,可以将 项目\ ...
- sql server 2008 执行计划
SSMS允许我们查看一个图形化的执行计划(快捷键Ctrl+L)
- SQL TRY CATCH
begin try select 1/0end trybegin catch select error_number() as 'number', error_line() as 'line', er ...
- C# 中Newtonsoft.Json的安装和使用
官网参考:http://json.codeplex.com/ 在程序包管理控制台,键入NuGet命令 install-package Newtonsoft.Json 安装Newtonsoft.Js ...