PaddleOCRSharp如何加载自己的模型

PaddleOCRSharp 是基于百度飞桨 PaddleOCR 打造的 C# 版 OCR 识别库,凭借轻量、高效、跨平台的特性,成为.NET 开发者实现文字识别的优选工具。官方默认提供了通用的中、英、多语言识别模型,能满足大部分基础场景需求,但在证件识别、行业票据、特定字体等个性化场景下,通用模型的识别精度会大幅下降。此时将 PaddleOCRSharp 适配自研的定制化模型,成为提升专属场景识别效果的关键。本文将从模型准备、配置调整、代码实现到常见问题排查,全方位讲解 PaddleOCRSharp 使用自定义模型的完整流程,帮助.NET 开发者快速落地专属 OCR 识别需求。

一、前置准备

在使用自定义模型前,需完成基础环境和工具的配置,确保开发环境与 PaddleOCRSharp 的运行要求匹配,同时做好自定义模型的格式校验。

1.1 开发环境要求

框架:.NET Framework 4.0 及以上 /.NET Core 6.0以上

操作系统:Windows(x86/x64)

依赖库:已安装 PaddleOCRSharp NuGet 包

运行库:需将 PaddleOCRSharp 对应的paddle_inference运行库)放置在项目输出目录,官方包会自动携带,若缺失可从 PaddleOCRSharp 仓库下载。

1.2 自定义模型的格式要求

PaddleOCRSharp 仅支持PaddlePaddle 的推理模型(inference model),不支持训练过程中的预训练模型、检查点模型,自定义模型需满足以下规范,这是模型能被加载的核心前提:

模型结构:需包含 PaddleOCR 标准的检测模型(det)、识别模型(rec),若需方向检测则增加方向分类模型(cls),三者为 PaddleOCR 的标准流水线,缺一不可(若无需方向分类,可在配置中关闭);

文件组成:

旧版格式模型每个模型需包含 3 个核心文件 inference.pdmodel、inference.pdiparams、inference.pdiparams.info;识别模型需要额外字典文件,例如:ppocr_keys.txt。

 

新版格式模型每个模型需包含 3 个核心文件 inference.json、model.pdiparams、inference.yml;新版格式不需要额外的字典文件,字典存于识别模型的inference.yml中。缺少任一文件可能会导致模型加载失败;

 

字典文件:若自定义模型的识别字典与官方通用字典不同(如行业专属词汇、自定义字符集),需准备对应的dict.txt字典文件,确保识别结果与字符集匹配。

1.3 项目目录规划

为方便管理自定义模型和配置文件,建议按分类存放模型的原则规划项目目录,避免文件路径混乱导致的加载错误,推荐目录结构如下(可根据实际需求调整):

OCRProject/

├─ bin/Release/net6.0/  # 项目输出目录,存放运行库、模型文件

│  ├─ inference/ # 包含PaddleOCRSharp默认的模型和配置文件

│  ├─ custom_model/     # 自定义模型根目录

│  │  ├─ det/           # 自定义检测模型(含3个核心文件)

│  │  ├─ rec/           # 自定义识别模型(含3个核心文件)

│  │  ├─ cls/           # 自定义方向分类模型(可选,含3个核心文件)

│  │  └─ dict.txt       # 自定义模型对应的字典文件

│  └─ PaddleOCRSharp.dll# 核心OCR库文件,包含opencv、paddle等必要依赖文件

└─ Program.cs           # 核心代码实现文件

注意:发布项目时,需将custom_model整个目录复制到项目输出目录,确保程序运行时能正确读取模型文件,路径建议使用相对路径,避免绝对路径导致的跨环境运行问题。

二、核心步骤:使用自定义模型实现 OCR 识别

PaddleOCRSharp 加载自定义模型的核心逻辑是通过配置类指定自定义模型的路径、配置自定义字典,而非修改源码。整个流程分为模型文件部署、配置类参数调整、代码编写实现识别三步,以下以.NET 6 控制台项目为例,讲解完整实现过程,WinForm/WPF/ASP.NET Core 项目的实现逻辑一致,仅界面交互部分不同。

步骤 1:部署自定义模型文件

将训练好的推理模型按上述目录规划,复制到项目输出目录的custom_model子目录中,确保检测、识别(可选方向分类)模型的 3 个核心文件完整,同时将自定义dict.txt字典文件放在custom_model根目录。

步骤 2:调整 PaddleOCRSharp 配置类参数

PaddleOCRSharp 通过OCRModelConfig类统一管理 OCR 的所有模型配置,OCRParameter类统一管理相关配置参数。使用自定义模型的关键是修改默认路径,指定自定义模型的相对 / 绝对路径。

