PaddleSeg模型使用C++部署到windows上的详细流程

PaddleSeg部署到windows详细流程

概要

在vs2017上使用C++部署PaddleSeg模型并成功推理。
相关链接:

https://blog.csdn.net/Vertira/article/details/122936086
https://github.com/PaddlePaddle/PaddleSeg
https://github.com/PaddlePaddle/PaddleX/blob/develop/deploy/cpp/docs/compile/paddle/windows.md
https://github.com/PaddlePaddle/PaddleX/tree/release/2.0.0/examples/C%23_deploy

环境依赖

这一部分参照

https://github.com/PaddlePaddle/PaddleX/blob/develop/deploy/cpp/docs/compile/paddle/windows.md

教程中的环境为在这里插入图片描述
本机环境为:
Visual Studio 2017
CUDA 10.1, CUDNN 7.6.5
CMake 3.0+

下载预测代码PaddleX

一开始用的PaddleSeg,但是PaddleX教程多,索性就用paddleX了。本机所用PaddleX版本为2.0。去github上下载。

d:
mkdir projects
cd projects
git clone https://github.com/PaddlePaddle/PaddleX.git

说明:其中C++预测代码在PaddleX\dygraph\deploy\cpp 目录,该目录不依赖任何PaddleX下其他目录。所有的公共实现代码在model_deploy目录下,所有示例代码都在demo目录下。

下载PaddlePaddle C++ 预测库

PaddlePaddle C++ 预测库针对是否使用GPU、是否支持TensorRT、以及不同的CUDA版本提供了已经编译好的预测库。
本机所用预测库不包含TensorRT,因此所下载的的预测库为:在这里插入图片描述
预测库链接:

https://paddleinference.paddlepaddle.org.cn/user_guides/download_lib.html#c

请根据实际情况选择下载,如若以上版本不满足您的需求,请至C++预测库下载列表选择符合的版本。
将预测库解压后,其所在目录(例如D:\projects\paddle_inference_install_dir\)下主要包含的内容有:

├── \paddle\ # paddle核心库和头文件
|
├── \third_party\ # 第三方依赖库和头文件
|
└── \version.txt # 版本和编译信息

安装配置OpenCV

在OpenCV官网下载适用于Windows平台的版本,选择你适用的版本,下载windows版本的,opencv链接:在这里插入图片描述

https://opencv.org/releases/

运行下载的可执行文件,将OpenCV解压至指定目录,例如D:\projects\opencv
配置环境变量,如下流程所示
我的电脑->属性->高级系统设置->环境变量
在系统变量中找到Path(如没有,自行创建),并双击编辑
新建,将opencv路径填入并保存,如D:\projects\opencv\build\x64\vc15\bin
在进行cmake构建时,会有相关提示,请注意输出。

编译PaddleX,Opencv以及paddleinference预测库

为了便于项目管理,将所有的文件汇总到一个文件夹中在这里插入图片描述
使用Cmake进行编译,我们主要对PaddleX/deploy/cpp中代码进行编译,并创建build文件夹用来承接编译生成的内容,
在这里插入图片描述
打开cmake-gui界面,导入相关路径
在这里插入图片描述

点击Configure进行,选择x64和vs2017。之后,在红色区域输入相关路径,(CUDA_LIB,OPENCV_DIR,PADDLE_DIR).如下,请不要勾选TENSORRT,要勾选WITH_GPU。若要进行TENSORRT加速,请去官方文档内下载相关文件,并查看教程,这里不做赘述。在这里插入图片描述
点击Generate进行生成,最终在build文件夹中出现了.sln文件,则表示通过cmake生成成功了解决方案。

在这里插入图片描述

打开sln文件,会发现在PaddleDeploy目录下生成了7个项目,其中关键的是
model_infer

下载并编译yaml

这一步很关键,我看到网上大部分教程没有,我也是查了很久才知道要下载这个。
yaml项目链接:

https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.7.0

在这里插入图片描述
下载完后解压并建立build文件夹:
在这里插入图片描述
编译参照以下链接:

https://www.cnblogs.com/mxnote/articles/16742022.html

编译完yaml后,将以下目录中lib文件取出来,要复制到paddlx中,详细路径请看下面在这里插入图片描述转到VS2017,将model_infer设为启动项在这里插入图片描述
打开model_infer属性,找到附加包含目录,可以看到目录下有一个关于yaml-cpp的路径,但如果你按照这个路径去看,文件内是没有东西,但是我们编译的时候需要yaml-cpp的头文件。包括进行paddleseg的C++部署时,也是缺少了yaml-cpp。在这里插入图片描述
接下来就是将yaml-cpp-0.7.0中include中的文件复制到PaddleX中去在这里插入图片描述
我们在链接器中也要增加lib路径和相关文件在这里插入图片描述
在这里插入图片描述

编译model_infer

将其中的model_infer.cpp更改如下:

// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
 
#include <gflags/gflags.h>
#include <string>
#include <vector>
#include<opencv2/opencv.hpp>
#include<iostream>
#include "model_deploy/common/include/paddle_deploy.h"
 
using namespace cv;
using namespace std;
 
//DEFINE_string(model_filename, "", "Path of det inference model");
//DEFINE_string(params_filename, "", "Path of det inference params");
//DEFINE_string(cfg_file, "", "Path of yaml file");
//DEFINE_string(model_type, "", "model type");
//DEFINE_string(image, "", "Path of test image file");
//DEFINE_bool(use_gpu, false, "Infering with GPU or CPU");
//DEFINE_int32(gpu_id, 0, "GPU card id");
// 这里的struct是为了在自己的项目中接收推理结果,因为推理结果是
//vector<PaddleDeploy::Result>类型,我们自己的项目中没有
struct result_local
{
    std::vector<uint8_t> data;
    // the shape of mask
    std::vector<float> score;
};
//为了导出dll。
#define DLLEXPORT extern "C" _declspec(dllexport)
 
string model_type = "seg";
PaddleDeploy::Model* model;
//设置接口
DLLEXPORT void Init(string model_filename, string cfg_file, string params_filename, int gpu_id)
{
    // create model
    model = PaddleDeploy::CreateModel(model_type);
    // model init
    model->Init(cfg_file);
    // inference engine init
    PaddleDeploy::PaddleEngineConfig engine_config;
    engine_config.model_filename = model_filename;
    engine_config.params_filename = params_filename;
    engine_config.use_gpu = true;
    engine_config.gpu_id = gpu_id;
    model->PaddleEngineInit(engine_config);
}
 
DLLEXPORT  void Predict(vector<Mat> imgs, vector<result_local>& results_back)
{
    cout << "enter Predict       imgs.size():   " << imgs.size() << endl;
    vector<cv::Mat> imgs_local;
    if (imgs.size() == 0)
    {
        cout << "nothing pic in";
    }
    for (int i = 0; i < imgs.size(); i++)
    {
        imgs_local.push_back(std::move(imgs[i]));
    }
    // predict
    std::vector<PaddleDeploy::Result> results;
    model->Predict(imgs_local, &results, 1);
    for (int i = 0; i < results.size(); i++)
    {
        result_local temp;
        vector<uint8_t> data = results[i].seg_result->label_map.data;
        vector<float> score = results[i].seg_result->score_map.data;
        temp.data = data;
        temp.score = score;
        results_back.push_back(temp);
    }
}
 
