世界上有很多 OCR 识别技术,本文来和大家介绍如果在 WPF 里,在运行到 win10 的设备上,通过 Windows Runtime 自带的 Windows.Media.Ocr 实现在给定的图片里面识别文本的功能

我采用的是 dotnet 6 框架版本,在 dotnet 5 和更高版本,在 dotnet 底层就删除了对 WinRT (Windows Runtime) 的底层支持,不再支持直接引用 .winmd 文件。移除的原因如 Breaking change: Built-in support for WinRT is removed from .NET - .NET Microsoft Docs 所说

由此在使用 WinRT 自带 Windows.Media.Ocr 的第一步是让 WPF 在 dotnet 6 框架上支持 WinRT 开发

在 dotnet 6 下,使用方法特别简单,只需要编辑 csproj 项目文件,在 TargetFramework 上,将原本的 net6.0-windows 的后面加上期望使用的 WinRT 的 SDK 版本,例如 19041 版本,更改后的代码如下

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<OutputType>WinExe</OutputType>
</PropertyGroup> </Project>

对应的 SDK 版本和所支持的系统的关系如 Call Windows Runtime APIs in desktop apps - Windows apps Microsoft Docs 描述:

  • net6.0-windows10.0.17763.0: 对应 Windows 10 1809 版本
  • net6.0-windows10.0.18362.0: 对应 Windows 10 1903 版本
  • net6.0-windows10.0.19041.0: 对应 Windows 10 2004 版本

开发过 UWP 的伙伴都知道,这里的 SDK 版本指的是目标版本。例如设置为 19041 对应的 Windows 10 2004 版本,而如果期望在更低的 Win10 版本,例如 1809 上运行,可以再指定一个最低版本,加上以下配置

   <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>

更改后的 csproj 项目文件的内容如下

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<OutputType>WinExe</OutputType>
</PropertyGroup>
</Project>

如以上步骤,即可完成对接 WinRT 的支持。其支持的原理也特别有趣,是通过给你引用一个叫 Microsoft.Windows.SDK.NET.dll 的 23 MB 以上的 dll 和一个叫 WinRT.Runtime.dll 的文件实现的

在 Microsoft.Windows.SDK.NET.dll 实现了对 WinRT 的一层包装,如此可以看到 WinRT 是多么庞大,只是对他的定义的包装,还没有包含实现,就有 23 MB 这么多

完成了对接 WinRT 之后,接下来就可以开始编写图片识别文本的功能了

假定已获取到图片文件 file 的文件路径,在对此图片进行转换为文本时,可以分为三步:

第一步解码图片文件

开始解码之前,需要从 file 文件路径读取出 IRandomAccessStream 对象,这个 IRandomAccessStream 对象表示的是一个 Stream 且此 Stream 支持随机访问。随机访问是和顺序访问相对,指的是可以从 Stream 的任意地方开始读写

        using IRandomAccessStream stream = await FileRandomAccessStream.OpenAsync(file, Windows.Storage.FileAccessMode.Read);

读取到了 IRandomAccessStream 对象,即可采用 Windows.Graphics.Imaging.BitmapDecoder 进行解码,在解码器里面将会自动识别图片文件是什么编码。如果感觉识别不靠谱,也可以自己传入指定的编码格式

        // 解码图片
var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream);

自己指定编码是通过传入对应编码的 GUID 值,此 GUID 值对应 WIC 层的定义,也就是说底层也是调用 WIC 层解码。如以下代码,传入指定 png 编码

        var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(Windows.Graphics.Imaging.BitmapDecoder.PngDecoderId, stream);

解码完成之后即可通过 GetSoftwareBitmapAsync 方法获取 Windows.Graphics.Imaging.SoftwareBitmap 对象,这就是一个在 WinRT 里面用来表示图片的一个对象

        // 获取图像
Windows.Graphics.Imaging.SoftwareBitmap? softwareBitmap = await decoder.GetSoftwareBitmapAsync();

