Mengenali goresan Tinta Windows sebagai teks dan bentuk

Mengonversi goresan tinta menjadi teks dan bentuk menggunakan kemampuan pengenalan yang disertakan dalam Windows Ink.

API Penting: InkCanvas, Windows.UI.Input.Inking

Pengenalan bentuk bebas dengan analisis tinta

Di sini, kami menunjukkan cara menggunakan mesin analisis Windows Ink (Windows.UI.Input.Inking.Analysis) untuk mengklasifikasikan, menganalisis, dan mengenali serangkaian goresan bentuk bebas pada InkCanvas sebagai teks atau bentuk. (Selain pengenalan teks dan bentuk, analisis tinta juga dapat digunakan untuk mengenali struktur dokumen, daftar poin, dan gambar generik.)

Catatan

Untuk skenario teks biasa dasar, baris tunggal, seperti input formulir, lihat Pengenalan tulisan tangan yang dibatasi nanti dalam topik ini.

Dalam contoh ini, pengenalan dimulai ketika pengguna mengklik tombol untuk menunjukkan bahwa mereka sudah selesai menggambar.

Unduh sampel ini dari sampel analisis Tinta (dasar)

  1. Pertama, kami menyiapkan UI (MainPage.xaml).

    UI mencakup tombol "Kenali", InkCanvas, dan Kanvas standar. Ketika tombol "Kenali" ditekan, semua goresan tinta pada kanvas tinta dianalisis dan (jika dikenali) bentuk dan teks yang sesuai digambar pada kanvas standar. Goresan tinta asli kemudian dihapus dari kanvas tinta.

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="*"/>
         </Grid.RowDefinitions>
         <StackPanel x:Name="HeaderPanel" 
                     Orientation="Horizontal" 
                     Grid.Row="0">
             <TextBlock x:Name="Header" 
                         Text="Basic ink analysis sample" 
                         Style="{ThemeResource HeaderTextBlockStyle}" 
                         Margin="10,0,0,0" />
             <Button x:Name="recognize" 
                     Content="Recognize" 
                     Margin="50,0,10,0"/>
         </StackPanel>
         <Grid x:Name="drawingCanvas" Grid.Row="1">
    
             <!-- The canvas where we render the replacement text and shapes. -->
             <Canvas x:Name="recognitionCanvas" />
             <!-- The canvas for ink input. -->
             <InkCanvas x:Name="inkCanvas" />
    
         </Grid>
    </Grid>
    
  2. Dalam file code-behind UI (MainPage.xaml.cs), tambahkan referensi jenis namespace yang diperlukan untuk fungsionalitas analisis tinta dan tinta kami:

  3. Kami kemudian menentukan variabel global kami:

     InkAnalyzer inkAnalyzer = new InkAnalyzer();
     IReadOnlyList<InkStroke> inkStrokes = null;
     InkAnalysisResult inkAnalysisResults = null;
    
  4. Selanjutnya, kami mengatur beberapa perilaku input tinta dasar:

    /// <summary>
    /// Initialize the UI page.
    /// </summary>
    public MainPage()
    {
        this.InitializeComponent();
    
        // Set supported inking device types.
        inkCanvas.InkPresenter.InputDeviceTypes =
            Windows.UI.Core.CoreInputDeviceTypes.Mouse |
            Windows.UI.Core.CoreInputDeviceTypes.Pen | 
            Windows.UI.Core.CoreInputDeviceTypes.Touch;
    
        // Set initial ink stroke attributes.
        InkDrawingAttributes drawingAttributes = new InkDrawingAttributes();
        drawingAttributes.Color = Windows.UI.Colors.Black;
        drawingAttributes.IgnorePressure = false;
        drawingAttributes.FitToCurve = true;
        inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
    
        // Listen for button click to initiate recognition.
        recognize.Click += RecognizeStrokes_Click;
    }
    
  5. Untuk contoh ini, kami melakukan analisis tinta di penanganan aktivitas klik tombol "Kenali".

    • Pertama, panggil GetStrokes di StrokeContainer inkCanvas.InkPresenteruntuk mendapatkan koleksi semua goresan tinta saat ini.
    • Jika ada goresan tinta, berikan dalam panggilan ke AddDataForStrokes dari InkAnalyzer.
    • Kami mencoba mengenali gambar dan teks, tetapi Anda dapat menggunakan metode SetStrokeDataKind untuk menentukan apakah Anda hanya tertarik pada teks (termasuk struktur dokumen dan daftar poin) atau hanya dalam gambar (termasuk pengenalan bentuk).
    • Panggil AnalyzeAsync untuk memulai analisis tinta dan mendapatkan InkAnalysisResult.
    • Jika Status mengembalikan status Diperbarui, panggil FindNodes untuk InkAnalysisNodeKind.InkWord dan InkAnalysisNodeKind.InkDrawing.
    • Iterasi melalui kedua set jenis node dan gambar teks atau bentuk masing-masing pada kanvas pengenalan (di bawah kanvas tinta).
    • Terakhir, hapus simpul yang dikenali dari InkAnalyzer dan goresan tinta yang sesuai dari kanvas tinta.
    /// <summary>
    /// The "Analyze" button click handler.
    /// Ink recognition is performed here.
    /// </summary>
    /// <param name="sender">Source of the click event</param>
    /// <param name="e">Event args for the button click routed event</param>
    private async void RecognizeStrokes_Click(object sender, RoutedEventArgs e)
    {
        inkStrokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
        // Ensure an ink stroke is present.
        if (inkStrokes.Count > 0)
        {
            inkAnalyzer.AddDataForStrokes(inkStrokes);
    
            // In this example, we try to recognizing both 
            // writing and drawing, so the platform default 
            // of "InkAnalysisStrokeKind.Auto" is used.
            // If you're only interested in a specific type of recognition,
            // such as writing or drawing, you can constrain recognition 
            // using the SetStrokDataKind method as follows:
            // foreach (var stroke in strokesText)
            // {
            //     analyzerText.SetStrokeDataKind(
            //      stroke.Id, InkAnalysisStrokeKind.Writing);
            // }
            // This can improve both efficiency and recognition results.
            inkAnalysisResults = await inkAnalyzer.AnalyzeAsync();
    
            // Have ink strokes on the canvas changed?
            if (inkAnalysisResults.Status == InkAnalysisStatus.Updated)
            {
                // Find all strokes that are recognized as handwriting and 
                // create a corresponding ink analysis InkWord node.
                var inkwordNodes = 
                    inkAnalyzer.AnalysisRoot.FindNodes(
                        InkAnalysisNodeKind.InkWord);
    
                // Iterate through each InkWord node.
                // Draw primary recognized text on recognitionCanvas 
                // (for this example, we ignore alternatives), and delete 
                // ink analysis data and recognized strokes.
                foreach (InkAnalysisInkWord node in inkwordNodes)
                {
                    // Draw a TextBlock object on the recognitionCanvas.
                    DrawText(node.RecognizedText, node.BoundingRect);
    
                    foreach (var strokeId in node.GetStrokeIds())
                    {
                        var stroke = 
                            inkCanvas.InkPresenter.StrokeContainer.GetStrokeById(strokeId);
                        stroke.Selected = true;
                    }
                    inkAnalyzer.RemoveDataForStrokes(node.GetStrokeIds());
                }
                inkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
    
                // Find all strokes that are recognized as a drawing and 
                // create a corresponding ink analysis InkDrawing node.
                var inkdrawingNodes =
                    inkAnalyzer.AnalysisRoot.FindNodes(
                        InkAnalysisNodeKind.InkDrawing);
                // Iterate through each InkDrawing node.
                // Draw recognized shapes on recognitionCanvas and
                // delete ink analysis data and recognized strokes.
                foreach (InkAnalysisInkDrawing node in inkdrawingNodes)
                {
                    if (node.DrawingKind == InkAnalysisDrawingKind.Drawing)
                    {
                        // Catch and process unsupported shapes (lines and so on) here.
                    }
                    // Process generalized shapes here (ellipses and polygons).
                    else
                    {
                        // Draw an Ellipse object on the recognitionCanvas (circle is a specialized ellipse).
                        if (node.DrawingKind == InkAnalysisDrawingKind.Circle || node.DrawingKind == InkAnalysisDrawingKind.Ellipse)
                        {
                            DrawEllipse(node);
                        }
                        // Draw a Polygon object on the recognitionCanvas.
                        else
                        {
                            DrawPolygon(node);
                        }
                        foreach (var strokeId in node.GetStrokeIds())
                        {
                            var stroke = inkCanvas.InkPresenter.StrokeContainer.GetStrokeById(strokeId);
                            stroke.Selected = true;
                        }
                    }
                    inkAnalyzer.RemoveDataForStrokes(node.GetStrokeIds());
                }
                inkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
            }
        }
    }
    
  6. Berikut adalah fungsi untuk menggambar TextBlock di kanvas pengenalan kami. Kami menggunakan persegi panjang pembatas goresan tinta terkait pada kanvas tinta untuk mengatur posisi dan ukuran font TextBlock.

     /// <summary>
     /// Draw ink recognition text string on the recognitionCanvas.
     /// </summary>
     /// <param name="recognizedText">The string returned by text recognition.</param>
     /// <param name="boundingRect">The bounding rect of the original ink writing.</param>
     private void DrawText(string recognizedText, Rect boundingRect)
     {
         TextBlock text = new TextBlock();
         Canvas.SetTop(text, boundingRect.Top);
         Canvas.SetLeft(text, boundingRect.Left);
    
         text.Text = recognizedText;
         text.FontSize = boundingRect.Height;
    
         recognitionCanvas.Children.Add(text);
     }
    
  7. Berikut adalah fungsi untuk menggambar elipsis dan poligon di kanvas pengenalan kami. Kami menggunakan persegi panjang pembatas goresan tinta terkait pada kanvas tinta untuk mengatur posisi dan ukuran font bentuk.

     // Draw an ellipse on the recognitionCanvas.
     private void DrawEllipse(InkAnalysisInkDrawing shape)
     {
         var points = shape.Points;
         Ellipse ellipse = new Ellipse();
    
         ellipse.Width = shape.BoundingRect.Width;
         ellipse.Height = shape.BoundingRect.Height;
    
         Canvas.SetTop(ellipse, shape.BoundingRect.Top);
         Canvas.SetLeft(ellipse, shape.BoundingRect.Left);
    
         var brush = new SolidColorBrush(Windows.UI.ColorHelper.FromArgb(255, 0, 0, 255));
         ellipse.Stroke = brush;
         ellipse.StrokeThickness = 2;
         recognitionCanvas.Children.Add(ellipse);
     }
    
     // Draw a polygon on the recognitionCanvas.
     private void DrawPolygon(InkAnalysisInkDrawing shape)
     {
         List<Point> points = new List<Point>(shape.Points);
         Polygon polygon = new Polygon();
    
         foreach (Point point in points)
         {
             polygon.Points.Add(point);
         }
    
         var brush = new SolidColorBrush(Windows.UI.ColorHelper.FromArgb(255, 0, 0, 255));
         polygon.Stroke = brush;
         polygon.StrokeThickness = 2;
         recognitionCanvas.Children.Add(polygon);
     }
    

