【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>

代碼下載:http://files.cnblogs.com/RMay/WpfRecognize.7z


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM