Поделиться через


Начало работы с распознаванием текста ИИ (OCR)

Распознавание текста, также известное как оптическое распознавание символов (OCR), поддерживается в Windows AI Foundry с помощью набора интерфейсов API с поддержкой искусственного интеллекта (ИИ), которые могут обнаруживать и извлекать текст в изображениях и преобразовывать его в потоки символов, доступные для машинного чтения.

Эти API могут определять символы, слова, строки, границы текста в форме многоугольников и предоставлять уровни достоверности для каждого совпадения. Они также поддерживаются исключительно аппаратным ускорением на устройствах с нейронной единицей обработки (NPU), что делает их более быстрыми и более точными, чем устаревшие API Windows.Media.Ocr.Ocr.OcrEngine в пакете SDK для платформы Windows.

Дополнительные сведения об API см. в справочнике по API для распознавания текста (OCR).

Это важно

Ниже приведен список функций ИИ Windows и выпуска пакета SDK для приложений Windows, в котором они в настоящее время поддерживаются.

Экспериментальная версия 1.8 (1.8.0-experimental1) - Стирание объектов, Phi Silica, LoRA тонкой настройки для Phi Silica, Сводка бесед (Текстовый интеллект)

Частная предварительная версия — семантический поиск

Версия 1.7.1 (1.7.250401001) — все остальные API

Эти API будут работать только на устройствах предварительной версии Windows (WIP), которые получили обновление 7 мая. 28-29 мая необязательное обновление будет выпущено на устройства, отличные от WIP, за которым следует обновление 10 июня. Это обновление приведет к использованию моделей ИИ, необходимых для работы API Windows. Эти обновления также требуют, чтобы любое приложение, использующее API Windows AI, не могло работать, пока ему не будет предоставлено удостоверение пакета во время выполнения.

Что можно сделать с помощью распознавания текста ИИ?

Используйте функции распознавания текста ИИ для идентификации и распознавания текста на изображении. Вы также можете получить границы текста и оценки достоверности для распознанного текста.

Создание ImageBuffer из файла

В этом примере WinUI мы вызываем LoadImageBufferFromFileAsync функцию для получения ImageBuffer из файла изображения.

В функции LoadImageBufferFromFileAsync мы выполните следующие действия:

  1. Создайте объект StorageFile из указанного пути к файлу.
  2. Откройте поток в StorageFile с помощью OpenAsync.
  3. Создайте BitmapDecoder для потока.
  4. Вызовите GetSoftwareBitmapAsync в декодере, чтобы получить SoftwareBitmap объект.
  5. Возвращает буфер изображения из 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);
}
#include <iostream>
#include <sstream>
#include <winrt/Microsoft.Windows.AI.Imaging.h>
#include <winrt/Windows.Graphics.Imaging.h>
#include <winrt/Microsoft.Graphics.Imaging.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include<winrt/Microsoft.UI.Xaml.Media.h>
#include<winrt/Microsoft.UI.Xaml.Shapes.h>

using namespace winrt;
using namespace Microsoft::UI::Xaml;
using namespace Microsoft::Windows::AI;
using namespace Microsoft::Windows::AI::Imaging;
using namespace winrt::Microsoft::UI::Xaml::Controls;
using namespace winrt::Microsoft::UI::Xaml::Media;


winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> 
    MainWindow::RecognizeTextFromSoftwareBitmap(
        Windows::Graphics::Imaging::SoftwareBitmap const& bitmap)
{
    winrt::Microsoft::Windows::AI::Imaging::TextRecognizer textRecognizer = 
        EnsureModelIsReady().get();
    Microsoft::Graphics::Imaging::ImageBuffer imageBuffer = 
        Microsoft::Graphics::Imaging::ImageBuffer::CreateForSoftwareBitmap(bitmap);
    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.str()};
}

Распознавание текста в растровом изображении

В следующем примере показано, как распознать некоторый текст в объекте SoftwareBitmap как одно строковое значение:

  1. Создайте объект TextRecognizer с помощью вызова EnsureModelIsReady функции, которая также подтверждает наличие языковой модели в системе.
  2. Используя растровое изображение, полученное в предыдущем фрагменте кода, мы вызываем функцию RecognizeTextFromSoftwareBitmap .
  3. Вызовите CreateBufferAttachedToBitmap в файле изображения, чтобы получить объект ImageBuffer .
  4. Вызовите RecognizeTextFromImage , чтобы получить распознанный текст из ImageBuffer.
  5. Создайте объект wstringstream и загрузите его с распознаваемым текстом.
  6. Возвратите строку.

Примечание.

Функция EnsureModelIsReady используется для проверки состояния готовности модели распознавания текста (и её установки при необходимости).

using Microsoft.Windows.Vision;
using Microsoft.Windows.AI;
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.GetReadyState() == AIFeatureReadyState.EnsureNeeded)
    {
        var loadResult = await TextRecognizer.EnsureReadyAsync();
        if (loadResult.Status != PackageDeploymentStatus.CompletedSuccess)
        {
            throw new Exception(loadResult.ExtendedError().Message);
        }
    }

    return await TextRecognizer.CreateAsync();
}
winrt::Windows::Foundation::IAsyncOperation<winrt::Microsoft::Windows::AI::Imaging::TextRecognizer> MainWindow::EnsureModelIsReady()
{
    if (winrt::Microsoft::Windows::AI::Imaging::TextRecognizer::GetReadyState() == AIFeatureReadyState::NotReady)
    {
        auto loadResult = TextRecognizer::EnsureReadyAsync().get();
           
        if (loadResult.Status() != AIFeatureReadyResultState::Success)
        {
            throw winrt::hresult_error(loadResult.ExtendedError());
        }
    }

    return winrt::Microsoft::Windows::AI::Imaging::TextRecognizer::CreateAsync();
}

Получение границ слов и уверенности

Здесь показано, как визуализировать BoundingBox каждого слова в объекте SoftwareBitmap в виде коллекции цветокодированных многоугольников в элементе Grid .

Примечание.

В этом примере предполагается, что объект TextRecognizer уже создан и передан в функцию.

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);
        }
    }
}
void MainWindow::VisualizeWordBoundariesOnGrid(
    Windows::Graphics::Imaging::SoftwareBitmap const& bitmap,
    Grid const& grid,
    TextRecognizer const& textRecognizer)
{
    Microsoft::Graphics::Imaging::ImageBuffer imageBuffer = 
        Microsoft::Graphics::Imaging::ImageBuffer::CreateForSoftwareBitmap(bitmap);

    RecognizedText result = textRecognizer.RecognizeTextFromImage(imageBuffer);

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

            winrt::Microsoft::UI::Xaml::Shapes::Polygon polygon{};
            polygon.Points(points);
            polygon.StrokeThickness(2);
            if (word.MatchConfidence() < 0.33)
            {
                polygon.Stroke(redBrush);
            }
            else if (word.MatchConfidence() < 0.67)
            {
                polygon.Stroke(yellowBrush);
            }
            else
            {
                polygon.Stroke(greenBrush);
            }

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

Ответственное применение ИИ

Мы использовали сочетание следующих шагов, чтобы гарантировать, что эти API-интерфейсы визуализации являются надежными, безопасными и созданными ответственно. Мы рекомендуем ознакомиться с рекомендациями, описанными в статье "Разработка ответственного искусственного интеллекта" в Windows при реализации функций ИИ в приложении.

См. также