Berikut sampel ini dalam tindakan:

Sebelum analisis Setelah analisis
Before analysis After analysis

Pengenalan tulisan tangan yang dibatasi

Di bagian sebelumnya (Pengenalan bentuk bebas dengan analisis tinta), kami menunjukkan cara menggunakan API analisis tinta untuk menganalisis dan mengenali goresan tinta sewenang-wenang dalam area InkCanvas.

Di bagian ini, kami menunjukkan cara menggunakan mesin pengenalan tulisan tangan Windows Ink (bukan analisis tinta) untuk mengonversi serangkaian goresan pada InkCanvas ke teks (berdasarkan paket bahasa default yang diinstal).

Catatan

Pengenalan tulisan tangan dasar yang ditampilkan di bagian ini paling cocok untuk skenario input teks baris tunggal seperti input formulir. Untuk skenario pengenalan yang lebih kaya yang mencakup analisis dan interpretasi struktur dokumen, item daftar, bentuk, dan gambar (selain pengenalan teks), lihat bagian sebelumnya: Pengenalan bentuk bebas dengan analisis tinta.

Dalam contoh ini, pengenalan dimulai ketika pengguna mengklik tombol untuk menunjukkan bahwa mereka selesai menulis.

Unduh sampel ini dari sampel pengenalan tulisan tangan Tinta

  1. Pertama, kami menyiapkan UI.

    UI menyertakan tombol "Kenali", InkCanvas, dan area untuk menampilkan hasil pengenalan.

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="*"/>
         </Grid.RowDefinitions>
         <StackPanel x:Name="HeaderPanel"
                     Orientation="Horizontal"
                     Grid.Row="0">
                 <TextBlock x:Name="Header"
                     Text="Basic ink recognition sample"
                     Style="{ThemeResource HeaderTextBlockStyle}"
                     Margin="10,0,0,0" />
                 <Button x:Name="recognize"
                     Content="Recognize"
                     Margin="50,0,10,0"/>
         </StackPanel>
         <Grid Grid.Row="1">
             <Grid.RowDefinitions>
                 <RowDefinition Height="*"/>
                 <RowDefinition Height="Auto"/>
             </Grid.RowDefinitions>
             <InkCanvas x:Name="inkCanvas"
                 Grid.Row="0"/>
             <TextBlock x:Name="recognitionResult"
                 Grid.Row="1"
                 Margin="50,0,10,0"/>
         </Grid>
     </Grid>
    
  2. Untuk contoh ini, Anda perlu terlebih dahulu menambahkan referensi jenis namespace yang diperlukan untuk fungsionalitas tinta kami:

  3. Kami kemudian mengatur beberapa perilaku input tinta dasar.

    InkPresenter dikonfigurasi untuk menginterpretasikan data input dari pena dan mouse sebagai goresan tinta (InputDeviceTypes). Goresan tinta dirender pada InkCanvas menggunakan InkDrawingAttributes yang ditentukan. Pendengar untuk peristiwa klik pada tombol "Kenali" juga dinyatakan.

    public MainPage()
        {
            this.InitializeComponent();
    
            // Set supported inking device types.
            inkCanvas.InkPresenter.InputDeviceTypes =
                Windows.UI.Core.CoreInputDeviceTypes.Mouse |
                Windows.UI.Core.CoreInputDeviceTypes.Pen;
    
            // Set initial ink stroke attributes.
            InkDrawingAttributes drawingAttributes = new InkDrawingAttributes();
            drawingAttributes.Color = Windows.UI.Colors.Black;
            drawingAttributes.IgnorePressure = false;
            drawingAttributes.FitToCurve = true;
            inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
    
            // Listen for button click to initiate recognition.
            recognize.Click += Recognize_Click;
        }
    
  4. Akhirnya, kami melakukan pengenalan tulisan tangan dasar. Untuk contoh ini, kami menggunakan penanganan aktivitas klik tombol "Kenali" untuk melakukan pengenalan tulisan tangan.

    // Get all strokes on the InkCanvas.
        IReadOnlyList<InkStroke> currentStrokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
    
    // Create a manager for the InkRecognizer object
        // used in handwriting recognition.
        InkRecognizerContainer inkRecognizerContainer =
            new InkRecognizerContainer();
    
    // Recognize all ink strokes on the ink canvas.
        IReadOnlyList<InkRecognitionResult> recognitionResults =
            await inkRecognizerContainer.RecognizeAsync(
                inkCanvas.InkPresenter.StrokeContainer,
                InkRecognitionTarget.All);
    
    string str = "Recognition result\n";
        // Iterate through the recognition results.
        foreach (var result in recognitionResults)
        {
            // Get all recognition candidates from each recognition result.
            IReadOnlyList<string> candidates = result.GetTextCandidates();
            str += "Candidates: " + candidates.Count.ToString() + "\n";
            foreach (string candidate in candidates)
            {
                str += candidate + " ";
            }
        }
        // Display the recognition candidates.
        recognitionResult.Text = str;
        // Clear the ink canvas once recognition is complete.
        inkCanvas.InkPresenter.StrokeContainer.Clear();
    
    • Berikut adalah contoh handler klik, secara lengkap.
    // Handle button click to initiate recognition.
        private async void Recognize_Click(object sender, RoutedEventArgs e)
        {
            // Get all strokes on the InkCanvas.
            IReadOnlyList<InkStroke> currentStrokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
    
            // Ensure an ink stroke is present.
            if (currentStrokes.Count > 0)
            {
                // Create a manager for the InkRecognizer object
                // used in handwriting recognition.
                InkRecognizerContainer inkRecognizerContainer =
                    new InkRecognizerContainer();
    
                // inkRecognizerContainer is null if a recognition engine is not available.
                if (!(inkRecognizerContainer == null))
                {
                    // Recognize all ink strokes on the ink canvas.
                    IReadOnlyList<InkRecognitionResult> recognitionResults =
                        await inkRecognizerContainer.RecognizeAsync(
                            inkCanvas.InkPresenter.StrokeContainer,
                            InkRecognitionTarget.All);
                    // Process and display the recognition results.
                    if (recognitionResults.Count > 0)
                    {
                        string str = "Recognition result\n";
                        // Iterate through the recognition results.
                        foreach (var result in recognitionResults)
                        {
                            // Get all recognition candidates from each recognition result.
                            IReadOnlyList<string> candidates = result.GetTextCandidates();
                            str += "Candidates: " + candidates.Count.ToString() + "\n";
                            foreach (string candidate in candidates)
                            {
                                str += candidate + " ";
                            }
                        }
                        // Display the recognition candidates.
                        recognitionResult.Text = str;
                        // Clear the ink canvas once recognition is complete.
                        inkCanvas.InkPresenter.StrokeContainer.Clear();
                    }
                    else
                    {
                        recognitionResult.Text = "No recognition results.";
                    }
                }
                else
                {
                    Windows.UI.Popups.MessageDialog messageDialog = new Windows.UI.Popups.MessageDialog("You must install handwriting recognition engine.");
                    await messageDialog.ShowAsync();
                }
            }
            else
            {
                recognitionResult.Text = "No ink strokes to recognize.";
            }
        }
    

