Zinnia库及其实现方法研究 (转)

zinnia是一个开源的手写识别库。采用C++实现。具有手写识别,学习以及文字模型数据制作转换等功能。

  • 项目地址 [http://zinnia.sourceforge.net ]
  • License: NewBSD
  • 作者对SVM很有研究. 比同类程序的效率要高效.(同类项目如tegaki)
  • 我的目的是通过这个研究简单的手写输入实现方法

Zinnia库特点

  • SVM机实现
  • 轻量级,可移植
  • 线程安全,可供C,C++,Perl,Python,Ruby调用
  • 每秒50-100 char的认识速度
  • 快速学习

以下为通过源代码研究和debug得出的结论。

可能不是完全准确

接口

定义了Character,Recognizer,Result,Trainer等4个接口类。然后分别使用CharacterImpl, RecognizerImpl, ResultImpl, TrainerImpl实现。

公用方法

  • 定义了一个模板类 read_static 用来从一个大数据集合中读取模板类大小的数据,源数据指针根据读取长度自加。和read_ptr的区别是这个是使用memcpy,读取内容到新内存里,内存的大小即模板类的大小。而read_ptr只是返回指针,并没有指针外的内存占用。
  • 定义了一个指针读取类read_ptr用来读取数据指针,源数据指针根据读取长度自加。
  • 存储数据普遍使用vector,在每次使用前首先通过resize方法对vector的大小进行重定义。

读取文字模型文件

  • 文字模型数据采用如下数据结构。

struct Model{ const char *character; // utf-8 character float bias; // const FeatureNode *x; //features};

  • 使用一个Vector<Model>将所有的模型数据载入。

读取用户输入的手写笔迹

  • 可以自由设置手写框的大小。在内部处理中所有笔迹都被转化为1*1的手写框内的坐标来处理。
  • 通过Character类的add方法增加坐标。add的第一个参数为当前笔画,第二个参数为坐标点。通过重复使用add方法可以加入多笔输入笔迹。其中每笔包含多个坐标点数据。

由于作者没有提供界面程序。所以我使用MFC做了一个界面。包括

  • 笔迹输入区域用于接受笔迹输入。300X300pixel
  • 文字显示区域。显示笔迹识别结果
  • 辞书切换radiobutton。用来切换日语输入模式和汉语输入模式
  • 识别按钮。当前笔迹识别并消除当前笔迹。
  • OK按钮。退出。

笔迹识别feature提取

  • 首先进行坐标转换。即将用户设置的a*b大小的输入框输入的坐标点转化为1*1大小输入框下的坐标点。即坐标x坐标均缩小至1/a,y坐标均缩小至1/b。存储至node链表中。node包含x和y坐标。结构如下

struct Node { float x; float y;};

  • 然后使用显著点寻找算法。首先从第一笔的笔记数据开始。以起点first和终点last作为pair[0]的初始值。然后在起点到终点之间的其他点里面寻找一个最显著的点。(作者设定的显著点特征值为0.001。即当dist^2>0.001的时候此点是显著的)。找到最显著的点best之后,再使用递归的方式,在first和best之间(此时best为当前轮回的last)以及best和last之间寻找最显著点。最终寻找到所有的最显著点。以“张”字的第一笔为例。起点终点之间的最显著点就是折点。而起点和折点之间,折点和终点之间没有其他显著点。这样这一笔可以查找出一个显著点。并且生成3个node_pair即 起点-终点 起点-折点 折点-终点
  • 然后针对第一笔的3个node_pair添加feature数据。其中每一对node_pair会被添加12个feature。分别是

    • 起点终点的距离
    • 起点终点所成直线的角度
    • 起点距离x轴中心线的距离
    • 起点距离y轴中心线的距离
    • 终点距离x轴中心线的距离
    • 终点距离y轴中心线的距离
    • 起点和输入框中心点所成直线的角度
    • 终点和输入框中心点所成直线的角度
    • 起点距离中心点距离
    • 终点距离中心点距离
    • 起点终点x轴上的投影距离
    • 起点终点y轴上的投影距离

  • 以【串】字为实例。node_pair为17个。如图
  • 其中这些node_pair可以根据feature结构的index属性分类。包括2个类别。

    • 实体笔迹有7笔 (1,345,6,9,111213,15,17)。其中实体笔迹是基于1000*n来定义index的。7笔即在0 – 6*1000 这个范围。
    • 非实体笔迹有6笔(2,6,8,10,14,16)就是这些不是实际笔迹输入。只是画完一笔之后的终点和下一笔的起点之间的连线。这类笔迹使用100000+(n+1)*1000来定义index。6笔即在101000-106000这个范围。
    • 这样会有17*12 = 204 个feature。然后加上每个字最初的一个和最后的2个feature。一共是207个feature。正是通过这207个feature进行文字的识别,并在文字模型库里面进行匹配。得到前十个最相似的文字。

文字匹配

  • 匹配将对汉字库里面所有文字进行匹配。匹配过程是将【串】字204个feature与汉字库当前汉字的所有feature进行匹配。当【串】字某一feature的index与汉字库当前汉字的某一feature的index相同时。即取两个feature值的乘积。如果index不一致则继续下一个链表的结点来比对index。
  • 将取得所有乘积相加。最后再加上汉字库当前汉字的固有属性bias。最终形成汉字库当前汉字的最终值。得到所有汉字的最终值之后按从小到大排出前十位即为识别的最终结果。

学习功能

学习功能依靠SVM机实现。还没有来得及分析这部分代码。

打算专门对SVM做一个研究。

(手写识别) Zinnia库及其实现方法研究的更多相关文章

  1. Tensorflow之基于MNIST手写识别的入门介绍

    Tensorflow是当下AI热潮下,最为受欢迎的开源框架.无论是从Github上的fork数量还是star数量,还是从支持的语音,开发资料,社区活跃度等多方面,他当之为superstar. 在前面介 ...

  2. 使用PyTorch构建神经网络模型进行手写识别

    使用PyTorch构建神经网络模型进行手写识别 PyTorch是一种基于Torch库的开源机器学习库,应用于计算机视觉和自然语言处理等应用,本章内容将从安装以及通过Torch构建基础的神经网络,计算梯 ...

  3. 【Win 10 应用开发】手写识别

    记得前面(忘了是哪天写的,反正是前些天,请用力点击这里观看)老周讲了一个14393新增的控件,可以很轻松地结合InkCanvas来完成涂鸦.其实,InkCanvas除了涂鸦外,另一个大用途是墨迹识别, ...

  4. JS / Egret 单笔手写识别、手势识别

    UnistrokeRecognizer 单笔手写识别.手势识别 UnistrokeRecognizer : https://github.com/RichLiu1023/UnistrokeRecogn ...

  5. tensorflow笔记(四)之MNIST手写识别系列一

    tensorflow笔记(四)之MNIST手写识别系列一 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7436310.html ...

  6. 10分钟搞懂Tensorflow 逻辑回归实现手写识别

    1. Tensorflow 逻辑回归实现手写识别 1.1. 逻辑回归原理 1.1.1. 逻辑回归 1.1.2. 损失函数 1.2. 实例:手写识别系统 1.1. 逻辑回归原理 1.1.1. 逻辑回归 ...

  7. [纯C#实现]基于BP神经网络的中文手写识别算法

    效果展示 这不是OCR,有些人可能会觉得这东西会和OCR一样,直接进行整个字的识别就行,然而并不是. OCR是2维像素矩阵的像素数据.而手写识别不一样,手写可以把用户写字的笔画时间顺序,抽象成一个维度 ...

  8. win10下通过Anaconda安装TensorFlow-GPU1.3版本,并配置pycharm运行Mnist手写识别程序

    折腾了一天半终于装好了win10下的TensorFlow-GPU版,在这里做个记录. 准备安装包: visual studio 2015: Anaconda3-4.2.0-Windows-x86_64 ...

  9. 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别

    [源码下载] 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) ...

随机推荐

  1. 使用SQL Server 2005作业设置定时任务

    公司有一个老项目由于直接把终端拍摄的图片以二进制的形式保存到数据库中,数据库比较大所以需要经常删除这些冗余数据,手动删除费时费力,项目组长让我把这些操作变成自动的,每天执行一次,只保留最近两个月的图片 ...

  2. MSP430单片机输入与输出

    MSP430单片机的输入输出线绝大多数是服用的,除了个别的端口外,基本上是8为为一组,不同的型号的MSP430的端口有所不同,就msp430F5438而言,一共有11个I/O端口,其中除了第十一P11 ...

  3. Gdb 常用命令

    命令名称 含义 示例 b  fun_name 设置断点 b  main b 行号 if  条件 设置带条件断点 如:b 11 if  i==10 n 下一行 n s 跳入函数内部 s  sum fin ...

  4. 【译】 AWK教程指南 11递归程序

    awk 中除了函数的参数列表(Argument List)上的参数(Arguments)外,所有变量不管于何处出现,全被视为全局变量.其生命持续至程序结束——该变量不论在function外或 func ...

  5. VBScript Sample:遍历文件夹并获取XML文件中指定内容

    案例: 我有一个文件夹,里面有很多子文件夹,每个子文件夹中都存在一个相同名字的XML文件,XML文件里面的标签结构相同,只是内容不同,XML文件中包含ID,Name等标签. 文件夹及文件结构如下图: ...

  6. [原]Android开发环境搭建

    [Date]2014-04-20 [Author]wintys (wintys@gmail.com) http://wintys.cnblogs.com [Keywords]android . 离线a ...

  7. NOIP2014 寻找道路

    2.寻找道路 (road.cpp/c/pas) [问题描述] 在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1.路径上的所有点的出边所指 ...

  8. CUDA基本概念

    CUDA计算模型 CUDA中计算分为两部分,串行部分在Host上执行,即CPU,而并行部分在Device上执行,即GPU. 相比传统的C语言,CUDA增加了一些扩展,包括了库和关键字. CUDA代码提 ...

  9. Java实现在访问者模式中使用反射

    集合类型在面向对象编程中很常用,这也带来一些代码相关的问题.比如,“怎么操作集合中不同类型的对象?” 一种做法就是遍历集合中的每个元素,然后根据它的类型而做具体的操作.这会很复杂,尤其当你不知道集合中 ...

  10. js避免全局污染

    避免声明全局变量,以免发生冲突