Erste Schritte mit der Texterkennung (OCR) im Windows App SDK
Tipp
Geben Sie Feedback zu diesen APIs und deren Funktionalität, indem Sie ein neues Problem im GitHub-Repository des Windows App SDK erstellen. (Stellen Sie sicher, dass Sie OCR in den Titel einschließen!)
Die Texterkennung, auch als optische Zeichenerkennung (OCR) bezeichnet, wird vom Windows App SDK durch eine Reihe künstlicher Intelligenz (AI)-gesicherter 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 finden Sie unter API-Referenz für AI-gesicherte Texterkennung (OCR) im Windows App SDK.
Wichtig
Dieses Feature ist noch nicht verfügbar. Es wird erwartet, dass es in einer bevorstehenden experimentellen Kanalversion des Windows App SDK ausgeliefert wird.
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.
- CoPilot+ PCs mit einem Qualcomm Snapdragon® X Elite Prozessor.
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.
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);
}
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();
}
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);
}
}
}
Zugreifen auf Dateien und Ordner mit Windows App SDK und WinRT-APIs