首页 > 编程知识 正文

PaddleX的C 部署的方式的几种使用方式

时间:2023-05-05 14:15:34 阅读:197556 作者:578

之前作者针对PaddleDetection写过一个系列文章,其中最后一篇是针对PaddlDetection的C++部署方式进行一些改造。这篇文章是根据PaddleX在Github官方的代码以及文档,将C++部署相关代码进行整理,并进行了如下工作:
1、 将官方C++预测代码在Visual Studio下生成解决方案(.sln)
2、 将C++预测代码进行生成dll
3、 使用python调用生成的dll
4、 使用C#调用生成的dll

将官方的C++预测代码在Visual Studio下生成解决方案
准备工作:
使用工具Cmake vs2019社区版 Git(提前下载好git,不然在后期编译过程中会不成功)
预测代码来源:https://github.com/PaddlePaddle/PaddleX (注意选择develop分支)

依赖库:
Opencv:选择3.4.6版本
https://sourceforge.net/projects/opencvlibrary/files/3.4.6/opencv-3.4.6-vc14_vc15.exe/download
Paddle预测库:选择win10下的cuda10版本。
https://www.paddlepaddle.org.cn/documentation/docs/zh/advanced_guide/inference_deployment/inference/windows_cpp_inference.html

一、首先将上述需要依赖的opencv和预测库,PaddleX下载好,并保存在某个文件夹中。如下图是作者存放的一个文件夹。

二、将opencv添加到环境变量里面,如下图所示。

三、利用Cmake软件进行编译。源码路径为cpp文件所在目录,应为里面有CMakeLists.txt文件,作者同时在该目录下创建了新的文件夹/out用于生成编译后的文件。

四、点击config,选择vs2019 X64选项后,点击Generate


五、根据报错进行修改,主要修改cuda_lib、opencv、paddle_dir路径

六、再次点击Generate


七、点击open project,同时我们在out文件夹下发现了生成了解决方案。



八、针对“detector”项目进行“重新生成”。同时一定要将模式配置成为Release
备注:PaddleX提供了分类,检测,分割三种预测部署的方案,我们案例以检测为例说明。


九、生成成功

十、运行该生成的main.exe文件。方式为打开out/release文件,会发现有一个main.exe文件。利用命令行打开后,运行即可。运行过程中需要添加模型的路径以及预测图像的路径,但是发现报错!!!

十一、解决上述报错,寻找下图中其他文件,并放置件当成生成exe的文件夹中。

Ps#####此时此刻进行预测的模型是按照PaddleX直接导出的模型,需要注意的是,PaddleX导出的模型和PaddleDetection导出的模型中yml文件是不一致的,这一点需要着重注意。
如下图是所示的模型保存后的结果形式,作者使用PaddleX中的昆虫检测demo检测,训练了一个基于yolo的模型。

其中yml文件内容

十三、预测结果如下图所示,我们看到输出的结果中有检测框的坐标、置信度、类别信息。

如下是在output文件夹生成的命名为“test.jpeg”的检测后图像

至此,完成了第一步以及第一步的所有测试,预测图像检测效果不好的原因是作者迭代的次数比较少。

将C++预测代码进行生成dll
一、 我们需要修改CMakeLists.txt文件,修改倒数第十三行
将add_executable(main src/main.cc src/preprocess_op.cc src/object_detector.cc) 变成ADD_library(main SHARED src/main.cc src/preprocess_op.cc src/object_detector.cc)

二、 然后按照上文中继续重新cmake一次。
三、 在属性—常规—配置类型中修改成.dll文件。

四、 修改完上述内容后,点击“重新生成”,出现报错。

五、 利用Everything(一个windows下非常好用的文件检索工具),发现电脑里面并没有libpaddle_fluid.dll文件,只有libpaddle_fluid.lib文件。同时打开libpaddle_fluid.dll所在的文件,的确没有发现libpaddle_fluid.lib文件。这个应该是paddle的预测库里面将lib和dll都写在了lib里面吧。

六、在附加依赖项中将libpaddle_fluid.dll改成libpaddle_fluid.lib


六、 再次重新生成,发现生成了dll。

