다음을 통해 공유


AI 텍스트 인식 시작(OCR)

OCR(광학 문자 인식)으로도 알려진 텍스트 인식은 이미지 내에서 텍스트를 감지 및 추출하고 컴퓨터에서 읽을 수 있는 문자 스트림으로 변환할 수 있는 Windows AI API 집합에서 지원됩니다.

이러한 API는 문자, 단어, 선, 다각형 텍스트 경계를 식별하고 각 일치 항목에 대한 신뢰도 수준을 제공할 수 있습니다. 또한 NPU(신경 처리 장치)가 있는 디바이스의 하드웨어 가속에서만 지원되므로 Windows 플랫폼 SDK의 레거시 Windows.Media.Ocr.OcrEngine API보다 빠르고 정확합니다.

API 세부 정보는OCR(텍스트 인식)에 대한 API ref를 참조하세요.

AI 텍스트 인식으로 무엇을 할 수 있나요?

AI 텍스트 인식 기능을 사용하여 이미지의 텍스트를 식별하고 인식합니다. 인식된 텍스트의 텍스트 경계 및 신뢰도 점수를 가져올 수도 있습니다.

참고

읽을 수 없거나 크기가 작은 문자는 부정확한 결과를 생성할 수 있습니다.

파일에서 ImageBuffer 만들기

이 WinUI 예제에서는 이미지 파일에서 LoadImageBufferFromFileAsync를 가져오는 함수를 호출 합니다.

LoadImageBufferFromFileAsync 함수에서 다음 단계를 완료합니다.

  1. 지정된 파일 경로에서 StorageFile 개체를 만듭니다.
  2. OpenAsync를 사용하여 StorageFile에서 스트림을 엽니다.
  3. 스트림용 BitmapDecoder를 만듭니다.
  4. 비트맵 디코더에서 GetSoftwareBitmapAsync를 호출하여 SoftwareBitmap 개체를 가져옵니다.
  5. CreateBufferAttachedToBitmap에서 이미지 버퍼를 반환합니다.
using Microsoft.Windows.AI.Imaging;
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.AI.Imaging;
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.NotReady)
    {
        var loadResult = await TextRecognizer.EnsureReadyAsync();
        if (loadResult.Status != AIFeatureReadyResultState.Success)
        {
            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();
}

단어 경계 및 신뢰도 가져오기

여기서는 SoftwareBitmap 개체에 있는 각 단어의 BoundingBox를 Grid 요소의 색으로 구분된 다각형 컬렉션으로 시각화하는 방법을 보여 줍니다.

참고

이 예제에서는 TextRecognizer 개체가 이미 만들어지고 함수에 전달되었다고 가정합니다.

using Microsoft.Windows.AI.Imaging;
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가 신뢰할 수 있고 안전하며 책임감 있게 빌드되도록 했습니다. 앱에서 AI 기능을 구현할 때 Windows의 책임 있는 생성 AI 개발에 설명된 모범 사례를 검토하는 것이 좋습니다.

참고하십시오