第二步是判断本机的 OCR 引擎是否支持指定的语言。相当于判断设置里面的语言是否有对应的选项支持

例如已知识别的是中文的图片,可以先通过 OcrEngine.IsLanguageSupported 判断是否支持简体中文识别

        // 准备识别
Windows.Globalization.Language lang = new Windows.Globalization.Language("zh-CN");
// 判断是否支持简体中文识别
if (Windows.Media.Ocr.OcrEngine.IsLanguageSupported(lang))
{
// 如果支持识别才能继续
}

如果本机系统不支持,那就只能告诉用户,你的电脑不支持识别,然后咱的应用就啥都做不了

如果本机系统支持,那就可以开始创建识别引擎

            var engine = Windows.Media.Ocr.OcrEngine.TryCreateFromLanguage(lang);
if (engine != null)
{
}

以上是尝试创建,其实如果上面的判断通过了,那基本上都是成功的。那为什么不采用一句话判断加创建?原因是创建的代码是比较消耗资源的,判断的代码是比较快速的,完全看自己的业务

第三步就是本文的重点,开始进行识别

                OcrResult? result = await engine.RecognizeAsync(softwareBitmap);

如此即可完成识别,这个识别速度我测试是非常快的。实际的识别和具体的图片和设备有关

这里拿到的 OcrResult 可以通过 Text 属性获取到识别的文本,如以下代码,将获取的文本放入到一个 TextBox 控件

                OcrText.Text = result.Text;

如果需要获取对应在图片上的每个字符所在的图片的坐标,可以采用高级的用法,遍历 OcrResult 的 Lines 属性,如以下代码

                foreach (OcrLine line in result.Lines)
{
foreach (var word in line.Words)
{
// 识别的字符所在相对图片的坐标和尺寸
Windows.Foundation.Rect bounds = word.BoundingRect;
var text = word.Text;
}
}

以上就是在 WPF 通过 WinRT 调用系统自带的图片转文本功能,此功能不需要依赖其他第三方,但是依赖用户的系统环境,此功能免费,且使用简单

本文代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin d2959ab2d217d57e9357684d7bf39510e4d9cae8

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 JagerekukibeHelcewhalay 文件夹

WPF 使用 Win10 的 WinRT 自带 Windows.Media.Ocr 实现图片转文本的更多相关文章

  1. win7自带windows media player 已停止工作

    解决方法如下: 在计算机开始,菜单找到控制面板 ,然后打开程序和功能,选择打开或关闭window功能,媒体功能.再取消windows Media Center Windows MediaPlayer选 ...

  2. win10 如何关掉自带的杀毒软件 window defender

    问题描述: win10系统,自带的杀毒软件 window defender 会实时保护电脑对文件进行检测,将认为的病毒文件自动清除, 造成我想下载的MDK5的注册机一直下载不成功,即使从别处拷贝过来, ...

  3. WPF进阶教程 - 使用Decorator自定义带三角形的边框

    原文:WPF进阶教程 - 使用Decorator自定义带三角形的边框 写下来,备忘. Decorator,有装饰器.装饰品的意思,很容易让人联想到设计模式里面的装饰器模式.Decorator类负责包装 ...

  4. WPF实现Win10汉堡菜单

    WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织 前言 有小伙伴提出需要实现Win10汉堡菜单效果. 由于在WPF中没有现成的类似UWP的汉堡菜单,所以我们 ...

  5. win10如何一键开启关闭windows Defender(亲测有效)

    win10如何一键开启关闭windows Defender(亲测有效) 一.总结 一句话总结:各种找资料如何开启关闭都没用,直接下载软件简单方便 软件 因为我关windows defender是用的一 ...

  6. Win10巧用自带输入法轻松打出特殊字符

    给电脑输入信息时,如果要用上键盘上没有的特殊符号,那就为难了.其实,在Win10中,自带的微软拼音就能让你轻松输入键盘上没有的符号.下面来看看Win10如何输入特殊符号. 微软拼音不但中文输入智能化做 ...

  7. 解决Win10电脑右下角的“激活windows转到电脑设置”的水印的方法

    Win10正式版的用户反馈新系统在使用一段时候后,自己电脑桌面右下角就突然出现了“激活windows10转到设置以激活windows”的水印字样.这是怎么回事呢?下面,我就向大家分享win10电脑右下 ...

  8. WPF System.InvalidCastException: 无法将类型为“System.Windows.Media.Color”的对象强制转换为类型“System.Windows.Media.Brush”。

    场景:添加ComboBox样式,界面卡死,日志异常文件如下: -- ::, | ERROR | System.InvalidCastException: 无法将类型为“System.Windows.M ...

  9. WPF 问题 PresentationCore.dll!System.Windows.Media.Composition.DUCE.Channel.SyncFlush() 分析

    错误信息: 没有足够的内存继续执行程序 在 System.Windows.Media.Composition.DUCE.Channel.SyncFlush() 在 System.Windows.Int ...

  10. 背水一战 Windows 10 (27) - 控件(文本类): TextBlock

    [源码下载] 背水一战 Windows 10 (27) - 控件(文本类): TextBlock 作者:webabcd 介绍背水一战 Windows 10 之 控件(文本类) TextBlock 示例 ...

