Compartir a través de


Reconocimiento de texto en el SDK de Aplicaciones para Windows

Las nuevas API de reconocimiento de texto de inteligencia artificial (IA) que se incluirán con el SDK de Aplicaciones para Windows se pueden usar para identificar caracteres en una imagen, reconocer palabras, líneas, límites poligonales y proporcionar niveles de confianza para las coincidencias generadas.

Estas nuevas API del SDK de Aplicaciones para Windows son más rápidas y precisas que las API de Windows.Media.Ocr.OcrEngine heredadas en el SDK de Plataforma para Windows y admiten la aceleración de hardware en dispositivos que tengan una unidad de procesamiento neuronal (NPU).

Importante

El canal experimental del SDK de Aplicaciones para Windows incluye API y características que se encuentran en las primeras fases del desarrollo. Todas las API del canal experimental están sujetas a revisiones exhaustivas y cambios importantes y se pueden eliminar de versiones posteriores en cualquier momento. No son compatibles para el uso en entornos de producción, y las aplicaciones que utilizan las características experimentales no se pueden publicar en Microsoft Store.

Requisitos previos

¿Qué puedo hacer con el SDK de Aplicaciones para Windows y el reconocimiento de texto de IA?

Use las características de reconocimiento de texto de IA en el SDK de Aplicaciones para Windows para identificar y reconocer texto en una imagen. También puede obtener los límites de texto y las puntuaciones de confianza del texto reconocido.

Creación de un elemento ImageBuffer a partir de un archivo

En este ejemplo, llamamos a una función LoadImageBufferFromFileAsync para obtener un elemento ImageBuffer de un archivo de imagen.

En la función LoadImageBufferFromFileAsync, se completan los pasos siguientes:

  1. Cree un objeto StorageFile a partir de la ruta de acceso del archivo especificada.
  2. Abra una secuencia en StorageFile mediante OpenAsync.
  3. Cree un elemento BitmapDecoder de la secuencia.
  4. Llame a GetSoftwareBitmapAsync en el decodificador de mapa de bits para obtener un objeto SoftwareBitmap.
  5. Devuelva un búfer de imagen de CreateBufferAttachedToBitmap.
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);
}

Reconocimiento de texto en una imagen de mapa de bits

En el siguiente ejemplo se muestra cómo reconocer texto en un objeto SoftwareBitmap como un valor de cadena único:

  1. Cree un objeto TextRecognizer a través de una llamada a la función EnsureModelIsReady, que también confirmará que haya un modelo de lenguaje presente en el sistema.
  2. Con el mapa de bits que ha obtenido en el fragmento de código anterior, llame a la función RecognizeTextFromSoftwareBitmap.
  3. Llame a CreateBufferAttachedToBitmap en el archivo de imagen para obtener un objeto ImageBuffer.
  4. Llame a RecognizeTextFromImage para obtener el texto reconocido de ImageBuffer.
  5. Cree un objeto wstringstream y cárguelo con el texto reconocido.
  6. Devuelva la cadena.

Nota:

La función EnsureModelIsReady se usa para comprobar el estado de preparación del modelo de reconocimiento de texto (e instalarlo si es necesario).

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();
}

Obtención de límites de palabras y confianza

Aquí se muestra cómo visualizar el BoundingBox de cada palabra en un objeto SoftwareBitmap como una colección de polígonos codificados por colores en un elemento Grid.

Nota:

En este ejemplo se supone que ya se ha creado un objeto TextRecognizer y se ha pasado a la función.

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);
        }
    }
}

Recursos adicionales

Acceso a archivos y carpetas con SDK de Aplicaciones para Windows y API de WinRT