Pengakuan internasional

Pengenalan tulisan tangan yang disertakan dalam platform tinta Windows mencakup subset lokal dan bahasa yang luas yang didukung oleh Windows.

Lihat topik properti InkRecognizer.Name untuk daftar bahasa yang didukung oleh InkRecognizer .

Aplikasi Anda dapat mengkueri sekumpulan mesin pengenalan tulisan tangan yang diinstal dan menggunakan salah satunya, atau membiarkan pengguna memilih bahasa pilihan mereka.

Catatan Pengguna dapat melihat daftar bahasa yang diinstal dengan masuk ke Pengaturan -> Waktu & Bahasa. Bahasa yang terinstal tercantum di bawah Bahasa.

Untuk menginstal paket bahasa baru dan mengaktifkan pengenalan tulisan tangan untuk bahasa tersebut:

  1. Buka Pengaturan > Waktu & bahasa > Wilayah &bahasa.
  2. Pilih Tambahkan bahasa.
  3. Pilih bahasa dari daftar, lalu pilih versi wilayah. Bahasa sekarang tercantum di halaman Wilayah &bahasa .
  4. Klik bahasa dan pilih Opsi.
  5. Pada halaman Opsi bahasa, unduh mesin pengenalan tulisan tangan (mereka juga dapat mengunduh paket bahasa lengkap, mesin pengenalan ucapan, dan tata letak keyboard di sini).