//int main(int argc, char** argv) {
//  // Parsing command-line
//  google::ParseCommandLineFlags(&argc, &argv, true);
//
//  // create model
//  PaddleDeploy::Model* model = PaddleDeploy::CreateModel(FLAGS_model_type);
//
//  // model init
//  model->Init(FLAGS_cfg_file);
//
//  // inference engine init
//  PaddleDeploy::PaddleEngineConfig engine_config;
//  engine_config.model_filename = FLAGS_model_filename;
//  engine_config.params_filename = FLAGS_params_filename;
//  engine_config.use_gpu = FLAGS_use_gpu;
//  engine_config.gpu_id = FLAGS_gpu_id;
//  model->PaddleEngineInit(engine_config);
//
//  // prepare data
//  std::vector<cv::Mat> imgs;
//  imgs.push_back(std::move(cv::imread(FLAGS_image)));
//
//  // predict
//  std::vector<PaddleDeploy::Result> results;
//  model->Predict(imgs, &results, 1);
//
//  std::cout << results[0] << std::endl;
//  delete model;
//  return 0;
//}

打开属性页-配置属性-常规,将配置类型改为动态库dll,目标文件扩展名改为.dll。在这里插入图片描述
右键项目-点击生成
在这里插入图片描述
在VS中新建项目

#include<iostream>
#include<opencv2/opencv.hpp>
#include<Windows.h>
using namespace std;
using namespace cv;
 
