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

之前作者针对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分支)
PaddleX的C++部署的方式的几种使用方式_第1张图片

依赖库:
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
PaddleX的C++部署的方式的几种使用方式_第2张图片

一、首先将上述需要依赖的opencv和预测库,PaddleX下载好,并保存在某个文件夹中。如下图是作者存放的一个文件夹。
PaddleX的C++部署的方式的几种使用方式_第3张图片
二、将opencv添加到环境变量里面,如下图所示。
PaddleX的C++部署的方式的几种使用方式_第4张图片
三、利用Cmake软件进行编译。源码路径为cpp文件所在目录,应为里面有CMakeLists.txt文件,作者同时在该目录下创建了新的文件夹/out用于生成编译后的文件。
PaddleX的C++部署的方式的几种使用方式_第5张图片

四、点击config,选择vs2019 X64选项后,点击Generate
PaddleX的C++部署的方式的几种使用方式_第6张图片
PaddleX的C++部署的方式的几种使用方式_第7张图片
五、根据报错进行修改,主要修改cuda_lib、opencv、paddle_dir路径
PaddleX的C++部署的方式的几种使用方式_第8张图片
PaddleX的C++部署的方式的几种使用方式_第9张图片

六、再次点击Generate

PaddleX的C++部署的方式的几种使用方式_第10张图片
七、点击open project,同时我们在out文件夹下发现了生成了解决方案。

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

PaddleX的C++部署的方式的几种使用方式_第13张图片
PaddleX的C++部署的方式的几种使用方式_第14张图片

九、生成成功
PaddleX的C++部署的方式的几种使用方式_第15张图片
十、运行该生成的main.exe文件。方式为打开out/release文件,会发现有一个main.exe文件。利用命令行打开后,运行即可。运行过程中需要添加模型的路径以及预测图像的路径,但是发现报错!!!
PaddleX的C++部署的方式的几种使用方式_第16张图片
十一、解决上述报错,寻找下图中其他文件,并放置件当成生成exe的文件夹中。
PaddleX的C++部署的方式的几种使用方式_第17张图片
Ps#####此时此刻进行预测的模型是按照PaddleX直接导出的模型,需要注意的是,PaddleX导出的模型和PaddleDetection导出的模型中yml文件是不一致的,这一点需要着重注意。
如下图是所示的模型保存后的结果形式,作者使用PaddleX中的昆虫检测demo检测,训练了一个基于yolo的模型。
PaddleX的C++部署的方式的几种使用方式_第18张图片
其中yml文件内容
PaddleX的C++部署的方式的几种使用方式_第19张图片

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

如下是在output文件夹生成的命名为“test.jpeg”的检测后图像
PaddleX的C++部署的方式的几种使用方式_第20张图片
PaddleX的C++部署的方式的几种使用方式_第21张图片

在这里插入图片描述

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

将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)
PaddleX的C++部署的方式的几种使用方式_第22张图片

PaddleX的C++部署的方式的几种使用方式_第23张图片

二、 然后按照上文中继续重新cmake一次。
三、 在属性—常规—配置类型中修改成.dll文件。
PaddleX的C++部署的方式的几种使用方式_第24张图片
四、 修改完上述内容后,点击“重新生成”,出现报错。
PaddleX的C++部署的方式的几种使用方式_第25张图片
五、 利用Everything(一个windows下非常好用的文件检索工具),发现电脑里面并没有libpaddle_fluid.dll文件,只有libpaddle_fluid.lib文件。同时打开libpaddle_fluid.dll所在的文件,的确没有发现libpaddle_fluid.lib文件。这个应该是paddle的预测库里面将lib和dll都写在了lib里面吧。
PaddleX的C++部署的方式的几种使用方式_第26张图片
PaddleX的C++部署的方式的几种使用方式_第27张图片

六、在附加依赖项中将libpaddle_fluid.dll改成libpaddle_fluid.lib
在这里插入图片描述

六、 再次重新生成,发现生成了dll。
PaddleX的C++部署的方式的几种使用方式_第28张图片
七、 看到dll后,我们仿佛看到了曙光,但是还是需要进行修改,因为这样我们才能被调用,作者改造了detector.cc文件中代码,并在头文件中添加了接口文件。


```csharp

```csharp

```cpp
#include 
#include 
#include 
#include 
#include 
#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文档中添加接口,接口如红框内所示
PaddleX的C++部署的方式的几种使用方式_第29张图片
九、然后我们继续点击“重新生成”,重新生成的dll就是下述步骤中我们即将调用的dll。
使用python调用生成好的dll;
在上一章节我们说了如何生成dll,这一章节,我们需要进行测试,在这里我们使用python进行测试,利用python调用dll。在生成的dll的文件中创建一个叫mian.py的python文件。
Python部分代码如下:

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

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

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

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

PaddleX的C++部署的方式的几种使用方式_第32张图片
三、 设置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预测库中可以找到)

PaddleX的C++部署的方式的几种使用方式_第33张图片
五、 点击“启动“按钮进行测试;
PaddleX的C++部署的方式的几种使用方式_第34张图片
六、 我们在C#的运行目录下发现了生成了一张output.jpeg图片,证明我们调用成功。

PaddleX的C++部署的方式的几种使用方式_第35张图片
在这里插入图片描述
七、至此,我们生成dll,并且实现了成功的调用。

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

你可能感兴趣的:(Paddle,python,c++,paddlepaddle,深度学习,人工智能)