百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

使用.NET开发一个屏幕OCR工具

xsobi 2024-12-08 19:33 1 浏览

本文将介绍使用.NET开发的一款桌面截图 OCR 工具,软件已开源,地址:https://github.com/sangyuxiaowu/Snipping_OCR

背景

因为不同地方人们的使用习惯不同,国内可能截图更多的是使用QQ,微信等即时聊天工具提供的截图功能。所以我们竟然可能会遇到这样的场景:按了截图快捷键却发现并没有任何反应,尝试了多次才意识到 —— 没有开聊天软件。

当我们需要OCR识别时也是经常通过这些社交软件,QQ可以在电脑端使用,微信的文字识别却是需要在手机端识别后发给电脑端。


QQ截图OCR


作为一个老年人,QQ 已经不怎么用了,而且 QQ 文字识别的结果复制编辑不是很方便。并且针对保密级别比较高的工作,我们还是更倾向于离线的 OCR 工具。

软件的实现

软件的设计非常简单,通过调用 Windows 系统本身的截图功能,在用户截图后,从剪贴板获取到图片后通过 PaddleOCRSharp 来进行 OCR 的识别,然后将结果输出。

软件的难点之一其实调用系统的截图,中间的波折可以查看今天推送的另一篇文章《为应用添加截图功能》。

OCR 识别已经非常成熟了,百度开源的 PaddleOCR 框架相对 Tesseract 中文识别的效果好太多太多了。得益于开源项目 PaddleOCRSharp[1] 对C++代码修改并封装的.NET的工具类库,我们可以方便的在 .NET 项目中实现 OCR 功能。

var ocrResult = new OCRResult();using PaddleOCREngine engine = new PaddleOCREngine(, new OCRParameter());ocrResult = engine.DetectText(imgfile);

ocrResult 的返回结果是带坐标位置的,我们可以通过对其进行进一步的处理实现比如身份证的 OCR 识别。

若想使用其开发 WebAPI ,之前版本可以直接返回 ocrResult,最近某次更新版本后直接返回数据都是空的,可做如下数据处理:

List<Json_TextBlock> res = new List<Json_TextBlock>();foreach(var item in ocrResult.TextBlocks){ var points = new List<object>();
foreach (var p in item.BoxPoints) { points.Add(new { p.X, p.Y }); }
res.Add(new Json_TextBlock { Score = item.Score, BoxPoints = points, Text = item.Text });}
// 处理适配新版本的 json 问题/// <summary>/// 识别的文本块/// </summary>public class Json_TextBlock{ public List<object> BoxPoints { get; set; } = new List<object>(); public string Text { get; set; } /// <summary> /// 置信度 /// </summary> public float Score { get; set; }}

软件使用


Snipping_OCR


可以前往 Github 或 Gitee 下载 https://gitee.com/sang93/Snipping_OCR/releases/

双击 Snipping_OCR.exe 启动软件,最小化按钮可将其最小化到系统托盘,关闭则为退出软件,最小化后双击托盘可显示主界面。

软件启动会尝试注册全局热键 Ctrl + Alt + A 可以使用该热键来启动截图识别,暂时不支持修改设置,若快捷无法正常使用,可以使用其他软件或者系统自带的截图工具 “Win + Shift + S”截图后,在托盘使用右键菜单 “识别剪贴板”来进行 OCR 识别。


识别剪贴板


可以将图片拖放到左边空白区域来识别,复制图片文件后也可以在托盘使用右键菜单 “识别剪贴板”来进行 OCR 识别。

References

[1] PaddleOCRSharp: https://github.com/raoyutian/PaddleOCRSharp


相关推荐

js向对象中添加元素(对象,数组) js对象里面添加元素

一、添加一个元素对象名["属性名"]=值(值:可以是一个值,可以是一个对象,也可以是一个数组)这样添加进去的元素,就是一个值或对象或数组...

JS小技巧,如何去重对象数组?(一)

大家好,关于数组对象去重的业务场景,想必大家都遇到过类似的需求吧,这对这样的需求你是怎么做的呢。下面我就先和大家分享下如果是基于对象的1个属性是怎么去重实现的。方法一:使用.filter()和....

「C/C++」之数组、vector对象和array对象的比较

数组学习过C语言的,对数组应该都不会陌生,于是这里就不再对数组进行展开介绍。模板类vector模板类vector类似于string,也是一种动态数组。能够在运行阶段设置vector对象的长度,可以在末...

如何用sessionStorage保存对象和数组

背景:在工作中,我将[{},{}]对象数组形式,存储到sessionStorage,然后ta变成了我看不懂的形式,然后我想取之用之,发现不可能了~记录这次深刻的教训。$clickCouponIndex...

JavaScript Array 对象 javascript的array对象

Array对象Array对象用于在变量中存储多个值:varcars=["Saab","Volvo","BMW"];第一个数组元素的索引值为0,第二个索引值为1,以此类推。更多有...

JavaScript中的数组Array(对象) js array数组

1:数组Array:-数组也是一个对象-数组也是用来存储数据的-和object不同,数组中可以存储一组有序的数据,-数组中存储的数据我们称其为元素(element)-数组中的每一个元素都有一...

数组和对象方法&amp;数组去重 数组去重的5种方法前端

列举一下JavaScript数组和对象有哪些原生方法?数组:arr.concat(arr1,arr2,arrn);--合并两个或多个数组。此方法不会修改原有数组,而是返回一个新数组...

C++ 类如何定义对象数组?初始化数组?linux C++第43讲

对象数组学过C语言的读者对数组的概念应该很熟悉了。数组的元素可以是int类型的变量,例如int...

ElasticSearch第六篇:复合数据类型-数组,对象

在ElasticSearch中,使用JSON结构来存储数据,一个Key/Value对是JSON的一个字段,而Value可以是基础数据类型,也可以是数组,文档(也叫对象),或文档数组,因此,每个JSON...

第58条:区分数组对象和类数组对象

示例设想有两个不同类的API。第一个是位向量:有序的位集合varbits=newBitVector;bits.enable(4);bits.enable([1,3,8,17]);b...

八皇后问题解法(Common Lisp实现)

如何才能在一张国际象棋的棋盘上摆上八个皇后而不致使她们互相威胁呢?这个著名的问题可以方便地通过一种树搜索方法来解决。首先,我们需要写一个函数来判断棋盘上的两个皇后是否互相威协。在国际象棋中,皇后可以沿...

visual lisp修改颜色的模板函数 怎么更改visual studio的配色

(defunBF-yansemokuai(tuyuanyanse/ss)...

用中望CAD加载LISP程序技巧 中望cad2015怎么加载燕秀

1、首先请加载lisp程序,加载方法如下:在菜单栏选择工具——加载应用程序——添加,选择lisp程序然后加载,然后选择添加到启动组。2、然后是添加自定义栏以及图标,方法如下(以...

图的深度优先搜索和广度优先搜索(Common Lisp实现)

为了便于描述,本文中的图指的是下图所示的无向图。搜索指:搜索从S到F的一条路径。若存在,则以表的形式返回路径;若不存在,则返回nil。...

两个有助于理解Common Lisp宏的例子

在Lisp中,函数和数据具有相同的形式。这是Lisp语言的一个重大特色。一个Lisp函数可以分析另一个Lisp函数;甚至可以和另一个Lisp函数组成一个整体,并加以利用。Lisp的宏,是实现上述特色的...