最近項目中需要用到一個手寫鍵盤,我們使用了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>