news 2026/6/10 16:03:14

C#AI系列(6): C#离线实现高效OCR

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#AI系列(6): C#离线实现高效OCR

幅提升。

在C#中调用Tesseract (https://github.com/tesseract-ocr/tesseract) 有两个方式:

命令行调用:带参数执行 tesseract.exe 文件,读取控制台获取解析结果。适合简单直观,不需要写代码,直接在终端输入命令即可,且跨语言通用。

Wrapper调用:使用封装好的C#库直接调用相关函数。适合深度集成,提高性能,减少出错。

命令行调用及参数网上已有很好的详细说明(如https://tesseract-ocr.cn/tessdoc/Command-Line-Usage.html),本文不再赘述(已经包含在仓库项目文件中了噢)。

下面我们通过Wrapper调用的方式来使用Tesseract。C# 目前比较好用的Wrapper有同名的Tesseract(https://github.com/charlesw/tesseract, A .NET wrapper for tesseract-ocr 5.2.0.),在Nuget直接拉取可得到包含运行时和Wrapper库的完整程序,直接开箱即用。

二、Tesseract模型准备

执行OCR之前,要准备训练好模型,可以在官方仓库找到(https://github.com/tesseract-ocr/tessdata_best,https://github.com/tesseract-ocr/tessdata_fast),都是免费。

其中语言类模型(language .traineddata)能直接下载的 100 多种,命名规则就是“语言代码[+方向/变体]”。常用举例的有 eng、chi_sim、chi_tra、jpn、kor、rus、ara、deu、fra、spa、lat 等。另外就是垂直排版变体 chi_sim_vert、chi_tra_vert、jpn_vert、kor_vert, 其他特殊格式等:frak(德文花体)、equ(数学公式)、osd。

image

三、"四行代码"实现OCR

3.1 核心代码

核心代码就四行,非常简单,代码及注释如下:

// 1. 创建引擎实例(参数:语言包、数据路径)

using (var engine = new TesseractEngine(tessDataPath, "chi_sim + eng", EngineMode.LstmOnly))

{

// 2. 加载图像

using (var img = Pix.LoadFromFile(imgPath))

{

// 3. 创建页面对象

using (var page = engine.Process(img, PageSegMode.Auto))

{

// 4. 获取识别结果

Console.WriteLine("识别结果:\n" + page.GetText());

}

}

}

3.2 模型参数

模型加载时可同时加载多个语言,与命令行参数相似,直接用“+”拼接即可,如"eng + chi_sim + osd"。

3.3 引擎模式

EngineMode,对应命令行参数(OEM,--oem N)。4 选 1,决定用哪套“底层引擎”:

0: 仅传统引擎(tesseract 3 时代)

1: 仅 LSTM 神经网络(tesseract 4+ 主推)

2: 二者都跑,再合并结果

3: 自动选择(默认,通常等于 1)

3.4 页面分割模式

PageSegMode,对应命令行参数(--psm N)

共 14 个等级(0-13),决定 Tesseract 把图像当成什么版式来处理:

0: OSD only

1: 自动分栏 + OSD

2: 自动分栏,但不做 OSD 也不 OCR(未实现)

3: 完全自动分栏,默认模式

4: 单列可变尺寸文本

5: 单一垂直文本块

6: 单一统一文本块

7: 单行

8: 单个单词

9: 圆圈内的单个单词

10: 单个字符

11: 稀疏文本(无顺序)

12: 稀疏文本 + OSD

13: 原始行(绕过 Tesseract 特殊调整)

3.5 注意事项

根据实际需求选择合适的模型来OCR,eng对标点符号的处理比较好,一般均可以带上。如果是识别车牌照文本,或无规律的文本,则需要自行考虑改变页面分割模式,非常影响识别效果。

普通文本OCR如下:

image

结果:

image

四 扩展应用

4.1 文本块坐标导出及分级处理

遍历page的内部,按block、或word分级获取ocr结果的语言、文本及坐标,这样可以更好辅助实现证件信息读取

using (var iter = page.GetIterator())

{

iter.Begin();

do

{

do

{

do

{

do

{

if (iter.IsAtBeginningOf(PageIteratorLevel.TextLine))

{

iter.GetImage(PageIteratorLevel.TextLine, 0,out var x,out var y);

Console.WriteLine($"<BLOCK> ({x},{y}): {iter.GetWordRecognitionLanguage()}");

}

Console.Write(iter.GetText(PageIteratorLevel.Word));

Console.Write(" ");

if (iter.IsAtFinalOf(PageIteratorLevel.TextLine, PageIteratorLevel.Word))

{

Console.WriteLine();

}

} while (iter.Next(PageIteratorLevel.TextLine, PageIteratorLevel.Word));

if (iter.IsAtFinalOf(PageIteratorLevel.Para, PageIteratorLevel.TextLine))

{

Console.WriteLine();

}

} while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.TextLine));

} while (iter.Next(PageIteratorLevel.Block, PageIteratorLevel.Para));

} while (iter.Next(PageIteratorLevel.Block));

}

