首页 > 其他分享 >PaddleSharp:跨越一年的版本更新与亮点

PaddleSharp:跨越一年的版本更新与亮点

时间:2023-07-25 09:00:08浏览次数:44  
标签:PaddleOCR PaddleOcrAll PaddleSharp 跨越 亮点 using Sdcb PaddleDevice

PaddleSharp:跨越一年的版本更新与亮点

我始终坚信,开源社区是技术进步的重要推动力,也是我抽出我业余时间,投入到PaddleSharp这个项目的原因,这个项目充分展现了.NET在复杂计算领域的潜力。今天很高兴地告诉大家,PaddleSharp有了新版本!

先来说说背景,有的朋友可能知道,PaddleSharp过去老版本存在一些东西过时或者无法使用的情况。但是,时光恰恰是优化和革新的好理由和契机,我在距离上一篇文章发布之后,做了许多优化,下面我挑重要的部分做介绍。

整体体验

文档和示例

我一直在更新Github首页的使用文档和示例:

里面包含了大致介绍、使用方式、使用示例、注意事项等。

我会持续维护这些文档,尤其是有客户有时向我反馈一些问题,我会将里面一些常见的问题和解决办法写在上面文档中,因此建议初接触PaddleSharp的朋友看看。

xml注释和snuget调试

作为一名程序员,编程体验很重要,方法怎么用,一个是看示例,另一个就是看注释。

为此我将PaddleSharp中所有的公有方法、受保护方法都加上了详尽的xml注释,这一点在Github上显示了超过9000行代码变动,以后在Visual Studio中鼠标放在PaddleSharp里面的类、参数、方法上时,就会显示详尽的注释,比如下面这个注释:

/// <summary>
/// Returns an Action delegate that configures PaddleConfig for use with Onnx.
/// </summary>
/// <param name="cpuMathThreadCount">The number of CPU threads to use for math operations. A value of 0 sets it to minimum of 4 and the available number of processors.</param>
/// <param name="enableOnnxOptimization">Flag to enable or disable Onnx runtime optimization.</param>
/// <param name="memoryOptimized">Flag to enable or disable memory optimization.</param>
/// <param name="glogEnabled">Flag to enable or disable logging with glog.</param>
/// <returns>The ONNX Runtime paddle device definition.</returns>
public static Action<PaddleConfig> Onnx(int cpuMathThreadCount = 0, bool enableOnnxOptimization = true, bool memoryOptimized = true, bool glogEnabled = false)
{
    return cfg =>
    {
        cfg.OnnxEnabled = true;
        if (enableOnnxOptimization) cfg.EnableOnnxOptimization();
        cfg.CpuMathThreadCount = cpuMathThreadCount switch
        {
            0 => Math.Min(4, Environment.ProcessorCount),
            _ => cpuMathThreadCount
        };
        CommonAction(cfg, memoryOptimized, glogEnabled);
    };
}

可见它会每个成员函数、参数、返回值都作出了详尽的xml注释。

以此为基础,我还将所有的.NET包发布了.snuget包,这些包自带pdb调试符号文件,以后编程中按F11即可单步调试进入PaddleSharp的源代码中,。

Paddle推理库

设备管理

其中,一项重要的改变在于设备使用接口的设计。老版本中只有PaddleConfig.Defaults.UseGpu这一设备启用选项,为了增强扩展性和用户体验,便对其进行了扩展:新版本中我引入了下列设备:

  • PaddleDevice.Gpu()
  • PaddleDevice.Openblas()
  • PaddleDevice.Onnx()
  • PaddleDevice.Mkldnn()
  • PaddleDevice.TensorRt()(需要和PaddleDevice.Gpu()配合使用)

不同的方法代表着不同的设备类型,这无疑为用户提供了更大的选择空间,这是PaddleOCR的新版本使用示例(它需要作为PaddleOcrAll的参数传进去):

// 注:需要先安装如下NuGet包:
// * Sdcb.PaddleInference
// * Sdcb.PaddleOCR
// * Sdcb.PaddleOCR.Models.LocalV3
// * Sdcb.PaddleInference.runtime.win64.mkl
// * OpenCvSharp4.runtime.win
FullOcrModel model = LocalFullModels.ChineseV3;

