【WPF】提高InkAnalyer手写汉字识别的准确率

最近项目中需要用到一个手写键盘,我们使用了WPF的InkCanvas+InkAnalyer来开发。

按照文档,一般的代码写法如下:

            var analyzer = new InkAnalyzer();
            analyzer.AddStrokes(strokes, Constants.ChsLanguageId);
            analyzer.SetStrokesType(strokes, StrokeType.Writing);

            var status = analyzer.Analyze();
            if (status.Successful)
            {
                return analyzer.GetAlternates()
                    .OfType<AnalysisAlternate>()
                    .Select(x => x.RecognizedString)
                    .ToArray();
            }

            analyzer.Dispose();

不过,在实际跑起来之后,却发现识别精确度很低,经常会把一个字识别成好几个字,如果写的稍微远一点,则错误更多。

                              一个简单的人字会被识别成两个笔画

                             一个稍微写的开点的游字识别成了三个字

这让我们非常苦恼,在网上查阅资料也没有相关的方案。

经过我们仔细尝试后发现,如果我们把一个字连起来写一气呵成,识别率倒是上去了不少:

但是,我们不可能要求用户所有字都一气呵成吧?

就在这时,我们想到,既然不能要求用户把字一气呵成的写完,能不能通过程序让用户写的笔画“一气呵成”呢?

有了这个灵感,简单改动,将代码改成如下的写法:

        /// <summary>
        /// 识别
        /// </summary>
        /// <param name="strokes">笔迹集合</param>
        /// <returns>候选词数组</returns>
        public string[] Recognize(StrokeCollection strokes)
        {
            if (strokes == null || strokes.Count == 0)
                return Constants.EmptyAlternates;

            var stroke = GetCombinedStore(strokes);

            var analyzer = new InkAnalyzer();
            analyzer.AddStroke(stroke, Constants.ChsLanguageId);
            analyzer.SetStrokeType(stroke, StrokeType.Writing);

            var status = analyzer.Analyze();
            if (status.Successful)
            {
                return analyzer.GetAlternates()
                    .OfType<AnalysisAlternate>()
                    .Select(x => x.RecognizedString)
                    .ToArray();
            }

            analyzer.Dispose();

            return Constants.EmptyAlternates;
        }

        private static Stroke GetCombinedStore(StrokeCollection strokes)
        {
            var points = new StylusPointCollection();
            foreach (var stroke in strokes)
            {
                points.Add(stroke.StylusPoints);
            }
            return new Stroke(points);
        }

注意,在这种写法里面,我们并不直接使用InkCanvas给出的StrokeCollection,而是重新创建了一个Stroke,这个Stroke的StylusPoints是把所有Stroke的StylusPoints都添加进去了,多个Stroke变成了一个Stroke,这下我们再试试:

终于达到我们的要求了,呵呵

希望能给大家带来帮助

【附】如何启用手写识别:

1、在控制面板中选择 程序和功能->添加/删除Windows组件,选择TabletPC组件功能。

2、引用IACore.dll,IALoader.dll,IAWinFX.dll,Microsoft.Ink.Analysis.dll

3、App.config里面需要设置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
  </startup>
</configuration>

代码下载:https://files.cnblogs.com/RMay/WpfRecognize.7z

posted @ 2013-07-05 10:29  大佛脚下  阅读(5140)  评论(8编辑  收藏  举报