add:WinRT墨迹识别
This commit is contained in:
@@ -40,14 +40,19 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
try
|
||||
{
|
||||
_isModernSystemAvailable = Environment.Is64BitProcess;
|
||||
if (_isModernSystemAvailable)
|
||||
var tryModern = WinRtInkShapeRecognizer.IsApiAvailable
|
||||
&& (Environment.Is64BitProcess || Environment.Is64BitOperatingSystem);
|
||||
|
||||
_isModernSystemAvailable = false;
|
||||
if (tryModern)
|
||||
{
|
||||
try
|
||||
{
|
||||
_modernProcessor = new ModernInkProcessor();
|
||||
_modernAnalyzer = new ModernInkAnalyzer();
|
||||
LogHelper.WriteLogToFile("墨迹识别管理器:使用64位现代化墨迹识别系统");
|
||||
_isModernSystemAvailable = true;
|
||||
LogHelper.WriteLogToFile(
|
||||
$"墨迹识别管理器:使用现代化墨迹识别系统 (WinRT) - 进程64位: {Environment.Is64BitProcess}, OS64位: {Environment.Is64BitOperatingSystem}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -80,10 +85,9 @@ namespace Ink_Canvas.Helpers
|
||||
try
|
||||
{
|
||||
if (ShapeRecognitionRouter.ResolveUseWinRt(mode)
|
||||
&& _isModernSystemAvailable
|
||||
&& _modernProcessor != null)
|
||||
&& WinRtInkShapeRecognizer.IsApiAvailable)
|
||||
{
|
||||
return _modernProcessor.RecognizeShapeAsync(strokes);
|
||||
return RunWinRtOrLogAsync(strokes);
|
||||
}
|
||||
|
||||
var legacy = InkRecognizeHelper.RecognizeShapeIACore(strokes);
|
||||
@@ -96,6 +100,19 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<InkShapeRecognitionResult> RunWinRtOrLogAsync(StrokeCollection strokes)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await WinRtInkShapeRecognizer.RecognizeShapeAsync(strokes).ConfigureAwait(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile("WinRT 墨迹形状识别异常: " + ex, LogHelper.LogType.Error);
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<StrokeCollection> CorrectInkAsync(
|
||||
StrokeCollection strokes,
|
||||
ShapeRecognitionEngineMode mode)
|
||||
|
||||
@@ -26,19 +26,29 @@ namespace Ink_Canvas.Helpers
|
||||
var alternates = analyzer.GetAlternates();
|
||||
if (alternates.Count > 0)
|
||||
{
|
||||
while ((!alternates[0].Strokes.Contains(strokes.Last()) ||
|
||||
!IsContainShapeType(((InkDrawingNode)alternates[0].AlternateNodes[0]).GetShapeName()))
|
||||
&& strokesCount >= 2)
|
||||
while (strokesCount >= 2)
|
||||
{
|
||||
var alt0 = alternates[0];
|
||||
if (alt0?.AlternateNodes == null || alt0.AlternateNodes.Count == 0)
|
||||
break;
|
||||
var drawNode = alt0.AlternateNodes[0] as InkDrawingNode;
|
||||
if (drawNode == null)
|
||||
break;
|
||||
var shapeOk = IsContainShapeType(drawNode.GetShapeName());
|
||||
if (alt0.Strokes.Contains(strokes.Last()) && shapeOk)
|
||||
break;
|
||||
analyzer.RemoveStroke(strokes[strokes.Count - strokesCount]);
|
||||
strokesCount--;
|
||||
sfsaf = analyzer.Analyze();
|
||||
if (sfsaf.Successful)
|
||||
{
|
||||
alternates = analyzer.GetAlternates();
|
||||
}
|
||||
else
|
||||
break;
|
||||
if (alternates.Count == 0)
|
||||
break;
|
||||
}
|
||||
analysisAlternate = alternates[0];
|
||||
if (alternates.Count > 0)
|
||||
analysisAlternate = alternates[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +57,8 @@ namespace Ink_Canvas.Helpers
|
||||
if (analysisAlternate != null && analysisAlternate.AlternateNodes.Count > 0)
|
||||
{
|
||||
var node = analysisAlternate.AlternateNodes[0] as InkDrawingNode;
|
||||
if (node == null)
|
||||
return default;
|
||||
return new ShapeRecognizeResult(node.Centroid, node.HotPoints, analysisAlternate, node);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,41 +46,70 @@ namespace Ink_Canvas.Helpers
|
||||
/// <summary>由 <see cref="ModernInkProcessor"/> / <see cref="InkRecognitionManager"/> 在 UI 上 await(勿在收笔回调中同步阻塞)。</summary>
|
||||
internal static async Task<InkShapeRecognitionResult> RecognizeShapeAsync(StrokeCollection strokes)
|
||||
{
|
||||
var analyzer = new WinRtInkAnalyzer();
|
||||
foreach (Stroke s in strokes)
|
||||
if (!IsApiAvailable || strokes == null || strokes.Count == 0)
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var inkStroke = CreateInkStrokeFromWpf(s);
|
||||
if (inkStroke == null)
|
||||
continue;
|
||||
var analyzer = new WinRtInkAnalyzer();
|
||||
var added = 0;
|
||||
foreach (Stroke s in strokes)
|
||||
{
|
||||
var inkStroke = CreateInkStrokeFromWpf(s);
|
||||
if (inkStroke == null)
|
||||
continue;
|
||||
|
||||
analyzer.AddDataForStroke(inkStroke);
|
||||
analyzer.SetStrokeDataKind(
|
||||
inkStroke.Id,
|
||||
global::Windows.UI.Input.Inking.Analysis.InkAnalysisStrokeKind.Drawing);
|
||||
analyzer.AddDataForStroke(inkStroke);
|
||||
analyzer.SetStrokeDataKind(
|
||||
inkStroke.Id,
|
||||
global::Windows.UI.Input.Inking.Analysis.InkAnalysisStrokeKind.Drawing);
|
||||
added++;
|
||||
}
|
||||
|
||||
if (added == 0)
|
||||
{
|
||||
LogHelper.WriteLogToFile(
|
||||
"WinRT 形状识别:未能从 WPF 笔迹生成 InkStroke(检查 StylusPoints/DrawingAttributes)。",
|
||||
LogHelper.LogType.Warning);
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
}
|
||||
|
||||
await analyzer.AnalyzeAsync().AsTask().ConfigureAwait(true);
|
||||
|
||||
var drawing = FindPrimaryDrawing(analyzer);
|
||||
if (drawing == null)
|
||||
{
|
||||
LogHelper.WriteLogToFile("WinRT 形状识别:分析完成但未找到 InkAnalysisInkDrawing 节点。", LogHelper.LogType.Trace);
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
}
|
||||
|
||||
if (drawing.DrawingKind == global::Windows.UI.Input.Inking.Analysis.InkAnalysisDrawingKind.Drawing)
|
||||
{
|
||||
LogHelper.WriteLogToFile("WinRT 形状识别:结果为 Drawing(未识别为规则形状)。", LogHelper.LogType.Trace);
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
}
|
||||
|
||||
var name = MapDrawingKindToShapeName(drawing.DrawingKind);
|
||||
if (string.IsNullOrEmpty(name) || name == "Drawing")
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
var winPts = CopyWinRtPoints(drawing);
|
||||
var hot = ToWpfPointCollection(winPts);
|
||||
var c = drawing.Center;
|
||||
var centroid = new SysPoint(c.X, c.Y);
|
||||
BoundsFromPoints(winPts, out double w, out double h);
|
||||
|
||||
var toRemove = new StrokeCollection();
|
||||
foreach (Stroke s in strokes)
|
||||
toRemove.Add(s);
|
||||
|
||||
return new InkShapeRecognitionResult(name, centroid, hot, w, h, toRemove);
|
||||
}
|
||||
|
||||
await analyzer.AnalyzeAsync().AsTask().ConfigureAwait(true);
|
||||
|
||||
var drawing = FindPrimaryDrawing(analyzer);
|
||||
if (drawing == null ||
|
||||
drawing.DrawingKind == global::Windows.UI.Input.Inking.Analysis.InkAnalysisDrawingKind.Drawing)
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.WriteLogToFile("WinRtInkShapeRecognizer 异常: " + ex, LogHelper.LogType.Error);
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
var name = MapDrawingKindToShapeName(drawing.DrawingKind);
|
||||
if (string.IsNullOrEmpty(name) || name == "Drawing")
|
||||
return InkShapeRecognitionResult.Empty;
|
||||
|
||||
var winPts = CopyWinRtPoints(drawing);
|
||||
var hot = ToWpfPointCollection(winPts);
|
||||
var c = drawing.Center;
|
||||
var centroid = new SysPoint(c.X, c.Y);
|
||||
BoundsFromPoints(winPts, out double w, out double h);
|
||||
|
||||
var toRemove = new StrokeCollection();
|
||||
foreach (Stroke s in strokes)
|
||||
toRemove.Add(s);
|
||||
|
||||
return new InkShapeRecognitionResult(name, centroid, hot, w, h, toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
private static global::Windows.UI.Input.Inking.InkStroke CreateInkStrokeFromWpf(Stroke stroke)
|
||||
@@ -117,7 +146,8 @@ namespace Ink_Canvas.Helpers
|
||||
{
|
||||
global::Windows.UI.Input.Inking.Analysis.InkAnalysisInkDrawing best = null;
|
||||
double bestArea = -1;
|
||||
Visit(analyzer.AnalysisRoot);
|
||||
if (analyzer?.AnalysisRoot != null)
|
||||
Visit(analyzer.AnalysisRoot);
|
||||
return best;
|
||||
|
||||
void Visit(global::Windows.UI.Input.Inking.Analysis.IInkAnalysisNode node)
|
||||
@@ -135,7 +165,11 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var child in node.Children)
|
||||
// WinRT IInkAnalysisNode.Children 可能为 null,不可直接 foreach。
|
||||
var children = node.Children;
|
||||
if (children == null) return;
|
||||
|
||||
foreach (var child in children)
|
||||
Visit(child);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,17 +30,17 @@
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>embedded</DebugType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<Prefer32Bit>True</Prefer32Bit>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='x86 Debug|AnyCPU'">
|
||||
<DebugType>embedded</DebugType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<Prefer32Bit>True</Prefer32Bit>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>embedded</DebugType>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
<Prefer32Bit>True</Prefer32Bit>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Resources\icc.ico</ApplicationIcon>
|
||||
|
||||
@@ -3,6 +3,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -39,6 +40,9 @@ namespace Ink_Canvas
|
||||
/// </summary>
|
||||
private List<Circle> circles = new List<Circle>();
|
||||
|
||||
/// <summary>串行执行墨迹转形状(尤其 WinRT 异步延后),避免多笔 BeginInvoke 交错修改 newStrokes。</summary>
|
||||
private static readonly SemaphoreSlim InkToShapeSerial = new SemaphoreSlim(1, 1);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -390,6 +394,7 @@ namespace Ink_Canvas
|
||||
{
|
||||
async Task InkToShapeProcessCoreAsync()
|
||||
{
|
||||
await InkToShapeSerial.WaitAsync().ConfigureAwait(true);
|
||||
try
|
||||
{
|
||||
newStrokes.Add(e.Stroke);
|
||||
@@ -713,6 +718,10 @@ namespace Ink_Canvas
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); }
|
||||
finally
|
||||
{
|
||||
InkToShapeSerial.Release();
|
||||
}
|
||||
}
|
||||
|
||||
void InkToShapeProcess()
|
||||
@@ -730,7 +739,7 @@ namespace Ink_Canvas
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(ex);
|
||||
}
|
||||
}), DispatcherPriority.Background);
|
||||
}), DispatcherPriority.Normal);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user