Guest Post - Windows 10 e il riconoscimento della scrittura: cosa migliora con Creators Update?

Questo post è stato scritto da Igor Damiani, Solution Developer Expert presso Brain-Sys, appartenente alla community Visual Studio Tips & Tricks

Per gli sviluppatori di applicazioni Universal Windows Platform, il riconoscimento della scrittura con Windows 10 era disponibile fin dall’inizio. La possibilità di utilizzare una penna digitale sullo schermo è nota con il nome di Windows Ink, inchiostro digitale, ed è ben descritta a questo link. E’ utile per rendere l’utilizzo di un’app molto più rapido, soprattutto se la mole di informazioni è notevole e magari l’utente non ha molta dimestichezza con la tastiera. Con l’uscita di Windows 10 Creators Update ci sono alcune importanti novità che toccano questo aspetto, e che semplificano e migliorano la nostra produttività come sviluppatori UWP.

Vediamo di che cosa si tratta.

 

Introduzione

Innanzitutto, è importante ricordare che abbiamo a disposizione un certo numero di controlli che possiamo inserire nelle pagine XAML delle nostre applicazioni UWP. Il più intuitivo fra questi è sicuramente il controllo InkCanvas, grazie al quale abbiamo subito a disposizione una tavolozza su cui l’utente può scrivere, utilizzando tre tipologie di dispositivi di input:

  • mouse
  • touch
  • penna 
 <Grid>
    <InkCanvas x:Name="WritingArea" />
</Grid>

 

Un altro controllo a disposizione è InkToolbar, che fornisce all’utente tutta una serie di bottoni per modificare colore e spessore del tratto, oppure cambiare lo strumento di disegno. L’utente può quindi scegliere tra la penna a sfera, la matita, l’evidenziatore, la gomma ed un righello per effettuare misurazioni. E’ sufficiente impostare tramite binding la proprietà TargetInkCanvas per configurare il tutto.

 <Grid>
    <InkCanvas x:Name="WritingArea" />
    <InkToolbar VerticalAlignment="Top"
        TargetInkCanvas="{Binding ElementName=WritingArea}" />
</Grid>

Già con questi pochi controlli, l’utente ha a disposizione una superficie su cui scrivere, firmare, disegnare. La toolbar può inoltre essere completamente personalizzata, oppure scritta da zero all’interno del nostro codice XAML. Possiamo utilizzare oggetti come:

  • InkToolbarBallpointPenButton
  • InkToolbarEraserButton
  • InkToolbarStencilButton
  • InkToolbarCustomToolButton

Grazie a questi oggetti XAML, possiamo implementare la nostra toolbar. Per lo scopo di questo articolo non approfondiremo ulteriormente questo aspetto, ma è importante sapere che c’è questa possibilità.

Alcune di queste funzionalità sono disponibili anche con le versioni attuali di Windows 10. Ad esempio, il controllo InkCanvas è disponibile anche con le build 10240 e 10586. La build 14393, corrispondente all’Anniversary Edition di Windows 10, introduce la possibilità di utilizzare e personalizzare il controllo InkToolbar, come abbiamo già descritto.

Riconoscimento della scrittura: Novità di Creators Update

Cosa cambierà e cosa è destinato a migliorare adottando la prossima major release di Windows 10, denominata Creators Update, di prossima uscita? Come anticipato, Microsoft ha lavorato e riorganizzato le classi che elaborano il riconoscimento della nostra scrittura.

Per prima cosa, inseriamo un bottone che dovremo cliccare manualmente per effettuare l’analisi della scrittura.

 <Grid>
    <InkCanvas x:Name="WritingArea" />
    <InkToolbar VerticalAlignment="Top"
        TargetInkCanvas="{Binding ElementName=WritingArea}" />
    <Button VerticalAlignment="Bottom" Content="Recognize"
        x:Name="RecognizeButton" Click="RecognizeButton_Click" />
</Grid>

 

Adesso passiamo a scrivere il codice dell’event handler RecognizeButton_Click, all’interno del code-behind della nostra pagina.

 private void RecognizeButton_Click(object sender, RoutedEventArgs e)
{
    InkAnalyzer analyzer = new InkAnalyzer();
}

 

La classe InkAnalyzer, novità introdotta proprio con Windows 10 Creators Update, è la classe che si occupa di effettuare l’analisi di tutti gli input che l’utente ha fornito sulla superficie dell’InkCanvas, e restituire di conseguenza tutti i risultati ottenuti, sotto forma di stringa. E’ definita all’interno del namespace Windows.UI.Input.Inking. Per fare questo, dobbiamo chiamare il metodo AddDataForStrokes:

 private void RecognizeButton_Click(object sender, RoutedEventArgs e)
{
    IReadOnlyList<InkStroke> strokes = this.WritingArea.InkPresenter.StrokeContainer.GetStrokes();

    if (strokes.Any())
    {
        InkAnalyzer analyzer = new InkAnalyzer();
        analyzer.AddDataForStrokes(strokes);
    }
}

 

