共用方式為


開始使用 Windows 應用程式 SDK 中的文字辨識 (OCR)

重要

此功能尚無法使用。 預計將在即將推出的 Windows 應用程式 SDK 實驗通道發行中出貨。

Windows 應用程式 SDK 實驗通道包含開發初期的 API 和功能。 實驗通道中的所有 API 都受限於廣泛的修訂和中斷性變更,而且可以隨時從後續版本中移除。 不支援在生產環境中使用,且使用實驗性功能的應用程式無法發佈至 Microsoft 市集。

文字辨識,也稱為光學字元辨識(OCR),將由 Windows 應用程式 SDK 透過一組人工智慧(AI)支援的 API 來支援,這些 API 可以偵測和擷取影像內的文字,並將其轉換成計算機可讀取的字串串流。

這些 API 可以識別字元、文字、線條、多邊形文字界限,以及為每個相符專案提供信賴等級。 在具有神經處理單元 (NPU) 的裝置中,硬體加速也獨佔支持它們,使其比 Windows 平臺 SDK 中的舊版 Windows.Media.Ocr.OcrEngine API 更快且更精確。

如需 API 詳細數據,請參閱 Windows 應用程式 SDK 中適用於 AI 支援的文字辨識 (OCR) 的 API 參考。

提示

藉由在 Windows 應用程式 SDK GitHub 存放庫中建立新的問題,提供這些 API 及其功能的意見反應。 (請確定您在 標題中包含 OCR

必要條件

如何使用 Windows 應用程式 SDK 和 AI 文字辨識?

使用 Windows 應用程式 SDK 中的新 AI 文字辨識功能來識別和辨識影像中的文字。 您也可以取得已辨識文字的文字界限和信賴分數。

從檔案建立 ImageBuffer

在此範例中,我們會呼叫 函 LoadImageBufferFromFileAsync 式,從圖像檔取得 ImageBuffer

在 LoadImageBufferFromFileAsync 函式中,我們會完成下列步驟:

  1. 從指定的檔案路徑建立 StorageFile 物件。
  2. 使用 OpenAsync 在 StorageFile 上開啟數據流。
  3. 建立 數據流的BitmapDecoder
  4. 在點陣圖譯碼器上呼叫 GetSoftwareBitmapAsync 以取得 SoftwareBitmap 物件。
  5. 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);
}

辨識位圖影像中的文字

下列範例示範如何將 SoftwareBitmap 物件中的某些文字辨識為單一字串值:

  1. 透過呼叫 函式建立 EnsureModelIsReady 物件,這也會確認系統上有語言模型存在。
  2. 使用在上一個代碼段中取得的點陣圖,我們呼叫 函式 RecognizeTextFromSoftwareBitmap
  3. 在圖像檔上呼叫 CreateBufferAttachedToBitmap 以取得 ImageBuffer 物件。
  4. 呼叫 RecognizeTextFromImage 以從 ImageBuffer 取得辨識的文字。
  5. 建立 wstringstream 物件,並使用已辨識的文字載入它。
  6. 傳回字串。

注意

EnsureModelIsReady 式可用來檢查文字辨識模型的整備狀態(並視需要安裝)。

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

取得文字界限和信賴度

我們在這裡示範如何將SoftwareBitmap物件中每個單字的BoundingBox可視化,做為 Grid 元素上色彩編碼多邊形的集合。

注意

在此範例中,我們假設 TextRecognizer 物件已建立並傳入函式。

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

其他資源

使用 Windows 應用程式 SDK 和 WinRT API 存取檔案和資料夾