Erste Schritte mit KI-Texterkennung (OCR) im Windows App-SDK
Wichtig
Im neuesten experimentellen Kanal-Release für das Windows App SDK verfügbar.
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. Die Verwendung experimenteller Features wird in Produktionsumgebungen nicht unterstützt. Apps, die sie verwenden, können im Microsoft Store nicht veröffentlicht werden.
- Nicht gepackte Apps werden nicht unterstützt.
Die Texterkennung, auch als optische Zeichenerkennung (Optical Character Recognition, OCR) bezeichnet, wird vom Windows App-SDK über eine Reihe durch künstliche Intelligenz (KI) gesicherte APIs unterstützt, die Text in Bildern erkennen und extrahieren und in maschinenlesbare Zeichenströme konvertieren können.
Diese APIs können Zeichen, Wörter, Zeilen, polygonale Textgrenzen identifizieren und Konfidenzniveaus für jede Übereinstimmung bereitstellen. Sie werden auch ausschließlich von der Hardwarebeschleunigung in Geräten mit einer neuralen Verarbeitungseinheit (Neural Processing Unit, NPU) unterstützt, sodass sie schneller und genauer als die älteren Windows.Media.OcrEngine-APIs im Windows-Plattform-SDK sind.
API-Details enthält die API-Referenz für Texterkennung (OCR) im Windows App SDK.
Tipp
Senden Sie Ihr Feedback zu diesen APIs und deren Funktionalität, indem Sie ein neues Issue im GitHub-Repository des Windows App SDK erstellen (mit OCR im Titel) oder indem Sie auf ein vorhandenes Issue antworten.
Voraussetzungen
- Ein Copilot+ PC von Qualcomm, Intel oder AMD.
- Arm64EC (Emulation Compatible) wird derzeit nicht unterstützt.
- Windows 11 Insider Preview Build 26120.3073 (Dev- und Beta-Kanäle) oder höher muss auf Ihrem Gerät installiert sein.
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:
- Erstellen Sie ein StorageFile-Objekt aus dem angegebenen Dateipfad.
- Öffnen Sie einen Stream in der StorageFile mit OpenAsync.
- Erstellen Sie einen neuen BitmapDecoder für den Stream.
- Rufen Sie GetSoftwareBitmapAsync für den Bitmap-Decoder auf, um ein SoftwareBitmap-Objekt abzurufen.
- 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:
- Erstellen Sie ein TextRecognizer-Objekt über einen Aufruf der
EnsureModelIsReady
-Funktion, wodurch auch bestätigt wird, dass ein Sprachmodell in dem System vorhanden ist. - Mit der im vorherigen Codeausschnitt abgerufenen Bitmap rufen wir die
RecognizeTextFromSoftwareBitmap
Funktion auf. - Rufen Sie CreateBufferAttachedToBitmap in der Bilddatei auf, um ein ImageBuffer-Objekt abzurufen.
- Rufen Sie RecognizeTextFromImage auf, um den erkannten Text aus dem ImageBuffer abzurufen.
- Erstellen Sie ein wstringstream-Objekt, und laden Sie es mit dem erkannten Text.
- 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