Di sini, kami menunjukkan cara menggunakan mesin pengenalan tulisan tangan untuk menafsirkan serangkaian goresan pada InkCanvas berdasarkan pengenal yang dipilih.

Pengenalan dimulai oleh pengguna mengklik tombol ketika mereka selesai menulis.

  1. Pertama, kami menyiapkan UI.

    UI menyertakan tombol "Kenali", kotak kombo yang mencantumkan semua pengenal tulisan tangan yang diinstal, InkCanvas, dan area untuk menampilkan hasil pengenalan.

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel x:Name="HeaderPanel"
                        Orientation="Horizontal"
                        Grid.Row="0">
                <TextBlock x:Name="Header"
                           Text="Advanced international ink recognition sample"
                           Style="{ThemeResource HeaderTextBlockStyle}"
                           Margin="10,0,0,0" />
                <ComboBox x:Name="comboInstalledRecognizers"
                         Margin="50,0,10,0">
                    <ComboBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding Name}" />
                            </StackPanel>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                </ComboBox>
                <Button x:Name="buttonRecognize"
                        Content="Recognize"
                        IsEnabled="False"
                        Margin="50,0,10,0"/>
            </StackPanel>
            <Grid Grid.Row="1">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <InkCanvas x:Name="inkCanvas"
                           Grid.Row="0"/>
                <TextBlock x:Name="recognitionResult"
                           Grid.Row="1"
                           Margin="50,0,10,0"/>
            </Grid>
        </Grid>
    
  2. Kami kemudian mengatur beberapa perilaku input tinta dasar.

    InkPresenter dikonfigurasi untuk menginterpretasikan data input dari pena dan mouse sebagai goresan tinta (InputDeviceTypes). Goresan tinta dirender pada InkCanvas menggunakan InkDrawingAttributes yang ditentukan.

    Kami memanggil InitializeRecognizerList fungsi untuk mengisi kotak kombo recognizer dengan daftar pengenal tulisan tangan yang diinstal.

    Kami juga mendeklarasikan pendengar untuk peristiwa klik pada tombol "Kenali" dan peristiwa pemilihan berubah pada kotak kombo pengenal.

     public MainPage()
     {
        this.InitializeComponent();
    
        // Set supported inking device types.
        inkCanvas.InkPresenter.InputDeviceTypes =
            Windows.UI.Core.CoreInputDeviceTypes.Mouse |
            Windows.UI.Core.CoreInputDeviceTypes.Pen;
    
        // Set initial ink stroke attributes.
        InkDrawingAttributes drawingAttributes = new InkDrawingAttributes();
        drawingAttributes.Color = Windows.UI.Colors.Black;
        drawingAttributes.IgnorePressure = false;
        drawingAttributes.FitToCurve = true;
        inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);
    
        // Populate the recognizer combo box with installed recognizers.
        InitializeRecognizerList();
    
        // Listen for combo box selection.
        comboInstalledRecognizers.SelectionChanged +=
            comboInstalledRecognizers_SelectionChanged;
    
        // Listen for button click to initiate recognition.
        buttonRecognize.Click += Recognize_Click;
    }
    
  3. Kami mengisi kotak kombo recognizer dengan daftar pengenal tulisan tangan yang diinstal.

    InkRecognizerContainer dibuat untuk mengelola proses pengenalan tulisan tangan. Gunakan objek ini untuk memanggil GetRecognizers dan mengambil daftar pengenal yang diinstal untuk mengisi kotak kombo pengenal.

    // Populate the recognizer combo box with installed recognizers.
    private void InitializeRecognizerList()
    {
        // Create a manager for the handwriting recognition process.
        inkRecognizerContainer = new InkRecognizerContainer();
        // Retrieve the collection of installed handwriting recognizers.
        IReadOnlyList<InkRecognizer> installedRecognizers =
            inkRecognizerContainer.GetRecognizers();
        // inkRecognizerContainer is null if a recognition engine is not available.
        if (!(inkRecognizerContainer == null))
        {
            comboInstalledRecognizers.ItemsSource = installedRecognizers;
            buttonRecognize.IsEnabled = true;
        }
    }
    
  4. Perbarui pengenal tulisan tangan jika pilihan kotak kombo pengenal berubah.

    Gunakan InkRecognizerContainer untuk memanggil SetDefaultRecognizer berdasarkan pengenal yang dipilih dari kotak kombo pengenal.

    // Handle recognizer change.
        private void comboInstalledRecognizers_SelectionChanged(
            object sender, SelectionChangedEventArgs e)
        {
            inkRecognizerContainer.SetDefaultRecognizer(
                (InkRecognizer)comboInstalledRecognizers.SelectedItem);
        }
    
  5. Terakhir, kami melakukan pengenalan tulisan tangan berdasarkan pengenal tulisan tangan yang dipilih. Untuk contoh ini, kami menggunakan penanganan aktivitas klik tombol "Kenali" untuk melakukan pengenalan tulisan tangan.

    // Get all strokes on the InkCanvas.
        IReadOnlyList<InkStroke> currentStrokes =
            inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
    
    // Recognize all ink strokes on the ink canvas.
    IReadOnlyList<InkRecognitionResult> recognitionResults =
        await inkRecognizerContainer.RecognizeAsync(
            inkCanvas.InkPresenter.StrokeContainer,
            InkRecognitionTarget.All);
    
    string str = "Recognition result\n";
    // Iterate through the recognition results.
    foreach (InkRecognitionResult result in recognitionResults)
    {
            // Get all recognition candidates from each recognition result.
            IReadOnlyList<string> candidates =
                result.GetTextCandidates();
            str += "Candidates: " + candidates.Count.ToString() + "\n";
            foreach (string candidate in candidates)
            {
                str += candidate + " ";
            }
    }
    // Display the recognition candidates.
    recognitionResult.Text = str;
    // Clear the ink canvas once recognition is complete.
    inkCanvas.InkPresenter.StrokeContainer.Clear();
    
    • Berikut adalah contoh handler klik, secara lengkap.
    // Handle button click to initiate recognition.
    private async void Recognize_Click(object sender, RoutedEventArgs e)
    {
        // Get all strokes on the InkCanvas.
        IReadOnlyList<InkStroke> currentStrokes =
            inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
    
        // Ensure an ink stroke is present.
        if (currentStrokes.Count > 0)
        {
            // inkRecognizerContainer is null if a recognition engine is not available.
            if (!(inkRecognizerContainer == null))
            {
                // Recognize all ink strokes on the ink canvas.
                IReadOnlyList<InkRecognitionResult> recognitionResults =
                    await inkRecognizerContainer.RecognizeAsync(
                        inkCanvas.InkPresenter.StrokeContainer,
                        InkRecognitionTarget.All);
                // Process and display the recognition results.
                if (recognitionResults.Count > 0)
                {
                    string str = "Recognition result\n";
                    // Iterate through the recognition results.
                    foreach (InkRecognitionResult result in recognitionResults)
                    {
                        // Get all recognition candidates from each recognition result.
                        IReadOnlyList<string> candidates =
                            result.GetTextCandidates();
                        str += "Candidates: " + candidates.Count.ToString() + "\n";
                        foreach (string candidate in candidates)
                        {
                            str += candidate + " ";
                        }
                    }
                    // Display the recognition candidates.
                    recognitionResult.Text = str;
                    // Clear the ink canvas once recognition is complete.
                    inkCanvas.InkPresenter.StrokeContainer.Clear();
                }
                else
                {
                    recognitionResult.Text = "No recognition results.";
                }
            }
            else
            {
                Windows.UI.Popups.MessageDialog messageDialog =
                    new Windows.UI.Popups.MessageDialog(
                        "You must install handwriting recognition engine.");
                await messageDialog.ShowAsync();
            }
        }
        else
        {
            recognitionResult.Text = "No ink strokes to recognize.";
        }
    }
    