配置项调整原则

模型路径需指向模型所在目录,而非具体模型文件,PaddleOCRSharp 会自动读取目录下的 3 个核心模型文件;底层自动检测和加载model或者inference文件名的模型。

步骤 3:编写核心代码实现自定义模型的 OCR 识别

基于调整后的OCRModelConfig配置类,结合 PaddleOCRSharp 的PaddleOCR核心类,即可实现自定义模型的文字识别。以下提供完整可运行的代码示例,包含图片文件识别和图片流识别两种常用场景。

说明:本示例实际仍用的是PP_OCR_v5_Mobile模型,仅修改模型文件夹来作为演示模型。

PaddleOCRSharp版本采用v5.1+Paddle.Runtime.win_x64 v3.1.0.1

完整代码示例

using System;
using System.IO;
using System.Linq;

using PaddleOCRSharp;
namespace OCRProject
{
    internal class Program
    {
        static PaddleOCREngine engine;
        
        static void Main(string[] args)
        {
            try
            {


                //新建一个模型配置对象
                OCRModelConfig modelConfig = new OCRModelConfig();

                //获取程序根目录
                string rootPath = AppContext.BaseDirectory;
                //asp.net framework的根目录在bin文件夹下
                //rootPath = Path.Combine( AppContext.BaseDirectory,"bin");
                //获取程序根目录下自定义模型的文件夹目录
                string modelPath = Path.Combine(rootPath, "custom_model");
                modelConfig.det_infer = Path.Combine(modelPath, "det");
                modelConfig.cls_infer = Path.Combine(modelPath, "cls");
                modelConfig.rec_infer = Path.Combine(modelPath, "rec");
                //如果是新格式模型,这里keys不为空即可。
                modelConfig.keys = Path.Combine(modelPath, "dict.txt");
                //新建一个参数配置对象,具体参数的描述和缺省值详见:https://gitee.com/raoyutian/PaddleOCRSharp/blob/master/doc/UseInCsharp.md
                OCRParameter oCRParameter = new OCRParameter();
                
                //使用modelConfig加载自定义模型,oCRParameter参数
                //engine = new PaddleOCREngine(modelConfig, oCRParameter);

                //使用modelConfig加载自定义模型,custom.json配置文件参数(推荐,修改参数不用修改代码部署后仍能修改配置)
                string parameterjsonfile = Path.Combine(modelPath, "custom.json");
                string parameterjson = File.ReadAllText(parameterjsonfile);
                engine = new PaddleOCREngine(modelConfig, parameterjson);
                //使用文件路径参数
                //有其他重载方法,如bitmp、byte数组,base64、cvMat 指针、bitmp指针

                string imagefile= Path.Combine(rootPath, "image","test.jpg");
                OCRResult result= engine.DetectText(imagefile);

                //使用bytes参数
                //var bytes=  File.ReadAllBytes(imagefile);
                //engine.DetectText(bytes);

                //使用Bitmap参数
                //var bmp=new Bitmap() ;
                //engine.DetectText(bmp);

                //OCRResult类具体描述详见:https://gitee.com/raoyutian/PaddleOCRSharp/blob/master/doc/UseInCsharp.md
                if (result!=null && result.TextBlocks!=null)
                {
                    //result.Text默认是对所有文本框进行拼接的字符串,没有空格换行等
                    Console.WriteLine("识别结果:\n" + result.Text);

                    //result.JsonText是底层原始json格式的字符串,result.TextBlocks是根据result.JsonText反序列化得到的对象
                    Console.WriteLine("识别结果(json):\n" + result.JsonText);

                    //遍历每个文本框
                    foreach (var tb in result.TextBlocks)
                    {
                        // 识别文字内容 ToString()是对TextBlock的字符串形式的组合。
                        Console.WriteLine($"{tb.ToString()}");
                        // 识别文字纯内容
                        Console.WriteLine($"{tb.Text}");

                        //文本框坐标左上顶点
                        Console.WriteLine($"{tb.BoxPoints[0].ToString()}");
                        //文本框坐标右上顶点
                        Console.WriteLine($"{tb.BoxPoints[1].ToString()}");
                        //文本框坐标右下顶点
                        Console.WriteLine($"{tb.BoxPoints[2].ToString()}");
                        //文本框坐标左下顶点
                        Console.WriteLine($"{tb.BoxPoints[3].ToString()}");

                    }

                    //如果对返回结果顺序不满意,可以自行对结果进行排序
                    //从左到右,从上到下排序
                    result.TextBlocks = result.TextBlocks.OrderBy(u => u.BoxPoints[0].X).ThenBy(u => u.BoxPoints[0].Y).ToList();

                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("err:"+ex.Message);
            }
            //阻止命令行窗口自动关闭
            Console.ReadKey();
        }
    }
}

  

 

步骤 4:项目发布与运行

右键项目→生成,确保项目无编译错误;

进入项目输出目录(如bin/Release/net6.0),检查custom_model目录、运行库、PaddleOCRSharp 核心文件是否完整;将测试图片test.jpg放入image目录,直接运行OCRProject.exe,即可看到自定义模型的识别结果。

示例运行结果如图:

 

640

 

三、WinForm/WPF 项目适配:可视化界面中使用自定义模型

实际开发中,更多场景是在 WinForm/WPF 可视化项目中使用自定义模型,核心配置与控制台项目完全一致,仅需增加图片选择、界面展示的逻辑。此处不再给出示例。

四、常见问题与排查方案

使用自定义模型时,容易因模型格式、路径、配置等问题导致加载失败或识别异常,以下是高频问题及对应的排查方案,覆盖 90% 以上的使用场景:

问题 1:程序运行时报错 “模型文件不存在”

原因:模型路径配置错误、模型文件缺失、相对路径根目录错误;

排查:

检查配置中的模型路径是否为项目输出目录的相对路径,而非源码目录;

验证模型目录下是否存在model.pdmodel、model.pdiparams、model.pdiparams.info三个文件;

尝试使用绝对路径测试,排除相对路径解析问题。

问题 2:模型加载成功,但识别结果为乱码 / 漏字 / 错字

原因:字典文件与自定义模型字符集不匹配、识别模型输入尺寸与训练时不一致;

排查:

检查keys是否指向自定义dict.txt,确保字典中的字符集与模型训练时的字符集完全一致;

建议基于 PaddleOCR v3/v4 训练模型,搭配最新版 PaddleOCRSharp,算子兼容性最佳。

问题 4:CPU 推理速度过慢

优化方案:

适当减小模型输入尺寸(如将 max_side_len从 960 改为 640),牺牲少量精度提升速度;

开启 PaddleOCRSharp 的多线程推理(配置类中cpu_math_library_num_threads默认设为 10,根据 CPU 核心数调整);

对输入图片进行预处理,裁剪掉无文字的区域,减少模型推理的像素量;

问题 5:ASP.NET 项目中使用自定义模型,部署后识别失败

原因:IIS 进程权限不足、模型文件被锁定、路径解析错误;

排查:

给网站部署目录添加IIS_IUSRS和Network Service的读写权限;

模型路径使用AppContext.BaseDirectory拼接(如Path.Combine(AppContext.BaseDirectory, "custom_model/det")),确保在ASP.NET 中正确解析根目录;

PaddleOCREngine引擎的初始化放在单例中,避免多次加载模型导致的文件锁定问题。

五、进阶优化:提升自定义模型的识别效果与运行效率

5.1 模型优化

训练时增加场景化样本,提升模型对目标场景的适配性,如票据识别需增加不同版式、不同清晰度的票据样本。

5.2 配置优化

根据实际场景调整检测阈值避免漏检;

开启图片预处理:在识别前对图片进行灰度化、二值化、降噪处理,提升模糊图片的识别精度,可使用 OpenCvSharp 配合 PaddleOCRSharp 实现预处理。

5.3 代码优化

在ASP.NET Core/WinService 等服务端项目中,将PaddleOCR引擎设为单例,避免每次请求都加载模型(模型加载耗时较长,单例可大幅提升并发效率);

对识别结果进行后处理:根据业务需求筛选文字块(如按坐标筛选特定区域的文字、按字符长度过滤无效识别结果),提升结果的可用性。

六、总结

PaddleOCRSharp 使用自定义模型的核心是遵循 PaddleOCR 的推理模型规范,通过 OCRModelConfig 配置类精准指定自定义模型、字典文件的路径,整个过程无需修改 PaddleOCRSharp 的源码,仅需调整配置和编写少量业务代码,即可快速适配专属场景的 OCR 需求。

PaddleOCRSharp 的高扩展性让.NET 开发者能快速落地定制化 OCR 需求,结合自定义模型的场景化优势,可在证件、票据、物流、金融等众多行业实现高精度的文字识别,是.NET 生态中 OCR 开发的优质选择。

完整项目源代码可以加入QQ群获取:318860399
posted on 2026-01-29 14:37  英田科技-明月心  阅读(6)  评论(0)    收藏  举报