系列文章 如何使用PaddleDetection做一个完整项目(三)


系列文章 如何使用PaddleDetection做一个完整项目(三)
该文章是PaddleDetection的完结篇,请参考之前两篇文章
本文将针对如何使用PaddleDetection中C++预测库的编译,封装,调用进行说明。
- 如何进行C++预测的编译(生成.sln解决方案);
- 如何将C++预测代码封装成一个dll;
- 如何使用python调用生成好的dll;
- 如何使用C#调用生成好的dll;
如何进行C++预测代码的编译(生成.sln解决方案)
使用工具:Cmake vs2019社区版 Git(提前下载好git,不然在后期编译过程中会不成功)
预测代码来源: https:// github.com/PaddlePaddle /PaddleDetection/tree/master (注意选择master分支)
依赖库:
Opencv:选择3.4.6版本
Paddle预测库:选择win10下的cuda10版本。
一、首先将上述需要依赖的opencv和预测库,PaddleDetection下载好,并保存在某个文件夹中。如下图是作者存放的一个文件夹。
二、将opencv添加到环境变量里面,如下图所示。
三、利用Cmake软件进行编译。源码路径为cpp文件所在目录,应为里面有CMakeLists.txt文件,作者同时在该目录下创建了新的文件夹/out用于生成编译后的文件。
四、点击config,选择vs2019 X64选项后,点击Generate
五、根据报错进行修改,主要修改cuda_lib、opencv、paddle_dir路径
六、再次点击Generate
七、点击open project,同时我们在out文件夹下发现了生成了解决方案。
八、针对“main”项目进行“重新生成”。同时一定要将模式配置成为Release
九、出现报错
十、修改报错---根据报错,应该是编译过程中,cudnn.lib寻找不正确。通过修改路径实现。方式为点击属性--连接器--输入--附加依赖项。
十一、改正上述错误后的正确的形式
十二、重新生成,如下图是重新生成后的结果。
十二、运行该生成的main.exe文件。方式为打开out/release文件,会发现有一个main.exe文件。利用命令行打开后,运行即可。运行过程中需要添加模型的路径以及预测图像的路径。
Ps#####此时此刻进行预测的模型是按照《系列文章 如何适用PaddleDetection实现一完整的项目(一)》中export.py文件形式导出“__model__”和“__params__”的形式,但是在后续paddle的升级过程中,export.py文件不仅仅会导出“__model__”和“__params__”,还会导出一个infer_cfg.yml的文件。作者在这个过程中,是使用PaddleDetection-release0.3版本进行导出的,因为作者之前安装的paddle版本是1.7的,而目前的master分支是必须使用paddle2.0版本的。因此小伙伴们需要注意这个问题。
如下图是所示的模型保存后的结果形式,作者依旧使用水果检测的模型进行预测。
其中yml文件内容
十三、预测结果如下图所示,我们看到输出的结果中有检测框的坐标、置信度、类别信息。
如下是在out文件夹生成的命名为“output.jpeg”的检测后图像
十四、对代码进行一下小修改。之前我们需要在命令行中输入图像和模型的路径,作者在代码中添加图像和模型的路径,查看预测情况。修改如下:
十五、修改上述两处代码后,设置“设为启动项目”,并点击“本地windows调试器”
,直接查看输出的结果。
至此,完成了第一步以及第一步的所有测试。
如何将C++预测代码封装成一个dll
- 我们需要修改CMakeLists.txt文件,修改倒数第十三行
将add_executable(main src/ http:// main.cc src/ http:// preprocess_op.cc src/ http:// object_detector.cc ) 变成ADD_library(main SHARED src/ http:// main.cc src/ http:// preprocess_op.cc src/ http:// object_detector.cc )
- 然后按照上文中继续重新cmake一次。
- 再次经历之前的cudnn的路径问题,同时需要在属性—常规—配置类型中修改成.dll文件。
- 修改完上述内容后,点击“重新生成”,会发现out/release中出现了main.dll文件。
- 看到dll后,我们仿佛看到了曙光,但是还是需要进行修改,因为这样我们才能被调用,作者简化了 http:// main.cc 文件中的内容,并且配置了dll的接口,代码如下。其中有两个dll的接口,其中“add”是为了测试。
#include <glog/logging.h>
#include <iostream>
#include <string>
#include <vector>
#include "include/object_detector.h"
extern "C" __declspec(dllexport) void Loadmodel();
extern "C" __declspec(dllexport) int add(int a, int b);
void PredictImage(const std::string& image_path,
PaddleDetection::ObjectDetector* det);
int add(int a, int b) {
return a + b;
void Loadmodel() {
std::string model_dir = "D:\\0524\\test\\model";
std::string image_path = "D:\\0524\\test\\orange_71.jpg";
std::string video_path = "";
std::string run_mode = "fluid";
bool use_gpu = true;
// Load model and create a object detector
PaddleDetection::ObjectDetector det(model_dir, use_gpu, run_mode);
PredictImage(image_path, &det);
void PredictImage(const std::string& image_path,
PaddleDetection::ObjectDetector* det) {
// Open input image as an opencv cv::Mat object
cv::Mat im = cv::imread(image_path, 1);
// Store all detected result
std::vector<PaddleDetection::ObjectResult> result;
det->Predict(im, &result);
for (const auto& item : result) {
printf("class=%d confidence=%.2f rect=[%d %d %d %d]\n",
item.class_id,
item.confidence,
item.rect[0],
item.rect[1],
item.rect[2],
item.rect[3]);
// Visualization result
auto labels = det->GetLabelList();
auto colormap = PaddleDetection::GenerateColorMap(labels.size());
cv::Mat vis_img = PaddleDetection::VisualizeResult(
im, result, labels, colormap);
std::vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(95);
cv::imwrite("output.jpeg", vis_img, compression_params);
printf("Visualized output saved as output.jpeg\n");
}
六、然后我们继续点击“重新生成”,重新生成的dll就是下述步骤中我们即将调用的dll。
如何使用python调用生成好的dll;
在上一章节我们说了如何生成dll,这一章节,我们需要进行测试,在这里我们使用python进行测试,利用python调用dll。在生成的dll的文件中创建一个叫mian.py的python文件。
Python部分代码如下:
from ctypes import *
dll=CDLL("main.dll")
print(dll.add(1,2))
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
int a = 3;
int b = 2;
public Form1()
InitializeComponent();
[DllImport("main.dll", EntryPoint = "Loadmodel", CharSet = CharSet.Ansi)]
public static extern void Loadmodel();
[DllImport("main.dll", EntryPoint = "add", CharSet = CharSet.Ansi)]
public static extern int add(int a, int b);
private void button1_Click(object sender, EventArgs e)
int c = add(a, b);
Loadmodel();