七、 看到dll后,我们仿佛看到了曙光,但是还是需要进行修改,因为这样我们才能被调用,作者改造了detector.cc文件中代码,并在头文件中添加了接口文件。

```csharp```csharp```cpp#include <glog/logging.h>#include <fstream>#include <iostream>#include <string>#include <vector>#include "include/paddlex/paddlex.h"#include "include/paddlex/visualize.h"namespace PaddleX {std::string image;void PredictImage(std::string image, PaddleX::DetResult result );void Loadmodel() { std::string model_dir = "E:\0608\inference_model"; std::string key = ""; std::string image_list = ""; std::string save_dir = "output"; int gpu_id = 0; bool use_trt = 0; bool use_gpu = 1; // Load model and create a object detector PaddleX::DetResult result; PredictImage(image, result);}void PredictImage(std::string image, PaddleX::DetResult result ) { image = "E:\0608\pic\test.jpg"; cv::Mat im = cv::imread(image, 1); // PaddleX::DetResult* result; std::string model_dir = "E:\0608\inference_model"; std::string key = ""; std::string image_list = ""; int gpu_id = 0; bool use_trt = 0; bool use_gpu = 1; PaddleX::Model model; model.Init(model_dir, use_gpu, use_trt, gpu_id, key); model.predict(im, &result); for (int i = 0; i < result.boxes.size(); ++i) { std::cout << ", predict label: " << result.boxes[i].category << ", label_id:" << result.boxes[i].category_id << ", score: " << result.boxes[i].score << ", box(xmin, ymin, w, h):(" << result.boxes[i].coordinate[0] << ", " << result.boxes[i].coordinate[1] << ", " << result.boxes[i].coordinate[2] << ", " << result.boxes[i].coordinate[3] << ")" << std::endl; } // 可视化 auto colormap = PaddleX::GenerateColorMap(model.labels.size()); cv::Mat vis_img = PaddleX::Visualize(im, result, model.labels, colormap, 0.5); std::string save_dir = "output"; std::string save_path = PaddleX::generate_save_path(save_dir, image); cv::imwrite(save_path, vis_img);//result->clear(); std::cout << "Visualized output saved as " << save_path << std::endl;}} // namespace PaddleX

八、 同时在paddlex.h文档中添加接口,接口如红框内所示

九、然后我们继续点击“重新生成”,重新生成的dll就是下述步骤中我们即将调用的dll。
使用python调用生成好的dll;
在上一章节我们说了如何生成dll,这一章节,我们需要进行测试,在这里我们使用python进行测试,利用python调用dll。在生成的dll的文件中创建一个叫mian.py的python文件。
Python部分代码如下:

from ctypes import *dll=CDLL("detector.dll")print(dll.Loadmodel())

运行python代码,可以看到最终输出结果如下图:


至此说明利用python调用dll成功了。
使用C#调用生成好的dll;
在上一个章节中我们说了如何使用python调用dll,接着,我们尝试使用C#调用一个dll,此方式为工业上经常使用的一种方式。
一、 首先创建一个C#的窗体应用程序。

二、 在改窗体应用程序中设置一个button事件。


三、 设置dll接口代码以及设置button,相关代码如下

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Runtime.InteropServices;namespace WindowsFormsApp1{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } [DllImport("main.dll", EntryPoint = "Loadmodel", CharSet = CharSet.Ansi)] public static extern void Loadmodel(); private void button1_Click(object sender, EventArgs e) { Loadmodel(); } private void Form1_Load(object sender, EventArgs e) { } }}

四、 将C++release路径下生成的文件全部复制到C#项目运行目录下,在C++的release文件中,有一些文件只有dll,没有对应的lib文件,这个时候,我们需要搜索到这些dll对应的lib文件,全部放在C#的运行目录下。(PS#这些对应的文件都在我们下载的paddle预测库中可以找到)


五、 点击“启动“按钮进行测试;

六、 我们在C#的运行目录下发现了生成了一张output.jpeg图片,证明我们调用成功。



七、至此,我们生成dll,并且实现了成功的调用。

有问题,欢迎咨询,作者微信yzl819819

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。