[纯C#实现]基于BP神经网络的中文手写识别算法
效果展示


这不是OCR,有些人可能会觉得这东西会和OCR一样,直接进行整个字的识别就行,然而并不是.
OCR是2维像素矩阵的像素数据.而手写识别不一样,手写可以把用户写字的笔画时间顺序,抽象成一个维度.这样识别的就是3维的数据了.识别起来简单很多.
最近需要做一个中文手写识别算法.搜索了网上的一些前人作品,发现都是只讲了理论,不讲实际开发.于是打算自己开发一个,并记录开发过程.
由于代码量比较多,这里不会全部贴上来讲解,代码已经放到了gitee,部分地方需对照代码进行观看,下面有URL.
思路
网上关于中文手写识别的文章不多,不过数字OCR方案确有很多.
虽然中文手写识别并不等于OCR,但总归有点关联性.
我发现数字的OCR大概是这么个套路:

神经网络的输出层每一个节点对应一个数字的相似度.而中文不能这么做.因为中文有上万字.
不过这是手写识别,我们有用户写字的时候每一笔的数据,可以先识别笔画.然后再根据笔画,去识别字.
资源获取与数据模型设定
首先我们需要一个字典,用于提供所有中文汉字的笔画顺序,这玩意在百度搜索"字典 mdb"能得到很多(我会放到源码里)

通过查看字典的"笔顺"字段,我们可以看到,字典中的字,笔顺分为了: 横,竖,撇,捺,其它 这5个类型
横竖撇捺好弄,不过这个"其它"有点特别,通过查询.中文的笔画有30多种.
我按照长相,将笔画大体分成了这7种:
| ID | 笔画 | 名称 |
|---|---|---|
| 0 | ㇐ | 横 |
| 1 | ㇑ | 竖 |
| 2 | ㇓ | 撇 |
| 3 | ㇏ | 捺 |
| 4 | ㇕㇖⺄ | 横折 |
| 5 | ㇗㇙㇞㇟ㄣ㇂ ㇛㇜ | 竖折 |
| 6 | ㇡ ㇌ | 横折折折 |
也就是说,我这里是分成7种来识别的,后续使用的时候,是再转换为5种笔画.
我们将用户输入的笔画顺序识别出来后,经过字符串相似度算法,识别出用户输入的笔画,与字典中每个字的笔画的相似度,然后进行排序.
关于字符串相似度,这里采用的是 levenshtein算法,相关代码可在我的源码中找到.
开发采集工具&采集一些数据
首先我需要采集一些笔画数据,然后交给神经网络,训练神经网络识别能力.
这里开发了一个采集工具,用来采集一些用于训练的数据:
Gitee查看源码>>
Github查看源码>>
使用方法如下:

保存后会得到一个json文件,里面是采集到的笔画数据:

每个笔画采集30次之后保存,在保存后,请将这个文件改名,然后再重新打开一次软件,采集下一个笔画
把上面表格中的7个笔画每一个采集30次左右(次数不需要完全一样)每个笔画单独采集到一个文件

再额外采集一个用于测试的数据:

训练过程
这里选择BP网络的原因是因为网络上有直接复制即可用的C#代码,毕竟我是用C#开发,基于C#的神经网络代码很少.大部分是基于C或者python的.
我对我找到的BP网络的部分代码进行了修改,训练完后可以把训练结果保存为单个json文件.也可以读取json文件接着训练,或着运用里面的训练结果进行识别.
把上面采集的7个笔画样本放入神经网络训练:

如你所见,我另外开发了一个训练工具,读取前面步骤采集到的笔画数据生成矩阵,给BP网络,进行训练.
矩阵的格式:
**注:我用来训练的矩阵的大小是固定的16*16,以下只是为了说明而做的一个缩小版:**
| \ | 第0列 | 第1列 | 第2列 | 第3列 | 第4列 | 第5列 | 更多列 |
|---|---|---|---|---|---|---|---|
| 第0行 | 0.2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | . |
| 第1行 | 0.0 | 0.4 | 0.0 | 0.0 | 0.0 | 0.0 | . |
| 第2行 | 0.0 | 0.0 | 0.6 | 0.0 | 0.0 | 0.0 | . |
| 第3行 | 0.0 | 0.0 | 0.0 | 0.8 | 0.0 | 0.0 | . |
| 第4行 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | . |
| 第5行 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | . |
| 更多行 | . | . | . | . | . | . | . |
注意:我在矩阵中使用0~1之间的浮点数标识出了哪个像素是先画出来的,哪个像素是后画出来的.
不过神经网络输入的矩阵是1维的,所以在代码中可以看到,我写了个GetDim1Matrix方法,将这里面的数据,全部连接到了一起.
在代码中,有一个MatrixData类,这个类用于存放训练或者识别用的数据并进行矩阵的输出,可以在这里面找到生成矩阵的算法.
训练完成后,使用训练结果,对测试数据进行了测试.并生成了训练结果文件:

训练工具源码:
Gitee查看源码>>
Github查看源码>>
实际使用
识别功能和采集工具做在一起了,将神经网络训练出来的结果"GData.json"文件放进采集工具工程里.运行工程即可.


在实际使用中效果没有想象中的好,笔画相似度高的字比较多,得把字写得比较工整才能识别到,想要获取更好的结果,还需要对方案进行更多的优化才行.
改进计划
目前我比较倾向于这两个方案:
- 在测试中有个现象,笔画识别错误率有点高,可能需要修改笔画识别的方式,尝试用别的方式去识别笔画
- 我找到的字典有问题,字符虽然很全,但是笔画分类才5种,只分为"横,竖,撇,捺,其它",这个"其它"比较碍事,可以尝试找笔画分类更细的字典来解决这个问题.
如果对这个项目感兴趣或者有更好优化的思路,可以给我留言
[纯C#实现]基于BP神经网络的中文手写识别算法的更多相关文章
- 基于BP神经网络的字符识别研究
基于BP神经网络的字符识别研究 原文作者:Andrew Kirillov. http://www.codeproject.com/KB/cs/neural_network_ocr.aspx 摘要:本文 ...
- 基于BP神经网络的简单字符识别算法自小结(C语言版)
本文均属自己阅读源代码的点滴总结.转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:gzzaigcn2009@163.com 写在前面的闲话: 自我感觉自己应该不是一个非常 ...
- Tensorflow之基于MNIST手写识别的入门介绍
Tensorflow是当下AI热潮下,最为受欢迎的开源框架.无论是从Github上的fork数量还是star数量,还是从支持的语音,开发资料,社区活跃度等多方面,他当之为superstar. 在前面介 ...
- 基于tensorflow的MNIST手写识别
这个例子,是学习tensorflow的人员通常会用到的,也是基本的学习曲线中的一环.我也是! 这个例子很简单,这里,就是简单的说下,不同的tensorflow版本,相关的接口函数,可能会有不一样哟.在 ...
- densenet tensorflow 中文汉字手写识别
densenet 中文汉字手写识别,代码如下: import tensorflow as tf import os import random import math import tensorflo ...
- Windows下Tesseract4.0识别与中文手写字体训练
一 . tesseract 4.0 安装及使用 1. tesseract 4.0 安装 安装包下载地址: http://digi.bib.uni-mannheim.de/tesseract/tesse ...
- 基于steam的游戏销量预测 — PART 3 — 基于BP神经网络的机器学习与预测
语言:c++ 环境:windows 训练内容:根据从steam中爬取的数据经过文本分析制作的向量以及标签 使用相关:无 解释: 就是一个BP神经网络,借鉴参考了一些博客的解释和代码,具体哪些忘了,给出 ...
- tensorflow神经网络与单层手写字识别
1.知识点 """ 1.基础知识: 1.神经网络结构:1.输入层 2.隐含层 3.全连接层(类别个数=全连接层神经元个数)+softmax函数 4.输出层 2.逻辑回归: ...
- Pytorch1.0入门实战一:LeNet神经网络实现 MNIST手写数字识别
记得第一次接触手写数字识别数据集还在学习TensorFlow,各种sess.run(),头都绕晕了.自从接触pytorch以来,一直想写点什么.曾经在2017年5月,Andrej Karpathy发表 ...
随机推荐
- C# 对结构体和指针的使用
//结构体的定义 [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] pub ...
- TP5对数据库操作的事物作用
假如: 你写好了一段完整的代码,模型对数据库的操作,增删改查什么的,都没有问题,当然运行速度也是最快的,完全不用担心会出错, 前提肯定是已经写好的一整段代码, 但是,万一服务器中断了呢,执行一半,后面 ...
- VScode编辑器使用
快捷键: shift + alt + F 格式化
- angular js 初学
1 angularJS的一些概念 AngularJS 通过新的属性和表达式扩展了 HTML. AngularJS 是一个 JavaScript 框架,它是一个以Javascript编写的库,它可通过 ...
- python_ 函数
函数是啥? 函数能提高应用的模块性,和代码的重复利用率 函数特点? 1 代码块以 def 关键词开头,后接函数名和圆括号() 2 任何传入参数和自变量必须放在圆括号中间 3 函数以冒号开始,并且缩进 ...
- Qt学习3---子窗口与父窗口
创建子窗口后,主窗口的头文件需要 #include "子窗口头文件" 子窗口和父窗口之间相互切换 子窗口没有办法处理父窗口,子窗口此时就需要一个信号: * 信号必须有signal ...
- python中的Matplot库和Gdal库绘制富士山三维地形图-参考了虾神的喜马拉雅山
首先请大家读一下面这篇文章了解什么是Gdal http://blog.csdn.net/grllery/article/details/77822595 剩下的我要公布绘制富士山的代码了,虽然基本co ...
- bugku 密码学一些题的wp
---恢复内容开始--- 1.滴答滴 摩斯密码,http://tool.bugku.com/mosi/ 2.聪明的小羊 从提示猜是栅栏密码,http://tool.bugku.com/jiemi/ 3 ...
- redis(4.0.11)编译安装
一: redis数据库安装 系统环境:linux系统(centos/redhat):Red Hat Enterprise Linux Server release 6.8 (Santiago) red ...
- centos6.5-VMware虚拟机-双网卡绑定
1 添加多张网卡(生产环境中有多个卡槽,可用ifconfig查看) 2 编辑两张虚拟机的网卡和物理机的连接方式,这里两张都使用NAT即可 3 打开虚拟机查看所有的网卡(网络接口),修改配置网卡配置文件 ...