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