Pengenalan dinamis

Sementara, dua contoh sebelumnya mengharuskan pengguna untuk menekan tombol untuk memulai pengenalan, Anda juga dapat melakukan pengenalan dinamis menggunakan input stroke yang dipasangkan dengan fungsi waktu dasar.

Untuk contoh ini, kita akan menggunakan UI dan pengaturan stroke yang sama dengan contoh pengenalan internasional sebelumnya.

  1. Objek global ini (InkAnalyzer, InkStroke, InkAnalysisResult, DispatcherTimer) digunakan di seluruh aplikasi kami.

    // Stroke recognition globals.
    InkAnalyzer inkAnalyzer;
    DispatcherTimer recoTimer;
    
  2. Alih-alih tombol untuk memulai pengenalan, kami menambahkan pendengar untuk dua peristiwa goresan InkPresenter (StrokesCollected dan StrokeStarted), dan menyiapkan timer dasar (DispatcherTimer) dengan interval Tick satu detik.

    public MainPage()
    {
        this.InitializeComponent();
    
        // Set supported inking device types.
        inkCanvas.InkPresenter.InputDeviceTypes =
            Windows.UI.Core.CoreInputDeviceTypes.Mouse |
            Windows.UI.Core.CoreInputDeviceTypes.Pen;
    
        // Listen for stroke events on the InkPresenter to 
        // enable dynamic recognition.
        // StrokesCollected is fired when the user stops inking by 
        // lifting their pen or finger, or releasing the mouse button.
        inkCanvas.InkPresenter.StrokesCollected += inkCanvas_StrokesCollected;
        // StrokeStarted is fired when ink input is first detected.
        inkCanvas.InkPresenter.StrokeInput.StrokeStarted +=
            inkCanvas_StrokeStarted;
    
        inkAnalyzer = new InkAnalyzer();
    
        // Timer to manage dynamic recognition.
        recoTimer = new DispatcherTimer();
        recoTimer.Interval = TimeSpan.FromSeconds(1);
        recoTimer.Tick += recoTimer_TickAsync;
    }
    
  3. Kami kemudian menentukan handler untuk peristiwa InkPresenter yang kami deklarasikan pada langkah pertama (kami juga mengambil alih peristiwa halaman OnNavigatingFrom untuk mengelola timer kami).

    • StrokesCollected
      Tambahkan goresan tinta (AddDataForStrokes) ke InkAnalyzer dan mulai timer pengenalan ketika pengguna berhenti tinta (dengan mengangkat pena atau jari mereka, atau melepaskan tombol mouse). Setelah satu detik tidak ada input tinta, pengenalan dimulai.

      Gunakan metode SetStrokeDataKind untuk menentukan apakah Anda hanya tertarik pada teks (termasuk daftar poin amd struktur dokumen) atau hanya dalam gambar (termasuk pengenalan bentuk).

    • StrokeStarted
      Jika stroke baru dimulai sebelum peristiwa centang timer berikutnya, hentikan timer karena stroke baru kemungkinan adalah kelanjutan dari entri tulisan tangan tunggal.

    // Handler for the InkPresenter StrokeStarted event.
    // Don't perform analysis while a stroke is in progress.
    // If a new stroke starts before the next timer tick event,
    // stop the timer as the new stroke is likely the continuation
    // of a single handwriting entry.
    private void inkCanvas_StrokeStarted(InkStrokeInput sender, PointerEventArgs args)
    {
        recoTimer.Stop();
    }
    // Handler for the InkPresenter StrokesCollected event.
    // Stop the timer and add the collected strokes to the InkAnalyzer.
    // Start the recognition timer when the user stops inking (by 
    // lifting their pen or finger, or releasing the mouse button).
    // If ink input is not detected after one second, initiate recognition.
    private void inkCanvas_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args)
    {
        recoTimer.Stop();
        // If you're only interested in a specific type of recognition,
        // such as writing or drawing, you can constrain recognition 
        // using the SetStrokDataKind method, which can improve both 
        // efficiency and recognition results.
        // In this example, "InkAnalysisStrokeKind.Writing" is used.
        foreach (var stroke in args.Strokes)
        {
            inkAnalyzer.AddDataForStroke(stroke);
            inkAnalyzer.SetStrokeDataKind(stroke.Id, InkAnalysisStrokeKind.Writing);
        }
        recoTimer.Start();
    }
    // Override the Page OnNavigatingFrom event handler to 
    // stop our timer if user leaves page.
    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
        recoTimer.Stop();
    }
    
  4. Akhirnya, kami melakukan pengenalan tulisan tangan. Untuk contoh ini, kami menggunakan penanganan aktivitas Tick dari DispatcherTimer untuk memulai pengenalan tulisan tangan.

    private async void recoTimer_TickAsync(object sender, object e)
    {
        recoTimer.Stop();
        if (!inkAnalyzer.IsAnalyzing)
        {
            InkAnalysisResult result = await inkAnalyzer.AnalyzeAsync();
    
            // Have ink strokes on the canvas changed?
            if (result.Status == InkAnalysisStatus.Updated)
            {
                // Find all strokes that are recognized as handwriting and 
                // create a corresponding ink analysis InkWord node.
                var inkwordNodes =
                    inkAnalyzer.AnalysisRoot.FindNodes(
                        InkAnalysisNodeKind.InkWord);
    
                // Iterate through each InkWord node.
                // Display the primary recognized text (for this example, 
                // we ignore alternatives), and then delete the 
                // ink analysis data and recognized strokes.
                foreach (InkAnalysisInkWord node in inkwordNodes)
                {
                    string recognizedText = node.RecognizedText;
                    // Display the recognition candidates.
                    recognitionResult.Text = recognizedText;
    
                    foreach (var strokeId in node.GetStrokeIds())
                    {
                        var stroke =
                            inkCanvas.InkPresenter.StrokeContainer.GetStrokeById(strokeId);
                        stroke.Selected = true;
                    }
                    inkAnalyzer.RemoveDataForStrokes(node.GetStrokeIds());
                }
                inkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
            }
        }
        else
        {
            // Ink analyzer is busy. Wait a while and try again.
            recoTimer.Start();
        }
    }
    

Sampel topik

Sampel lainnya