Questo metodo richiede un unico parametro di tipo IEnumerable<InkStroke>, che può essere prelevato dall’oggetto InkCanvas, nel nostro caso WritingArea, tramite la chiamata:

 this.WritingArea.InkPresenter.StrokeContainer.GetStrokes()

 

Fatto questo, chiamiamo il metodo AnalyzeAsync:

 InkAnalysisResult result = await analyzer.AnalyzeAsync();

if (result.Status == InkAnalysisStatus.Updated)
{
    
}

 

Il risultato di questa chiamata è un’istanza della classe InkAnalysisResult (namespace Windows.UI.Input.Inking.Analysis). Da notare che al momento della scrittura di questo articolo, questo namespace è ancora segnalato come in prerelease, quindi potrebbe subire modifiche prima del rilascio al pubblico di Windows 10 Creators Update.

La classe InkAnalysisResult espone una proprietà Status che ci comunica se ci sono stati cambiamenti rispetto all’ultima analisi effettuata; se vi sono stati, Status è uguale a InkAnalysisStatus.Updated, altrimenti a InkAnalysisStatus.Unchanged. Di conseguenza, possiamo mostrare all’utente ciò che ha scritto:

 var text = analyzer.AnalysisRoot.RecognizedText;
MessageDialog dlg = new MessageDialog(text);
await dlg.ShowAsync();

 

E’ compito dell’oggetto InkAnalyzer quello di analizzare e mantenere lo stato del riconoscimento della nostra scrittura. La proprietà AnalysisRoot di questa classe espone una proprietà RecognizedText, ed altre proprietà interessanti come:

  • BoundingRect, di tipo Rect, che definisce l’area in pixel utilizzata dall’utente all’interno dell’InkCanvas
  • Children, di tipo IReadOnlyList<InkAnalysisNode>, che espone una lista di tutti i nodi ottenuti dall’analisi della grafia
  • Kind, di tipo InkAnalysisNodeKind, che restituisce uno dei possibili valori tra UnclassifiedInk, Root, WritingRegion, Paragraph, Line, InkWord, InkBullet, InkDrawing, ListItem

Notare che se all’interno dell’InkCanvas disegniamo un rettangolo, la proprietà RecognizedText restituisce “Rectangle”. Esaminando più a fondo la lista di oggetti restituiti dall’analisi possiamo andare a recuperare l’oggetto rettangolo disegnato, con le sue coordinate e le sue dimensioni.

Un possibile risultato che possiamo ottenere è ad esempio: image

 

In questo caso, è stato scritto “Visual Studio” in corsivo, mentre in quest’altro caso abbiamo utilizzato lo stampatello: image

 

Altre importanti funzionalità della classe InkAnalyzer

La classe InkAnalyzer espone altri metodi utili:

  • AddDataForStroke(InkStroke inkStroke): aggiunge una singola istanza di InkStroke
  • ClearDataForAllStrokes(): cancella la lista di oggetti InkStroke utilizzati per l’analisi della scrittura
  • RemoveDataForStroke(uint strokeId): rimuove una singola di istanza di InkStroke dato il suo id univoco
  • RemoveDataForStrokes(IEnumerable<int> strokeIds): rimuove una serie di oggetti InkStroke dato l’elenco di id univoci

Precedentemente a Windows 10 Creators Update l’analisi della scrittura era delegata alla classe InkRecognizerContainer. La nuova InkAnalyzer è più performante e più precisa e soprattutto analizza la scrittura in modo disaccoppiato rispetto all’oggetto XAML definito sull’interfaccia utente, nel nostro caso InkCanvas. InkAnalyzer richiede esclusivamente una lista di oggetti InkStroke, che possono essere serializzati e deserializzati nel formato Ink Serialized Format (ISF). Questo articolo descrive in modo accurato come salvare e caricare liste di oggetti InkStroke.

Ulteriori analisi sulla scrittura: la classe InkStroke

La classe InkStroke è molto interessante, perchè fornisce molte informazioni su come l’utente ha tracciato una particolare lettera o figura sullo schermo. Ad esempio:

  • StrokeDuration, di tipo Nullable<TimeSpan>: indica il tempo che l’utente ha impiegato per disegnare
  • StrokeStartedTime, di tipo Nullable<DateTimeOffset>: indica il momento esatto in cui l’utente ha cominciato a tracciare
  • BoundingRect, di tipo Rect: indica l’area relativa all’InkCanvas occupata da questo tratto. Possiamo risalire alle coordinate ed alle dimensioni del rettangolo
  • DrawingAttributes, di tipo InkDrawingAttributes: riporta informazioni importanti riguardanti la penna utilizzata per disegnare questo tratto. Ad esempio: colore, tipo e spessore, ma anche la pressione esercitata dall’utente sullo schermo, ed altro ancora

Conclusione

Windows 10 Creators Update porta un notevole valore aggiunto, sia per gli utenti finali, sia per tutti gli sviluppatori di app Universal Windows Platform. In questo articolo abbiamo trattato in modo particolare le innovazioni nel campo del riconoscimento della grafia e della scrittura.