Freigeben über


Texterkennung im Windows App SDK

Mit den neuen KI-Texterkennungs-APIs, die im Lieferumfang des Windows App SDK enthalten sind, lassen sich Zeichen in einem Bild identifizieren, Wörter, Linien und Polygongrenzen erkennen sowie Konfidenzniveaus für die generierten Übereinstimmungen bereitstellen.

Diese neuen Windows App SDK-APIs sind schneller und genauer als die älteren Windows.Media.Ocr.OcrEngine-APIs im Windows-Plattform-SDK und unterstützen die Hardwarebeschleunigung auf Geräten mit einer neuronalen Verarbeitungseinheit (NPU).

Wichtig

Der experimentelle Kanal des Windows App SDK enthält APIs und Features in frühen Entwicklungsphasen. Alle APIs im experimentellen Kanal unterliegen umfangreichen Überarbeitungen und Breaking Changes und können jederzeit aus nachfolgenden Versionen entfernt werden. Sie werden nicht für die Verwendung in Produktionsumgebungen unterstützt, und Apps, die experimentelle Features verwenden, können nicht im Microsoft Store veröffentlicht werden.

Voraussetzungen

Was kann ich mit dem Windows App SDK und der KI-Texterkennung tun?

Mit den KI-Texterkennungsfeatures im Windows App SDK können Sie Text in einem Bild identifizieren und erkennen. Sie können auch die Textbegrenzungen und Konfidenzbewertungen für den erkannten Text abrufen.

Erstellen eines ImageBuffers aus einer Datei

In diesem Beispiel wird eine LoadImageBufferFromFileAsync-Funktion aufgerufen, um einen ImageBuffer aus einer Bilddatei abzurufen.

In der LoadImageBufferFromFileAsync-Funktion führen wir die folgenden Schritte aus:

  1. Erstellen Sie ein StorageFile-Objekt aus dem angegebenen Dateipfad.
  2. Öffnen Sie einen Stream in der StorageFile mit OpenAsync.
  3. Erstellen Sie einen neuen BitmapDecoder für den Stream.
  4. Rufen Sie GetSoftwareBitmapAsync für den Bitmap-Decoder auf, um ein SoftwareBitmap-Objekt abzurufen.
  5. Geben Sie einen Bildpuffer aus CreateBufferAttachedToBitmap zurück.
using Microsoft.Windows.Vision;
using Microsoft.Windows.Imaging;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;

public async Task<ImageBuffer> LoadImageBufferFromFileAsync(string filePath)
{
    StorageFile file = await StorageFile.GetFileFromPathAsync(filePath);
    IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
    SoftwareBitmap bitmap = await decoder.GetSoftwareBitmapAsync();

    if (bitmap == null)
    {
        return null;
    }

    return ImageBuffer.CreateBufferAttachedToBitmap(bitmap);
}
namespace winrt
{
    using namespace Microsoft::Windows::Vision;
    using namespace Microsoft::Windows::Imaging;
    using namespace Windows::Graphics::Imaging;
    using namespace Windows::Storage;
    using namespace Windows::Storage::Streams;
}

winrt::IAsyncOperation<winrt::ImageBuffer> LoadImageBufferFromFileAsync(
    const std::wstring& filePath)
{
    auto file = co_await winrt::StorageFile::GetFileFromPathAsync(filePath);
    auto stream = co_await file.OpenAsync(winrt::FileAccessMode::Read);
    auto decoder = co_await winrt::BitmapDecoder::CreateAsync(stream);
    auto bitmap = co_await decoder.GetSoftwareBitmapAsync();
    if (bitmap == nullptr) {
        co_return nullptr;
    }
    co_return winrt::ImageBuffer::CreateBufferAttachedToBitmap(bitmap);
}

Erkennen von Text in einem Bitmapbild

Das folgende Beispiel zeigt, wie ein Text in einem SoftwareBitmap-Objekt als einzelne Zeichenkette erkannt werden kann:

  1. Erstellen Sie ein TextRecognizer-Objekt über einen Aufruf der EnsureModelIsReady-Funktion, wodurch auch bestätigt wird, dass ein Sprachmodell in dem System vorhanden ist.
  2. Mit der im vorherigen Codeausschnitt abgerufenen Bitmap rufen wir die RecognizeTextFromSoftwareBitmap Funktion auf.
  3. Rufen Sie CreateBufferAttachedToBitmap in der Bilddatei auf, um ein ImageBuffer-Objekt abzurufen.
  4. Rufen Sie RecognizeTextFromImage auf, um den erkannten Text aus dem ImageBuffer abzurufen.
  5. Erstellen Sie ein wstringstream-Objekt, und laden Sie es mit dem erkannten Text.
  6. Gibt die Zeichenfolge zurück.

Hinweis

Die Funktion EnsureModelIsReady wird verwendet, um den Bereitschaftsstatus des Texterkennungsmodells zu überprüfen (und bei Bedarf zu installieren).

using Microsoft.Windows.Vision;
using Microsoft.Windows.Imaging;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;

public async Task<string> RecognizeTextFromSoftwareBitmap(SoftwareBitmap bitmap)
{
    TextRecognizer textRecognizer = await EnsureModelIsReady();
    ImageBuffer imageBuffer = ImageBuffer.CreateBufferAttachedToBitmap(bitmap);
    RecognizedText recognizedText = textRecognizer.RecognizeTextFromImage(imageBuffer);
    StringBuilder stringBuilder = new StringBuilder();

    foreach (var line in recognizedText.Lines)
    {
        stringBuilder.AppendLine(line.Text);
    }

    return stringBuilder.ToString();
}

