Windows 应用 SDK 中的 AI 文本识别(OCR)入门
重要
Windows 应用 SDK 的最新试验通道版本中提供。
Windows 应用 SDK 试验通道包括开发早期阶段的 API 和功能。 试验通道中的所有 API 都可能经过大量修订和中断性变更,并且随时可从后续版本中删除。 不支持在生产环境中使用实验性功能,并且任何使用这些功能的应用程序都不能发布到微软应用商店。
- 不支持自包含应用。
文本识别(也称为光学字符识别(OCR)通过一组人工智能(AI)支持的 API 支持 Windows 应用 SDK,这些 API 可以检测和提取图像中的文本并将其转换为计算机可读字符流。
这些 API 可以标识字符、字词、行、多边形文本边界,并为每个匹配提供置信度。 它们还由带有神经处理单元 (NPU) 的硬件加速设备独家支持,使其比 Windows 平台 SDK中的旧版 Windows.Media.Ocr.OcrEngine API 更快、更准确。
有关 API 的详细信息,请参阅 Windows 应用 SDK 中的文本识别(OCR)API参考。
先决条件
- 来自 Qualcomm、Intel 或 AMD 的 Copilot+ PC。
- 目前不支持 Arm64EC (仿真兼容)。
- Windows 11 Insider 预览版版本 26120.3073(开发和 Beta 频道) 或更高版本必须安装在设备上。
如何使用 Windows 应用 SDK 及 AI 文本识别?
使用 Windows 应用 SDK 附带的 AI 文本识别功能来辨认和识别图像中的文本。 还可以获取已识别文本的文本边界及置信度分数。
从文件中创建 ImageBuffer
在此示例中,我们调用 LoadImageBufferFromFileAsync
函数来从图像文件中获取 ImageBuffer。
在 LoadImageBufferFromFileAsync 函数中,我们会完成以下步骤:
- 从指定的文件路径创建 StorageFile 对象。
- 使用 OpenAsync 在 StorageFile 上打开流。
- 为流创建 BitmapDecoder。
- 调用位图解码器上的 GetSoftwareBitmapAsync,以获取 SoftwareBitmap 对象。
- 从 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);
}
识别位图图像中的文本
以下示例显示了如何将 SoftwareBitmap 对象中的某些文本识别为单个字符串值:
- 通过调用
EnsureModelIsReady
函数创建 TextRecognizer 对象,该函数还会确认系统上存在语言模型。 - 使用在之前的代码片段中获取的位图,我们可调用
RecognizeTextFromSoftwareBitmap
函数。 - 调用图像文件上的 CreateBufferAttachedToBitmap,以获取 ImageBuffer 对象。
- 调用 RecognizeTextFromImage 从 ImageBuffer 获取已识别的文本。
- 创建 wstringstream 对象,并使用已识别的文本进行加载。
- 返回字符串。
注意
EnsureModelIsReady
函数用于检查文本识别模型的就绪状态(并在必要时进行安装)。
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();
}
获取字词边界和置信度
下面介绍了如何将 SoftwareBitmap 对象中每个词的 BoundingBox 可视化为 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);
}
}
}
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 访问文件和文件夹