byte[] sampleImageData;
string sampleImageUrl = @"https://www.tp-link.com.cn/content/images2017/gallery/4288_1920.jpg";
using (HttpClient http = new HttpClient())
{
    Console.WriteLine("Download sample image from: " + sampleImageUrl);
    sampleImageData = await http.GetByteArrayAsync(sampleImageUrl);
}

// 下面的PaddleDevice.Mkldnn()是新加的
// 之前是用的PaddleConfig.Defaults.UseMkldnn = true
// 如果想要GPU,则改为PaddleDevice.Gpu()即可
using (PaddleOcrAll all = new PaddleOcrAll(model, PaddleDevice.Mkldnn())
{
    AllowRotateDetection = true, /* 允许识别有角度的文字 */ 
    Enable180Classification = false, /* 不允许识别旋转角度大于90度的文字 */
})
{
    // 如果需要读取本地文件,使用如下被注释的代码
    // using (Mat src2 = Cv2.ImRead(@"C:\test.jpg"))
    using (Mat src = Cv2.ImDecode(sampleImageData, ImreadModes.Color))
    {
        PaddleOcrResult result = all.Run(src);
        Console.WriteLine("Detected all texts: \n" + result.Text);
        foreach (PaddleOcrResultRegion region in result.Regions)
        {
            Console.WriteLine($"Text: {region.Text}, Score: {region.Score}, RectCenter: {region.Rect.Center}, RectSize:    {region.Rect.Size}, Angle: {region.Rect.Angle}");
        }
    }
}

其中用于设备管理的代码在:

using (PaddleOcrAll all = new PaddleOcrAll(model, PaddleDevice.Mkldnn())

它可以换为PaddleDevice.Openblas()(表示不使用Mkldnn):

using (PaddleOcrAll all = new PaddleOcrAll(model, PaddleDevice.Openblas())

或者换成PaddleDevice.Gpu()(表示使用GPU——但必须先安装Gpu的相关包并配好环境):

using (PaddleOcrAll all = new PaddleOcrAll(model, PaddleDevice.Gpu())

当然,我会尽量简化和清晰地解释这个部分。以下是我的修改提案:

库加载方式优化

在旧版PaddleSharp中,库加载方式主要有两种:在.NET Framework中采用Autoload方式,在.NET Core中采用SearchPathLoad方式。然而,这两种方式在某些情况下并不理想,特别是在Linux环境下。

Autoload方式

Autoload方式的主要问题在于,PaddleSharp依赖于paddle_inference_c.dll,而paddle_inference_c.dll又依赖于其他dll如openblas.dll。即使paddle_inference_c.dll成功加载,也可能因为其他依赖dll的问题导致推理失败。

解决办法是在调用依赖dll加载的函数前,先调用一个不会触发加载的函数,例如PaddleConfig.Version。然后在当前进程模型中找到paddle_inference_c模块,定位到它所在的文件夹,并把文件夹路径导入到环境变量中。

SearchPathLoad方式

SearchPathLoad方式利用了.NET Core 3.1引入的AppContext变量:NATIVE_DLL_SEARCH_DIRECTORIES。这种方式不需要读取进程模块就能知道dll的位置。

但是,这种方法在Linux环境下行不通。因为LinuxLD_LIBRARY_PATH环境变量必须在进程启动前被确定。一旦进程启动,环境变量的值就被缓存起来,运行时的修改对程序无效。

新的加载方式

为了解决上述问题,新的PaddleSharp版本采用了逐步加载依赖的方式。在Linux环境中,依次加载以下动态库:

  1. libgomp.so.1
  2. libiomp5.so
  3. libdnnl.so.2
  4. libmklml_intel.so
  5. libonnxruntime.so.1.11.1
  6. libpaddle2onnx.so.1.0.0rc2

这种新的加载方式有效解决了在Linux环境下的问题。

PaddleOCR

已经支持表格识别

这个许多客户反馈了许久,我在大概2023年五一的时候实现了表格识别功能,同时表格识别的模型我都加入了Sdcb.PaddleOCR.Models.LocalV3/Sdcb.PaddleOCR.Models.Online包,可以全离线表格识别或者按需下载模型表格识别。

它的使用示例如下(最新版本请参考这个链接:https://github.com/sdcb/PaddleSharp/blob/master/docs/ocr.md#table-recognition ):

// Install following packages:
// Sdcb.PaddleInference
// Sdcb.PaddleOCR
// Sdcb.PaddleOCR.Models.LocalV3
// Sdcb.PaddleInference.runtime.win64.mkl (required in Windows, linux using docker)
// OpenCvSharp4.runtime.win (required in Windows, linux using docker)
using PaddleOcrTableRecognizer tableRec = new(LocalTableRecognitionModel.ChineseMobileV2_SLANET);
using Mat src = Cv2.ImRead(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "table.jpg"));
// Table detection
TableDetectionResult tableResult = tableRec.Run(src);

// Normal OCR
using PaddleOcrAll all = new(LocalFullModels.ChineseV3);
all.Detector.UnclipRatio = 1.2f;
PaddleOcrResult ocrResult = all.Run(src);

// Rebuild table
string html = tableResult.RebuildTable(ocrResult);

效果如图:

Raw table Table model output Rebuilt table

值得注意的是,PaddleSharp的表格识别是基于飞桨的深度学习模型,对于一些规整的表格,它的效果可能不如使用传统的OpenCV算法,如果想了解传统算法,可以参考我2021年.NET Conf China做的技术分享的pdf:.NET玩转计算机视觉OpenCV - 周杰

两个新的模型包LocalV3/Online

新版本中,还引入了两个新的本地模型包:Sdcb.PaddleOCR.Models.LocalV3/Sdcb.PaddleOCR.Models.Online。一个表示完全本地——不用联网即可使用OCR,另一个表示需要联网,模型按需下载。

下面是使用Sdcb.PaddleOCR.Models.LocalV3的示例:

FullOcrModel model = LocalFullModels.EnglishV3; // 将EnglishV3换为其它模型,如ChineseV3
using (PaddleOcrAll all = new PaddleOcrAll(model))
{
    // ...
}

下面是使用Sdcb.PaddleOCR.Models.Online的示例:

FullOcrModel model = await OnlineFullModels.EnglishV3.DownloadAsync();
using (PaddleOcrAll all = new PaddleOcrAll(model))
{
    // ...
}

其中值得一提的是LocalV3,它将所有已知PaddleOCR的v3模型都包含了,安装这个包可以实现完全不联网部署。

为什么我需要淘汰原来的Sdcb.PaddleOCR.KnownModels

说来话长,首先KnownModels有下面几个缺点:

  • 主要原因是OCR需要使用的文字检测、180度分类、文字识别3个模型会下载到以语言命名的同一个文件夹中:

    C:\Users\ZhouJie\AppData\Roaming\paddleocr-models\ppocr-v3>tree /f
    C:.
    │  key.txt
    │
    ├─cls
    │      inference.pdiparams
    │      inference.pdiparams.info
    │      inference.pdmodel
    │
    ├─det
    │      inference.pdiparams
    │      inference.pdiparams.info
    │      inference.pdmodel
    │
    └─rec
            inference.pdiparams
            inference.pdiparams.info
            inference.pdmodel
    

    如上图,每个模型的cls文件夹都可能重复占用磁盘空间、且需要重复下载——这不合理。

    因此我引入了Sdcb.PaddleOCR.Models.Online,已经下载过的模型不会重复下载,这个行为和PaddleOCR上游Python代码一致。

  • 次要问题是它的命名,KnownModels不能代表它是本地模型还是线上模型(虽然它本质是线上模型、按需下载),如果使用LocalV3Online,则可以清晰地看出是本地模型或者线上模型。

识别阶段走batch

关于性能问题,新版本也做了一些重要的升级。OCR文字识别阶段能够自动支持batch处理,且走batch时会排序,将一样宽的文字行做一批识别,这样大大优化了程序的性能。

据一些客户的测试反馈,PaddleSharpPaddleOCR的性能表现很好,甚至在某些场景下和官方的C++Python版本相比有更好的表现。

总结

其实上面只是一些主要的,其实PaddleSharp项目还有许多非常有意思功能增强,比如RotationDetectionPaddle2Onnx,以后有机会我一一介绍。

我深信这些更新无疑会为.NET开源社区带来更多的可能性和便利。我将继续在这个领域上付出努力,为.NET社区做出更多的贡献。我期待着更多.NET爱好者能够加入我,一起提升PaddleSharp.NET深度学习实战应用中的影响力,它将始终保持好用且免费,让我们共同期待它的更多精彩!

想尝试PaddleSharp的朋友,欢迎访问我的Github,也请给个Star

标签:PaddleOCR,PaddleOcrAll,PaddleSharp,跨越,亮点,using,Sdcb,PaddleDevice
From: https://www.cnblogs.com/sdflysha/p/20230724-paddlesharp-in-a-year.html

相关文章

  • 从MVC跨越到DDD微服务架构是如何演进的
    微服务架构演进领域模型中对象的层次从内到外依次是:值对象、实体、聚合和限界上下文。实体或值对象的简单变更,一般不会让领域模型和微服务发生大变。但聚合的重组或拆分却可以。因为聚合内业务功能内聚,能独立完成特定业务。那聚合的重组或拆分,势必引起业务模块和系统功能变化。......
  • 总监面(高级或者架构面):从事至今做过哪些亮点功能或者是架构
    这种问题每个人经历不一样一般回答是不一样的,通常要回答出两点,一个提现技术,二要提现设计上的优化思路,(其实这种问题已经有点想骗作业的嫌疑了,只不过没有指明具体场景)可以分两次回答两个不同场景,如果偏管理的话,还需要回答第三点对项目的总体设计及管理思想。 一般回答分布式的细......
  • 界面控件DevExtreme v23.1新版亮点 - 全新的DateRangeBox组件
    DevExtreme拥有高性能的HTML5/JavaScript小部件集合,使您可以利用现代Web开发堆栈(包括React,Angular,ASP.NETCore,jQuery,Knockout等)构建交互式的Web应用程序。从Angular和Reac,到ASP.NETCore或Vue,DevExtreme包含全面的高性能和响应式UI小部件集合,可在传统Web和下一代移动应用程序中......
  • 跨越时空的对话:如何使用AI阅读工具ChatDOC快速建立数字化身?
    跨越时空的对话:如何使用ChatDOC快速建立数字化身?以史蒂夫·乔布斯AI为例开门见山,这篇文章主要介绍如何将AI改造为靠谱、好用、基于某个人物的数字化身。比如,乔布斯AI、马斯克AI、张一鸣AI、王兴AI、佛陀AI、孔子AI.想象一下,和乔布斯聊产品,和释迦摩尼论佛法,和孔子聊人生......
  • 山河大学:一所跨越山河,笑对未来的大学
    在高考分数刚刚出炉的时候,一所名为“山河大学”的虚构高校在网上火了起来。这个想法源于网友的玩笑,面对山东、山西、河南、河北四个省份的本科录取率低的问题,他们提出如果每个考生都拿出1000元,总共三十多亿,就可以打造出一所四省交界的综合性大学,面向“山河四省”招生。那么,如果真......
  • 界面组件DevExpress WPF v23.1新版亮点 - 启动和内存优化
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。无论是Office办公软件的衍伸产品,还是以数据为中心......
  • 界面组件DevExpress WinForm v23.1新版亮点 - 皮肤矢量图标全新升级
    DevExpressWinForms拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!DevExpressWinForm 控件日前正式发布了今年第一......
  • 网易云信今年发布的WE-CAN有哪些亮点?
    今年,网易云信发布了自研新一代大规模分布式传输网络WE-CAN(CommunicationsAccelerationNetwork)。根据网易云信发布的信息,WE-CAN不仅可以大大提高端到端的通信质量,降低通信成本,并且能够适用于多种应用场景。LiveVideoStack近期采访了网易云信服务端首席架构师吉奇,和他一起讨论了W......
  • 跨越式初学SpringBoot的各种问题《一》
    前提:本人没有学过一点SSM,在学SpringBoot之前,上网搜索了各种回答,关于能否跨越直接学SpringBoot,得到的都是肯定回答可以;在本人觉得promising,开始在哔哩哔哩大学,翻找各种SpringBoot叫教学视频,每一个教程打开第一集就是,要求懂SSM(谁懂啊bleak)。然而,我依然坚定开始了零SSM基础的学习!应......
  • 大厂产品的体验亮点
    编辑导语:用户体验决定了一款产品的用户留存率和转化率,好的用户体验具有极强极简的交互能力。本篇文章中,作者分享了提升交互能力的方法;在体验流程中设计师该注意什么;大厂产品的设计案例,以及学习思路,感兴趣的小伙伴不妨来看看~ 一、如何提升交互能力很多刚入门的小朋友不知道怎么提......