public async Task<TextRecognizer> EnsureModelIsReady()
{
    if (!TextRecognizer.IsAvailable())
    {
        var loadResult = await TextRecognizer.MakeAvailableAsync();
        if (loadResult.Status != PackageDeploymentStatus.CompletedSuccess)
        {
            throw new Exception(loadResult.ExtendedError().Message);
        }
    }

    return await TextRecognizer.CreateAsync();
}
namespace winrt
{
    using namespace Microsoft::Windows::Vision;
    using namespace Microsoft::Windows::Imaging;
    using namespace Windows::Graphics::Imaging;
}

winrt::IAsyncOperation<winrt::TextRecognizer> EnsureModelIsReady();

winrt::IAsyncOperation<winrt::hstring> RecognizeTextFromSoftwareBitmap(winrt::SoftwareBitmap const& bitmap)
{
    winrt::TextRecognizer textRecognizer = co_await EnsureModelIsReady();
    winrt::ImageBuffer imageBuffer = winrt::ImageBuffer::CreateBufferAttachedToBitmap(bitmap);
    winrt::RecognizedText recognizedText = textRecognizer.RecognizeTextFromImage(imageBuffer);
    std::wstringstream stringStream;
    for (const auto& line : recognizedText.Lines())
    {
        stringStream << line.Text().c_str() << std::endl;
    }
    co_return winrt::hstring{stringStream.view()};
}

winrt::IAsyncOperation<winrt::TextRecognizer> EnsureModelIsReady()
{
  if (!winrt::TextRecognizer::IsAvailable())
  {
    auto loadResult = co_await winrt::TextRecognizer::MakeAvailableAsync();
    if (loadResult.Status() != winrt::PackageDeploymentStatus::CompletedSuccess)
    {
        throw winrt::hresult_error(loadResult.ExtendedError());
    }
  }

  co_return winrt::TextRecognizer::CreateAsync();
}

Abrufen von Wortgrenzen und Konfidenz

Hier zeigen wir, wie man die BoundingBox eines jeden Wortes in einem SoftwareBitmap-Objekt als eine Sammlung von farbkodierten Polygonen auf einem Grid-Element visualisiert.

Hinweis

In diesem Beispiel wird davon ausgegangen, dass ein TextRecognizer-Objekt bereits erstellt und an die Funktion übergeben wurde.

using Microsoft.Windows.Vision;
using Microsoft.Windows.Imaging;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;

public void VisualizeWordBoundariesOnGrid(
    SoftwareBitmap bitmap,
    Grid grid,
    TextRecognizer textRecognizer)
{
    ImageBuffer imageBuffer = ImageBuffer.CreateBufferAttachedToBitmap(bitmap);
    RecognizedText result = textRecognizer.RecognizeTextFromImage(imageBuffer);

    SolidColorBrush greenBrush = new SolidColorBrush(Microsoft.UI.Colors.Green);
    SolidColorBrush yellowBrush = new SolidColorBrush(Microsoft.UI.Colors.Yellow);
    SolidColorBrush redBrush = new SolidColorBrush(Microsoft.UI.Colors.Red);

    foreach (var line in result.Lines)
    {
        foreach (var word in line.Words)
        {
            PointCollection points = new PointCollection();
            var bounds = word.BoundingBox;
            points.Add(bounds.TopLeft);
            points.Add(bounds.TopRight);
            points.Add(bounds.BottomRight);
            points.Add(bounds.BottomLeft);

            Polygon polygon = new Polygon();
            polygon.Points = points;
            polygon.StrokeThickness = 2;

            if (word.Confidence < 0.33)
            {
                polygon.Stroke = redBrush;
            }
            else if (word.Confidence < 0.67)
            {
                polygon.Stroke = yellowBrush;
            }
            else
            {
                polygon.Stroke = greenBrush;
            }

            grid.Children.Add(polygon);
        }
    }
}
namespace winrt
{
    using namespace Microsoft::Windows::Vision;
    using namespace Microsoft::Windows::Imaging;
    using namespace Micrsooft::Windows::UI::Xaml::Controls;
    using namespace Micrsooft::Windows::UI::Xaml::Media;
    using namespace Micrsooft::Windows::UI::Xaml::Shapes;
}

void VisualizeWordBoundariesOnGrid(
    winrt::SoftwareBitmap const& bitmap,
    winrt::Grid const& grid,
    winrt::TextRecognizer const& textRecognizer)
{
    winrt::ImageBuffer imageBuffer = winrt::ImageBuffer::CreateBufferAttachedToBitmap(bitmap);
    
    winrt::RecognizedText result = textRecognizer.RecognizeTextFromImage(imageBuffer);

    auto greenBrush = winrt::SolidColorBrush(winrt::Microsoft::UI::Colors::Green);
    auto yellowBrush = winrt::SolidColorBrush(winrt::Microsoft::UI::Colors::Yellow);
    auto redBrush = winrt::SolidColorBrush(winrt::Microsoft::UI::Colors::Red);
    
    for (const auto& line : recognizedText.Lines())
    {
        for (const auto& word : line.Words())
        {
            winrt::PointCollection points;
            const auto& bounds = word.BoundingBox();
            points.Append(bounds.TopLeft);
            points.Append(bounds.TopRight);
            points.Append(bounds.BottomRight);
            points.Append(bounds.BottomLeft);

            winrt::Polygon polygon;
            polygon.Points(points);
            polygon.StrokeThickness(2);

            if (word.Confidence() < 0.33)
            {
                polygon.Stroke(redBrush);
            }
            else if (word.Confidence() < 0.67)
            {
                polygon.Stroke(yellowBrush);
            }
            else
            {
                polygon.Stroke(greenBrush);
            }

            grid.Children().Add(polygon);
        }
    }
}

Zusätzliche Ressourcen

Zugreifen auf Dateien und Ordner mit Windows App SDK und WinRT-APIs