struct result_now
{
    std::vector<uint8_t> data;
    // the shape of mask
    std::vector<float> score;
};
typedef void(*ptrSub_Init)(string model_filename, string cfg_file, string params_filename, int gpu_id);
typedef void(*ptrSub_predict)(vector<cv::Mat> imgs, vector<result_now>& results_back);
HMODULE hMod = LoadLibrary("model_infer.dll");
typedef void(*ptrSub_batch_Init)(string model_filename, string cfg_file, string params_filename, int gpu_id,bool use_trt);
typedef void(*ptrSub_batch_predict)(std::vector<std::string> image_paths, vector<result_now>& results_back, int batch_size);
HMODULE hMod_batch = LoadLibrary("batch_infer.dll");
//这部分是用于接收model_infer的结果
void normal_infer()
{
    string imgs_path = "D:/VS_projects/test/";
    string cfg_file = "D:/PaddleSeg_projects/PaddleX_DLL/test/deploy.yaml";
    string params_filename = "D:/PaddleSeg_projects/PaddleX_DLL/test/model.pdiparams";
    string model_filename = "D:/PaddleSeg_projects/PaddleX_DLL/test/model.pdmodel";
    vector<string> img_names;
    glob(imgs_path, img_names);
    vector<Mat> imgs;
    for (int i = 0; i < img_names.size(); i++)
    {
        Mat img = imread(img_names[i]);
        imgs.push_back(img);
    }
    vector<result_now> results;
    if (hMod != NULL)
    {
        ptrSub_Init Init = (ptrSub_Init)GetProcAddress(hMod, "Init");
        ptrSub_predict Predict = (ptrSub_predict)GetProcAddress(hMod, "Predict");
        if (Init != NULL)
        {
            Init(model_filename, cfg_file, params_filename, 0);
        }
        if (Predict != NULL)
        {
            Predict(imgs, results);
        }
    }
    std::cout << results.size() << endl;
    std::vector<uint8_t> data = results[0].data;
    for (int i = 0; i < imgs[0].rows; i++)
    {
        for (int j = 0; j < imgs[0].cols; j++)
        {
            if (data[j + imgs[0].cols * i] == 0)
            {
                continue;
            }
            imgs[0].at<Vec3b>(i, j)[0] = data[j + imgs[0].cols * i] * 100;
            imgs[0].at<Vec3b>(i, j)[1] = data[j + imgs[0].cols * i] * 100;
            imgs[0].at<Vec3b>(i, j)[2] = data[j + imgs[0].cols * i] * 100;
        }
    }
    std::vector<uint8_t> data1 = results[1].data;
    for (int i = 0; i < imgs[1].rows; i++)
    {
        for (int j = 0; j < imgs[1].cols; j++)
        {
            if (data1[j + imgs[1].cols * i] == 0)
            {
                continue;
            }
            imgs[1].at<Vec3b>(i, j)[0] = data1[j + imgs[1].cols * i] * 100;
            imgs[1].at<Vec3b>(i, j)[1] = data1[j + imgs[1].cols * i] * 100;
            imgs[1].at<Vec3b>(i, j)[2] = data1[j + imgs[1].cols * i] * 100;
        }
    }
    namedWindow("re", WINDOW_AUTOSIZE);
    imshow("re", imgs[0]);
    namedWindow("re2", WINDOW_AUTOSIZE);
    imshow("re2", imgs[1]);
    waitKey(0);
}
//这部分用于接收batch_infer的结果
void batch_infer()
{
    string imgs_path = "D:/VS_projects/test/";
    string cfg_file = "D:/PaddleSeg_projects/PaddleX_DLL/test/deploy.yaml";
    string params_filename = "D:/PaddleSeg_projects/PaddleX_DLL/test/model.pdiparams";
    string model_filename = "D:/PaddleSeg_projects/PaddleX_DLL/test/model.pdmodel";
    vector<std::string> img_names;
    glob(imgs_path, img_names);
    vector<Mat> imgs;
    for (int i = 0; i < img_names.size(); i++)
    {
        Mat img = imread(img_names[i]);
        imgs.push_back(img);
    }
    vector<result_now> results;
    if (hMod_batch != NULL)
    {
        ptrSub_batch_Init Init = (ptrSub_batch_Init)GetProcAddress(hMod_batch, "Init");
        ptrSub_batch_predict Predict = (ptrSub_batch_predict)GetProcAddress(hMod_batch, "Predict");
        if (Init != NULL)
        {
            Init(model_filename, cfg_file, params_filename,0,false);
        }
        if (Predict != NULL)
        {
            Predict(img_names, results,1);
        }
    }
    std::cout << "local result size       "<<results.size() << endl;
    std::vector<uint8_t> data = results[0].data;
    for (int i = 0; i < imgs[0].rows; i++)
    {
        for (int j = 0; j < imgs[0].cols; j++)
        {
            if (data[j + imgs[0].cols * i] == 0)
            {
                continue;
            }
            imgs[0].at<Vec3b>(i, j)[0] = data[j + imgs[0].cols * i] * 100;
            imgs[0].at<Vec3b>(i, j)[1] = data[j + imgs[0].cols * i] * 100;
            imgs[0].at<Vec3b>(i, j)[2] = data[j + imgs[0].cols * i] * 100;
        }
    }
    std::vector<uint8_t> data1 = results[1].data;
    for (int i = 0; i < imgs[1].rows; i++)
    {
        for (int j = 0; j < imgs[1].cols; j++)
        {
            if (data1[j + imgs[1].cols * i] == 0)
            {
                continue;
            }
            imgs[1].at<Vec3b>(i, j)[0] = data1[j + imgs[1].cols * i] * 100;
            imgs[1].at<Vec3b>(i, j)[1] = data1[j + imgs[1].cols * i] * 100;
            imgs[1].at<Vec3b>(i, j)[2] = data1[j + imgs[1].cols * i] * 100;
        }
    }
    namedWindow("re", WINDOW_AUTOSIZE);
    imshow("re", imgs[0]);
    namedWindow("re2", WINDOW_AUTOSIZE);
    imshow("re2", imgs[1]);
    waitKey(0);
}
int main()
{
    //normal_infer();
    batch_infer();
}

这部分代码感谢该博主在这里插入图片描述
注意,新建项目的属性页需要更改两处:在这里插入图片描述
在这里插入图片描述
部署中也遇到了很多其他问题,翻阅官方部署文档和百度即可解决多数。
PS:在cmake过程中如果遇到了Could NOT find Git (missing: GIT_EXECUTABLE)这个问题,请去git官网页面下载git windows版本并安装,重启后尝试。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值