Udostępnij za pośrednictwem


Rozpocznij pracę z rozpoznawaniem tekstu przez sztuczną inteligencję (OCR) w pakiecie SDK dla aplikacji Windows

Ważny

Dostępne w najnowszej wersji eksperymentalnego kanału zestawu SDK aplikacji systemu Windows.

Eksperymentalny kanał zestawu SDK aplikacji systemu Windows obejmuje interfejsy API i funkcje we wczesnych etapach programowania. Wszystkie interfejsy API w kanale eksperymentalnym podlegają rozbudowanym poprawkom i zmianom powodujących niezgodność i mogą zostać usunięte z kolejnych wersji w dowolnym momencie. Funkcje eksperymentalne nie są obsługiwane w środowiskach produkcyjnych i aplikacjach, które ich używają, nie mogą być publikowane w sklepie Microsoft Store.

  • Aplikacje samodzielne nie są obsługiwane.

Rozpoznawanie tekstu, znane również jako optyczne rozpoznawanie znaków (OCR), jest obsługiwane przez zestaw SDK aplikacji systemu Windows za pomocą zestawu interfejsów API opartych na sztucznej inteligencji (AI), które mogą wykrywać i wyodrębniać tekst na obrazach i konwertować go na strumienie znaków czytelnych dla maszyny.

Te interfejsy API mogą identyfikować znaki, wyrazy, linie, wielokątne granice tekstu i zapewniać poziomy ufności dla każdego dopasowania. Są one również obsługiwane wyłącznie przez przyspieszanie sprzętowe w urządzeniach z jednostką przetwarzania neuronowego (NPU), dzięki czemu są szybsze i dokładniejsze, niż starsze interfejsy API Windows.Media.Ocr.OcrEngine w zestawie SDK platformy Windows.

Aby uzyskać szczegółowe informacje o interfejsie API , zobacz artykuł API ref for Text Recognition (OCR) w zestawie SDK aplikacji systemu Windows.

Napiwek

Prześlij opinię na temat tych interfejsów API i ich funkcji, tworząc nowe zgłoszenie w repozytorium GitHub Windows App SDK (w tym OCR w tytule) lub odpowiadając na istniejące zgłoszenie.

Warunki wstępne

Co mogę zrobić za pomocą zestawu SDK aplikacji systemu Windows i rozpoznawania tekstu sztucznej inteligencji?

Użyj nowych funkcji rozpoznawania tekstu sztucznej inteligencji w zestawie SDK aplikacji systemu Windows, aby zidentyfikować i rozpoznać tekst na obrazie. Możesz również uzyskać granice tekstu i poziomy ufności dla rozpoznanego tekstu.

Tworzenie elementu ImageBuffer z pliku

W tym przykładzie wywołujemy funkcję LoadImageBufferFromFileAsync, aby uzyskać ImageBuffer z pliku graficznego.

W funkcji LoadImageBufferFromFileAsync wykonamy następujące kroki:

  1. Utwórz obiekt StorageFile na podstawie określonej ścieżki pliku.
  2. Otwórz strumień w pliku StorageFile przy użyciu openAsync.
  3. Utwórz BitmapDecoder dla strumienia.
  4. Wywołaj GetSoftwareBitmapAsync na dekoderze mapy bitowej, aby uzyskać obiekt SoftwareBitmap.
  5. Zwróć bufor obrazu z CreateBufferAttachedToBitmap.
using Microsoft.Windows.Vision;
using Microsoft.Graphics.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);
}

Rozpoznawanie tekstu na obrazie mapy bitowej

W poniższym przykładzie pokazano, jak rozpoznać jakiś tekst w obiekcie SoftwareBitmap jako pojedynczą wartość ciągu:

  1. Utwórz obiekt TextRecognizer za pomocą wywołania funkcji EnsureModelIsReady, która potwierdza również obecność modelu językowego w systemie.
  2. Używając mapy bitowej uzyskanej w poprzednim fragmencie kodu, wywołujemy funkcję RecognizeTextFromSoftwareBitmap.
  3. Wywołaj CreateBufferAttachedToBitmap w pliku obrazu, aby uzyskać obiekt ImageBuffer.
  4. Wywołaj RecognizeTextFromImage, aby uzyskać rozpoznany tekst z ImageBuffer.
  5. Utwórz obiekt wstringstream i załaduj go rozpoznanym tekstem.
  6. Zwróć ciąg.

Notatka

Funkcja EnsureModelIsReady służy do sprawdzania stanu gotowości modelu rozpoznawania tekstu (i zainstalowania go w razie potrzeby).

using Microsoft.Windows.Vision;
using Microsoft.Graphics.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();
}

Uzyskaj granice wyrazów i pewność

W tym miejscu pokazano, jak wizualizować BoundingBox każdego wyrazu w obiekcie SoftwareBitmap jako kolekcję wielokątów kodowanych kolorami na elemencie Grid.

Notatka

W tym przykładzie przyjęto założenie, że obiekt TextRecognizer został już utworzony i przekazany do funkcji.

using Microsoft.Windows.Vision;
using Microsoft.Graphics.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);
        }
    }
}

Dodatkowe zasoby

Uzyskiwanie Dostępu do Plików i Folderów przy Użyciu Windows App SDK i Interfejsów API WinRT