效果如下:

image

识别后,每个block后面的数字表示当前文本矩形框的左上角xy坐标

image

4.2 pdf生成

生成导入图像的pdf文件,且pdf中OCR内容区域的文本可被拾取。

using (IResultRenderer renderer = Tesseract.PdfResultRenderer.CreatePdfRenderer(@"test.pdf", tessDataPath, false))

{

// PDF Title

using (renderer.BeginDocument("Serachablepdftest"))

{

using (TesseractEngine engine = new TesseractEngine(tessDataPath, "chi_sim+eng", EngineMode.Default))

{

using (var img = Pix.LoadFromFile(imgPath))

{

using (var page = engine.Process(img, "Serachablepdftest"))

{

renderer.AddPage(page);

}

}

}

}

}

效果如下:

image

转成pdf文件后的文字拾取效果:

image

五、单文件打包问题

单文件发布时,可能存在发布成功,但运行程序出现错误的问题。这个与wrapper在加载运行时过程中的文件路径及处理有关。

本项目中对这个wrapper进行了处理,将原来动态加载的非托管库直接写死为win环境下的x64了,这样就可以很好的单文件发布(13.4mb + 模型)及aot发布(3mb + 2.6mb + 4mb + 模型)。

修改后的tesseract(wrapper)可以在仓库里找到。

算上chi_sim和eng模型,所有必须文件加起来独立运行无依赖,一共40mb。

六、 最后

有了tesseract,C#实现ocr也是很方便的事情。简单ocr再也不需要花钱注册会员来整了,随便自己或找个身边的程序员编译下,分分钟就搞定。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 17:37:26

通过企业微信ipad协议接口查询群成员信息

请求方式POSTContentType:”application/json”参数参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信请求示例{"uuid":"3240fde0-45e2-48c0-90e8-cb098d0ebe43","roomid":1069XXXX5016166}返回示例{"…

作者头像 李华
网站建设 2026/6/10 15:43:02

JSP中如何设计大文件上传的加密存储方案?

我&#xff0c;一个负责过30企业级文件传输项目的上海IT人&#xff0c;想和你聊聊这个100G大文件传输的落地方案 先抛结论&#xff1a;这事儿能成&#xff0c;但得用“定制化研发成熟组件适配”的组合拳。作为公司项目负责人&#xff0c;我刚带着团队啃完类似需求&#xff08;…

作者头像 李华
网站建设 2026/6/10 3:14:47

网页前端如何利用JS实现100G文件分块上传?

武汉光谷XX软件公司大文件传输组件选型与自研方案 一、项目背景与需求分析 作为武汉光谷地区专注于软件研发的高新技术企业&#xff0c;我司长期服务于政府和企业客户&#xff0c;在政务信息化、企业数字化转型等领域积累了丰富的经验。当前&#xff0c;我司核心产品面临大文…

作者头像 李华
网站建设 2026/6/10 12:50:42

数学建模优秀论文算法-高斯过程回归

高斯过程回归&#xff08;GPR&#xff09;小白入门教程 0. 引言&#xff1a;为什么需要高斯过程回归&#xff1f; 在机器学习中&#xff0c;回归任务的目标是用已知数据拟合一个函数&#xff0c;预测新输入的输出。传统方法&#xff08;如线性回归、多项式回归&#xff09;存在…

作者头像 李华
网站建设 2026/6/10 4:39:40

数学建模优秀论文算法-深度生存网络

深度生存网络入门教程&#xff1a;从生存分析到端到端建模 引言 在医疗、金融、工业等领域&#xff0c;我们常关注**“事件发生时间”**问题&#xff1a; 医疗&#xff1a;癌症患者的生存期&#xff08;“多久会去世”&#xff09;&#xff1b;金融&#xff1a;客户的违约时间&…

作者头像 李华
网站建设 2026/6/9 22:06:51

基于python的大众点评数据爬取分析和推荐系统

基于Python的大众点评数据爬取分析和推荐系统 第一章 系统开发背景与核心意义 大众点评作为本地生活服务核心平台&#xff0c;汇聚了餐饮、休闲、购物等海量商家信息与亿级用户评论&#xff0c;这些数据承载着用户消费偏好、商家服务质量等核心价值。但当前存在明显痛点&#x…

作者头像 李华