推荐 TesseractOCR.NET:它基于 tesseract 5.3+,中文识别准确率高,支持精细控制;而 Windows.Media.Ocr 仅限 WinUI/UWP,WinForms/WPF 不兼容。

用什么库最靠谱:Tesseract.NET 还是 Windows.Media.Ocr?
Windows 自带的 Windows.Media.Ocr 简单、免部署、支持多语言,但仅限 UWP/WinUI 应用,桌面 WinForms/WPF 项目直接引用会报错 System.Runtime.InteropServices.COMException: 操作未被指定的接口支持。真要跑在传统 .NET Desktop 上,得选封装了 Tesseract 的库,比如 Tesseract.NET(注意不是官方 Tesseract,而是 Charlie Poole 维护的旧版)或更现代的 TesseractOCR.NET(基于原生 tesseract 5.x,推荐)。
关键区别在于:前者依赖老旧的 tesseract 3.x 引擎,识别中文需手动加载 chi_sim.traineddata;后者默认绑定 tesseract 5.3+,对简体中文识别准确率高不少,且支持 PageSegMode 和 OcrEngineMode 精细控制。
- WinForms/WPF 项目 → 用
TesseractOCR.NET,NuGet 安装TesseractOCR.NET包,它会自动拉取对应平台的原生 tesseract dll - WinUI 3 / UWP → 直接用
OcrEngine.TryCreateFromLanguage,无需额外模型文件,但语言必须已安装系统级 OCR 支持(如“中文(简体)”需在 Windows 设置 → 语言中启用) - 别碰
MODI或Microsoft Office Document Imaging——XP 时代遗留组件,Win10/11 已彻底移除
图像预处理不做好,识别结果全是乱码
OCR 不是万能照相机,输入图像是灰度模糊、倾斜、低对比度的,RecognizeAsync 或 Recognize 返回的 Text 很可能为空,或夹杂大量 和乱序字符。Tesseract 对二值化敏感,原始截图/手机拍的照片几乎都需要预处理。
实操上,用 SkiaSharp 做轻量级处理比 OpenCV 轻便得多(尤其对 .NET 开发者):
- 先转灰度:
SKImage.FromBitmap(bitmap).ToRaster().ToImage()+SKColorFilter.CreateMatrix调灰度矩阵 - 再二值化:用
SKShader.CreatePicture配合阈值滤镜,或直接用SKImage.ToPixelBytes()手动遍历像素点做阈值分割(建议阈值设为 128~150,太低留噪点,太高丢笔画) - 倾斜校正:调用
SKImage.GetBounds()后用霍夫线检测主文本行角度,再用SKMatrix.Rotate旋转 —— 这步很多人跳过,但斜 3° 以上文字识别率断崖下跌
中文识别总出错?模型路径和语言代码必须严格匹配
装好 TesseractOCR.NET 后,如果只传 "chi_sim" 却没放对模型文件,会抛 TesseractNotFoundException: Could not load language data for 'chi_sim'。这不是代码问题,是路径或命名错了。
模型文件必须放在可读目录,并且名字不能写错:
- 下载地址固定为:
https://github.com/tesseract-ocr/tessdata_best(别用tessdata主干分支,简体中文识别差一倍) - 下载
chi_sim.traineddata(不是chi_sim_vert,也不是chinese-sim),放到项目目录如./tessdata/ - 初始化时路径必须绝对或相对于当前工作目录:
new TesseractEngine("./tessdata", "chi_sim", EngineMode.Default)—— 注意是"chi_sim",不是"zh"或"chs" - 若仍报错,用
ProcessMonitor查看进程是否真的在读这个路径,常见坑是发布后./tessdata没随 exe 复制过去
识别速度慢、内存暴涨?别让 Tesseract 实例反复创建
TesseractEngine 初始化成本很高(加载模型、分配内存池),每次识别都 new 一个,CPU 占用飙升,GC 压力大,连续识别 10 张图可能卡死 UI。它本就是线程安全、可复用的对象。
- 全局单例:在
Program.cs或窗体类静态字段里初始化一次,重复用engine.Process(...) - 别把
IDisposable当银弹:虽然它实现了IDisposable,但Dispose()只清理内部资源,不禁止后续调用;提前 Dispose 反而引发ObjectDisposedException - 并发识别要用
Page级隔离:每个engine.Process()调用生成独立Page,可并行,但别共用同一个Page实例 - 内存泄漏信号:任务管理器里 dotnet.exe 私有工作集持续增长 >500MB,大概率是
TesseractEngine创建太随意
底层原理其实就一句话:Tesseract 是 C++ 引擎,.NET 封装只是 P/Invoke 桥梁,所有性能瓶颈都在模型加载、图像尺寸、PageSegMode 设置这三处。其他花哨 API,都是障眼法。











