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

识别功能早在Win 8 App的API中就有了,到了UWP,同样使用,这叫传承,一路学过来,都是一个体系的,我不明白为什么某些人一遇到升级就说SDK变化太大,适应不了。我是不明白了,有什么适应不了的,该不会是你笨吧,或者学习方法不对。反正老周在以前的博客中都说过了,学习要学活,不要把知识学死了,把东西往死里学,就是古人所说的书呆子。

好了,不谈论书呆子的事了,因为“书呆子”在民间有太多的误解,咱们还是说正题。

处理数字墨迹有两种方式:

1、一种是脱离InkCanvas控件的方法,处理过程是面向笔触(Stroke)的,这就需要你手动去管理好你的墨迹数据了;

2、要是上一种方法太麻烦,与InkCanvas关联的做法较好,这样不用自己去搞UI部分的内容。

本着易用、久用、耐用、实用、妙用等伟大原则,我们实现手写识别还是不要脱离InkCanvas控件,这样的话实现起来会轻松很多,除非你要搞很高级的应用场景。

不讲过多的理论,免得大家看的头晕,老周简单说一个原理,大家懂了原理后,直接干活,这是学编程的万能招数。

先看看大致的步骤:

1、大家知道,InkCanvas有个关联的InkPresenter属性,引用的是InkPresenter实例,这个你得知道,不然后面的步骤就无法玩了。

2、InkPresenter类有个StrokeContainer属性,类型为InkStrokeContainer,它表示墨迹笔触的集合,被收集到的输入数据就存放到这个集合中。一个笔触通常是指你用笔/手指/鼠标按下时开始,直到你释放笔/手指/鼠标这一阶段中,所绘制出来的一段墨迹(从下笔到提笔)。一花一世界,一落一起一笔触。

3、实例化InkRecognizerContainer类,调用RecognizeAsync方法执行识别,上面为啥要提到InkStrokeContainer呢?因为执行识别需要它,你想啊,没有用户输入的墨迹(笔触)数据,一片空白,你识别个球。

4、识别后返回一个InkRecognitionResult列表,对于中文,通常只有一个InkRecognitionResult对象,但对于英文单词,可能会多个,一个InkRecognitionResult表示一个单词。对于一个InkRecognitionResult来说,访问GetTextCandidates方法返回一个字符串列表,即候选项,匹配度高的字符串排在前面。

5、也可以访问InkRecognizerContainer.GetRecognizers方法获取当前系统中已安装的语言识别引擎,中文系统至少会有一个简体中文的识别引擎。你可以到系统设置里面安装其他语言的引擎。

OK,基本思路有了,下面就可以做事情了。

首先,布置一下UI,XAML代码如下:

        <Grid Margin="15">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="300"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Name="cmbRecons" Header="选一个:" DisplayMemberPath="Name"/>
<Border Background="LightGray" Grid.Row="1" Margin="2,6">
<InkCanvas Name="inkcv" />
</Border>
<TextBlock Grid.Row="2" Name="tbresult" TextWrapping="Wrap" Foreground="Red" FontSize="24"/>
</Grid>

ComboBox控件用来显示当前系统中安装的手写识别引擎,TextBlock用来显示识别结果。

现在,切换到代码视图,首先在页面类级别声明一个InkRecognizerContainer变量,并且实例化。

        InkRecognizerContainer inkRecognContainer = new InkRecognizerContainer();

另外,还需要一个Timer,作用是在墨迹收集2秒钟后进行识别。

        DispatcherTimer timer = new DispatcherTimer();

       ……

            // 准备计时器
// 延迟2秒,应该不算慢吧
timer.Interval = TimeSpan.FromSeconds(2d);
timer.Tick += onTimerTick;
// 处理ink操作事件
inkcv.InkPresenter.StrokeInput.StrokeStarted += (k1, k2) =>
{
// 人家正要下笔呢,没有在此时识别的道理
timer.Stop();
};
inkcv.InkPresenter.StrokesCollected += (t1, t2) =>
{
// 墨迹已收集,可以进行识别
timer.Start();
};

当下笔开始书写时,会发生StrokeStarted事件,在此时,应该停止计时,你总不能人家一边写你就一边识别,没什么意思。但InkCanvas收集到输入笔触后,会发生StrokesCollected事件,这时候就可以开始计时了,2秒钟后进行识别。说白了就是在用户停止手写2秒钟后识别。

在ComboBox控件中显示系统已安装的识别引擎:

            // 获取已安装的识别引擎列表
var inkrecogs = inkRecognContainer.GetRecognizers();
// 将这些列表显示到ComboBox控件中
cmbRecons.ItemsSource = inkrecogs;
// 处理选项更改事件
cmbRecons.SelectionChanged += (s1, s2) =>
{
// 将选中的识别引擎设为默认
InkRecognizer currec = (InkRecognizer)cmbRecons.SelectedItem;
inkRecognContainer.SetDefaultRecognizer(currec);
};
if (cmbRecons.Items.Count > )
cmbRecons.SelectedIndex = ;

当ComboBox控件做出选择后,引发SelectionChanged事件,在事件处理代码中可以调用SetDefaultRecognizer方法设置默认的识别引擎。

还有一件事,不要忘了,让InkCanvas支持笔、手触、鼠标来书写。

            // 全能书写