随机推荐

  1. Android线程池封装库

    目录介绍 1.遇到的问题和需求 1.1 遇到的问题有哪些 1.2 遇到的需求 1.3 多线程通过实现Runnable弊端 1.4 为什么要用线程池 2.封装库具有的功能 2.1 常用的功能 3.封装库 ...

  2. 三维模型3DTile格式轻量化压缩处理重难点分析

    三维模型3DTile格式轻量化压缩处理重难点分析 在对三维模型3DTile格式进行轻量化压缩处理的过程中,存在一些重要而又困难的问题需要解决.以下是几个主要的重难点: 1.压缩率和模型质量之间的平衡: ...

  3. 记录--用了那么久的Vue,你了解Vue的报错机制吗?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助   Vue的5种处理Vue异常的方法 相信大家对Vue都不陌生.在使用Vue的时候也会遇到报错,也会使用浏览器的F12 来查看报错信息.但 ...

  4. 记录--webpack和vite原理

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 每次用vite创建项目秒建好,前几天用vue-cli创建了一个项目,足足等了我一分钟,那为什么用 vite 比 webpack 要快 ...

  5. kali2.0 metasploit安装

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_40943540/arti ...

  6. verilog之display

    verilog之display 1.函数简介 $display是用于显示不同格式的变量的函数,用于测试过程中观察数据数据的特点.该观测不如波形图直观,但是如果可以详细的设置好观测点,有时可以达到事半功 ...

  7. 复现YOLO-of-RoboMaster-Keypoints-Detection-2023

    开源仓库地址: https://github.com/zRzRzRzRzRzRzR/YOLO-of-RoboMaster-Keypoints-Detection-2023 该仓库提供了数据集,目前只是 ...

  8. KingbaseES 原生XML系列三--XML数据查询函数

    KingbaseES 原生XML系列三--XML数据查询函数(EXTRACT,EXTRACTVALUE,EXISTSNODE,XPATH,XPATH_EXISTS,XMLEXISTS) XML的简单使 ...

  9. 花式栈溢出 CTFshowpwn88

    花式栈溢出 在这之前确实对这方面了解很少,一般这种花式栈溢出不仅仅要求你能发现漏洞,最主要的是你要有随机应变的能力 这个题是一个64位的题目看一下保护 canary 和 nx保护都开了,我们用ida打 ...

  10. #排列组合#CF1081C Colorful Bricks

    题目 一共 \(n\) 块砖排成一排,把每块砖涂成 \(m\) 种颜色中的一种, 其中恰有 \(k\) 块颜色与其左边的那块砖不同(不包括第一块),问涂色方案数,对 \(998244353\) 取模. ...