【www.fsgl168.com--科技】
【飞桨开发者说】:余志良,菲特(天津)智能科技有限公司项目经理,百度黄埔学院二期学员
今年3月、4月我分别发布了两篇文章:《如何用PaddleDetection做一个完整的目标检测项目》以及《》,为大家讲解了从模型训练到模型部署的全过程,其中模型部署基于Paddle预测库的Python接口。本篇将教大家通过PaddleDetection编译C++预测库,并将其封装成dll,实现PaddleDetection在Windows环境下的模型部署。
本文内容主要包括:
如何进行C++预测的编译(生成.sln解决方案)
如何将C++预测代码封装成一个dll
如何使用Python调用生成好的dll
如何使用C#调用生成好的dll
如何进行C++预测代码的编译
(生成.sln解决方案)
如何将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一次。三、再次经历之前的cudnn的路径问题,同时需要在属性—常规—配置类型中修改成.dll文件。四、修改完上述内容后,点击“重新生成”,会发现out/release中出现了main.dll文件。五、看到dll后,我们仿佛看到了曙光,但是还是需要进行修改,因为这样我们才能被调用,我简化了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
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(); } private void Form1_Load(object sender, EventArgs e) { } }}四、将C++ release路径下生成的文件全部复制到C#项目运行目录下,在C++的release文件中,有一些文件只有dll,没有对应的lib文件,这个时候,我们需要搜索到这些dll对应的lib文件,全部放在C#的运行目录下。(PS#这些对应的文件都在我们下载的paddle预测库中可以找到)五、点击“启动按钮”进行测试;六、我们在C#的运行目录下发现了生成了一张output.jpeg图片,证明我们调用成功至此,该系列文章基本上完成了从训练到部署的所有流程,十分感谢在写作过程中飞桨同学的帮助,非常感谢高松鹤、梁钰同学的大力帮助。后续会根据飞桨针对C++预测的更新,继续更新完善该文章。
更多资源
更多PaddleDetection的应用方法,欢迎访问项目地址:GitHub: https://github.com/PaddlePaddle/PaddleDetection Gitee: https://gitee.com/paddlepaddle/PaddleDetection如在使用过程中有问题,可加入飞桨官方QQ群进行交流:703252161。如果您想详细了解更多飞桨的相关内容,请参阅以下文档。官网地址:https://www.paddlepaddle.org.cn飞桨开源框架项目地址:GitHub:https://github.com/PaddlePaddle/PaddleGitee: https://gitee.com/paddlepaddle/PaddleEND