inkcv.InkPresenter.InputDeviceTypes = Windows.UI.Core.CoreInputDeviceTypes.Mouse | Windows.UI.Core.CoreInputDeviceTypes.Touch | Windows.UI.Core.CoreInputDeviceTypes.Pen;

下面是核心代码,就是上面那个Timer的Tick事件处理,在处理代码中,执行手写识别,并显示识别的结果。

            // 如果InkStrokeContainer中没有收集笔触,那就没有识别的必要了
// 所以Count应大于0
if (inkcv.InkPresenter.StrokeContainer.GetStrokes().Count > )
{
IReadOnlyList<InkRecognitionResult> results = await inkRecognContainer.RecognizeAsync(inkcv.InkPresenter.StrokeContainer, InkRecognitionTarget.All);
// 处理结果
if (results.Count > )
{
StringBuilder strbd = new StringBuilder();
strbd.AppendLine("结果:");
// 每个InkRecognitionResult实例表示一个汉字/单词的识别结果
// 而单个结果中又包含候选列表,最接近的识别结果优先级更高
for(int x = ; x < results.Count; x++)
{
string s = string.Join(",", results[x].GetTextCandidates().ToArray());
strbd.AppendLine(s);
}
// 显示结果
tbresult.Text = strbd.ToString();
// 清理墨迹
inkcv.InkPresenter.StrokeContainer.Clear();
}
}

不是很复杂,代码你应该看得懂的,不然,学.NET这么多年,太对不起自己了。注意的是,识别后返回多个结果,对于中文,通常只返回一个,因为多个汉字是可以一起识别,并放到字符候选列表中。

在代码的最后面有这么一句:

 inkcv.InkPresenter.StrokeContainer.Clear();

这句代码的作用是清除所收集的所有墨迹,清除后,InkCanvas会变回空白。

运行一下程序,然后手写一些字,看看识别效果。

示例源代码下载

【Win 10 应用开发】手写识别的更多相关文章

  1. AI应用开发实战 - 手写识别应用入门

    AI应用开发实战 - 手写识别应用入门 手写体识别的应用已经非常流行了,如输入法,图片中的文字识别等.但对于大多数开发人员来说,如何实现这样的一个应用,还是会感觉无从下手.本文从简单的MNIST训练出 ...

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

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

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

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

  4. 10分钟教你用python 30行代码搞定简单手写识别!

    欲直接下载代码文件,关注我们的公众号哦!查看历史消息即可! 手写笔记还是电子笔记好呢? 毕业季刚结束,眼瞅着2018级小萌新马上就要来了,老腊肉小编为了咱学弟学妹们的学习,绞尽脑汁准备编一套大学秘籍, ...

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

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

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

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

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

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

  8. (手写识别) Zinnia库及其实现方法研究

    Zinnia库及其实现方法研究 (转) zinnia是一个开源的手写识别库.采用C++实现.具有手写识别,学习以及文字模型数据制作转换等功能. 项目地址 [http://zinnia.sourcefo ...

  9. TensorFlow 入门之手写识别(MNIST) softmax算法

    TensorFlow 入门之手写识别(MNIST) softmax算法 MNIST flyu6 softmax回归 softmax回归算法 TensorFlow实现softmax softmax回归算 ...

随机推荐

  1. 奇异值分解(SVD)原理与在降维中的应用

    奇异值分解(Singular Value Decomposition,以下简称SVD)是在机器学习领域广泛应用的算法,它不光可以用于降维算法中的特征分解,还可以用于推荐系统,以及自然语言处理等领域.是 ...

  2. 使用 Roslyn 编译器服务

    .NET Core和 .NET 4.6中 的C# 6/7 中的编译器Roslyn 一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为 ...

  3. 记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题

    最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且在翻第二页的时候也是要这么多的时间,这肯定是不能接受的,也是让现场用SQLServerP ...

  4. Android 获取系统相册中的所有图片

    Android 提供了API可获取到系统相册中的一些信息,主要还是通过ContentProvider 来获取想要的内容. 代码很简单,只要熟悉ContentProvider 就可以了. public ...

  5. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之目录导航

    ASP.NET MVC with Entity Framework and CSS是2016年出版的一本比较新的.关于ASP.NET MVC.EF以及CSS技术的图书,我将尝试着翻译本书以供日后查阅. ...

  6. .net Elasticsearch 学习入门笔记

    一. es安装相关1.elasticsearch安装  运行http://localhost:9200/2.head插件3.bigdesk插件安装(安装细节百度:windows elasticsear ...

  7. 算法与数据结构(十七) 基数排序(Swift 3.0版)

    前面几篇博客我们已经陆陆续续的为大家介绍了7种排序方式,今天博客的主题依然与排序算法相关.今天这篇博客就来聊聊基数排序,基数排序算法是不稳定的排序算法,在排序数字较小的情况下,基数排序算法的效率还是比 ...

  8. vscode 1.5安装体验

    1.下载安装 官方下载地址: http://code.visualstudio.com/ 界面截图: 2.图标显示功能File Icon Themes vscode1.5版本文件夹视图,可显示文件类型 ...

  9. 以向VS 程序打包集成自动写入注册表功能为例,介绍如何实现自由控制安装过程

    最近由于项目部署时需要更灵活的控制程序安装的流程以及自定义安装行为,特意研究了一下VS程序打包,把解决办法和大家分享一下. 以VS2010为例: 这是一个已经设置好最基本的Visual Studio ...

  10. JSP 标准标签库(JSTL)

    JSP 标准标签库(JSTL) JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签, ...