PaddleSeg学习4——paddle模型使用TensorRT推理(c++)

paddle模型使用TensorRT推理

  • 1 模型末端添加softmax和argmax算子
  • 2 paddle模型转onnx模型
  • 3 onnx模型转TensorRT模型
    • 3.1 安装TensorRT-8.5.3.1
    • 3.2 使用 trtexec 将onnx模型编译优化导出为engine模型
  • 4 TensorRT模型推理测试
  • 5 完整代码
  • 6 测试结果

1 模型末端添加softmax和argmax算子

前文 PaddleSeg c++部署OCRNet+HRNet模型中的语义分割模型输出为float32类型,模型不含softmax和argmax处理,导致在项目应用过程中后处理耗时较高。
通过PaddleSeg/tools/export.py在网络末端增加softmax和argmax算子,解决应用中的后处理耗时问题。

参考文档PaddleSeg/docs/model_export_cn.md导出预测模型。将导出的预测模型文件保存在output/inference_model文件夹中,如下。模型输出类型为int32

./output/inference_model├── deploy.yaml            # 部署相关的配置文件,主要说明数据预处理的方式├── model.pdmodel          # 预测模型的拓扑结构文件├── model.pdiparams        # 预测模型的权重文件└── model.pdiparams.info   # 参数额外信息,一般无需关注网络输出类型为int32。
python tools/export.py \--config  configs\ocrnet\ocrnet_hrnetw18_cityscapes_1024x512_160k_lovasz_softmax.yml\--model_path output\iter_12000\model.pdparams \--save_dir output\inference_model--output_op argmax

PaddleSeg v2.0以前export.py中不含argmaxsoftmax参数选项,可通过以下代码在模型末端增加softmaxargmax算子。

import argparse
import os
import paddle
import yaml
from paddleseg.cvlibs import Config
from paddleseg.utils import loggerdef parse_args():parser = argparse.ArgumentParser(description='Model export.')# params of trainingparser.add_argument("--config",dest="cfg",help="The config file.",default=None,type=str,required=True)parser.add_argument('--save_dir',dest='save_dir',help='The directory for saving the model snapshot',type=str,default='./output')parser.add_argument('--model_path',dest='model_path',help='The path of model for evaluation',type=str,default=None)return parser.parse_args()class SavedSegmentationNet(paddle.nn.Layer):def __init__(self, net, without_argmax=False, with_softmax=False):super().__init__()self.net = netself.post_processer = PostPorcesser(without_argmax, with_softmax)def forward(self, x):outs = self.net(x)outs = self.post_processer(outs)return outsclass PostPorcesser(paddle.nn.Layer):def __init__(self, without_argmax, with_softmax):super().__init__()self.without_argmax = without_argmaxself.with_softmax = with_softmaxdef forward(self, outs):new_outs = []for out in outs:if self.with_softmax:out = paddle.nn.functional.softmax(out, axis=1)if not self.without_argmax:out = paddle.argmax(out, axis=1)new_outs.append(out)return new_outsdef main(args):os.environ['PADDLESEG_EXPORT_STAGE'] = 'True'cfg = Config(args.cfg)net = cfg.modelif args.model_path:para_state_dict = paddle.load(args.model_path)net.set_dict(para_state_dict)logger.info('Loaded trained params of model successfully.')# 增加softmax、argmax处理new_net = SavedSegmentationNet(net, True,True)new_net.eval()new_net = paddle.jit.to_static(new_net,input_spec=[paddle.static.InputSpec(shape=[None, 3, None, None], dtype='float32')])save_path = os.path.join(args.save_dir, 'model')paddle.jit.save(new_net, save_path)yml_file = os.path.join(args.save_dir, 'deploy.yaml')with open(yml_file, 'w') as file:transforms = cfg.export_config.get('transforms', [{'type': 'Normalize'}])data = {'Deploy': {'transforms': transforms,'model': 'model.pdmodel','params': 'model.pdiparams'}}yaml.dump(data, file)logger.info(f'Model is saved in {args.save_dir}.')if __name__ == '__main__':args = parse_args()main(args)

2 paddle模型转onnx模型

参考文档 PaddleSeg/docs/model_export_onnx_cn.md
参考文档Paddle2ONNX

(1)安装Paddle2ONNX

pip install paddle2onnx

(2)模型转换
执行如下命令,使用Paddle2ONNXoutput/inference_model文件夹中的预测模型导出为ONNX格式模型。将导出的预测模型文件保存为model.onnx

paddle2onnx --model_dir output/inference_model \--model_filename model.pdmodel \--params_filename model.pdiparams \--opset_version 12 \--save_file model.onnx \--enable_dev_version True

3 onnx模型转TensorRT模型

3.1 安装TensorRT-8.5.3.1

参考TensorRt安装

3.2 使用 trtexec 将onnx模型编译优化导出为engine模型

由于是动态输入,因此指定了输入尺寸范围和最优尺寸。将导出的预测模型文件保存为model.trt

trtexec.exe --onnx=model.onnx --explicitBatch --fp16 --minShapes=x:1x3x540x960 --optShapes=x:1x3x720x1280 --maxShapes=x:1x3x1080x1920 --saveEngine=model.trt

4 TensorRT模型推理测试

参考TensorRt动态尺寸输入的分割模型测试

5 完整代码

namespace TRTSegmentation {class Logger : public nvinfer1::ILogger{public:Logger(Severity severity = Severity::kWARNING) :severity_(severity) {}virtual void log(Severity severity, const char* msg) noexcept override{// suppress info-level messagesif (severity <= severity_) {//std::cout << msg << std::endl;}}nvinfer1::ILogger& getTRTLogger() noexcept{return *this;}private:Severity severity_;};struct InferDeleter{template <typename T>void operator()(T* obj) const{delete obj;}};template <typename T>using SampleUniquePtr = std::unique_ptr<T, InferDeleter>;class LaneSegInferTRT{public:LaneSegInferTRT(const std::string seg_model_dir = "") {this->seg_model_dir_ = seg_model_dir;InitPredictor();}~LaneSegInferTRT(){cudaFree(bindings_[0]);cudaFree(bindings_[1]);}void PredictSeg(const cv::Mat &image_mat, std::vector<PaddleSegmentation::DataLane> &solLanes /*实线*/,std::vector<PaddleSegmentation::DataLane> &dasLanes /*虚线*/,std::vector<double>* times = nullptr);private:void InitPredictor();// Preprocess image and copy data to input buffercv::Mat Preprocess(const cv::Mat& image_mat);// Postprocess imagevoid Postprocess(int rows, int cols, std::vector<int> &out_data,std::vector<PaddleSegmentation::DataLane> &solLanes,std::vector<PaddleSegmentation::DataLane> &dasLanes);private://static const int num_classes_ = 15;std::shared_ptr<nvinfer1::ICudaEngine> mEngine_;SampleUniquePtr<nvinfer1::IExecutionContext> context_seg_lane_;std::vector<void*> bindings_;std::string seg_model_dir_;int gpuMaxBufSize = 1280 * 720; // output};}//namespace PaddleSegmentation
#include "LaneSegInferTRT.hpp"
namespace {class Logger : public nvinfer1::ILogger{public:Logger(Severity severity = Severity::kWARNING) :severity_(severity) {}virtual void log(Severity severity, const char* msg) noexcept override{// suppress info-level messagesif (severity <= severity_) {//std::cout << msg << std::endl;}}nvinfer1::ILogger& getTRTLogger() noexcept{return *this;}private:Severity severity_;};
}namespace TRTSegmentation {#define CHECK(status)                                                                                                  \do                                                                                                                 \{                                                                                                                  \auto ret = (status);                                                                                           \if (ret != 0)                                                                                                  \{                                                                                                              \std::cerr << "Cuda failure: " << ret << std::endl;                                                         \}                                                                                                              \} while (0)void LaneSegInferTRT::InitPredictor(){if (seg_model_dir_.empty()) {throw "Predictor must receive seg_model!";}std::ifstream ifs(seg_model_dir_, std::ifstream::binary);if (!ifs) {throw "seg_model_dir error!";}ifs.seekg(0, std::ios_base::end);int size = ifs.tellg();ifs.seekg(0, std::ios_base::beg);std::unique_ptr<char> pData(new char[size]);ifs.read(pData.get(), size);ifs.close();// engine模型Logger logger(nvinfer1::ILogger::Severity::kVERBOSE);SampleUniquePtr<nvinfer1::IRuntime> runtime{nvinfer1::createInferRuntime(logger.getTRTLogger()) };mEngine_ = std::shared_ptr<nvinfer1::ICudaEngine>(runtime->deserializeCudaEngine(pData.get(), size), InferDeleter());this->context_seg_lane_ = SampleUniquePtr<nvinfer1::IExecutionContext>(mEngine_->createExecutionContext());bindings_.resize(mEngine_->getNbBindings());CHECK(cudaMalloc(&bindings_[0], sizeof(float) * 3 * gpuMaxBufSize));    // n*3*h*wCHECK(cudaMalloc(&bindings_[1], sizeof(int) * 1 * gpuMaxBufSize));      // n*1*h*w}cv::Mat LaneSegInferTRT::Preprocess(const cv::Mat& image_mat){cv::Mat img;cv::cvtColor(image_mat, img, cv::COLOR_BGR2RGB);if (true/*is_normalize*/) {img.convertTo(img, CV_32F, 1.0 / 255, 0);img = (img - 0.5) / 0.5;}return img;}void LaneSegInferTRT::PredictSeg(const cv::Mat &image_mat,std::vector<PaddleSegmentation::DataLane> &solLanes ,std::vector<PaddleSegmentation::DataLane> &dasLanes,std::vector<double>* times){// Preprocess imagecv::Mat img = Preprocess(image_mat);		int rows = img.rows;int cols = img.cols;this->context_seg_lane_->setBindingDimensions(0, nvinfer1::Dims4{ 1, 3 , rows, cols });int chs = img.channels();std::vector<float> input_data(1 * chs * rows * cols, 0.0f);hwc_img_2_chw_data(img, input_data.data());		CHECK(cudaMemcpy(bindings_[0], static_cast<const void*>(input_data.data()), 3 * img.rows * img.cols * sizeof(float), cudaMemcpyHostToDevice));// Run predictor 推理context_seg_lane_->executeV2(bindings_.data());// Get output tensor		std::vector<int> out_data(1 * 1 * rows * cols);CHECK(cudaMemcpy(static_cast<void*>(out_data.data()), bindings_[1], out_data.size() * sizeof(int), cudaMemcpyDeviceToHost));// PostprocessingPostprocess(rows, cols, out_data, solLanes,dasLanes);}void LaneSegInferTRT::Postprocess(int rows, int cols, vector<int>& out_data,std::vector<PaddleSegmentation::DataLane> &solLanes,std::vector<PaddleSegmentation::DataLane> &dasLanes){PaddleSegmentation::LanePostProcess laneNet(rows, cols);laneNet.lanePostprocessForTRT(out_data,solLanes,dasLanes);}	}//namespace PaddleSegmentation

6 测试结果

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/615318.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022 年全国职业院校技能大赛高职组云计算赛项试卷

【赛程名称】云计算赛项第一场-私有云 某企业拟使用OpenStack 搭建一个企业云平台&#xff0c;以实现资源池化弹性管理、企业应用集中管理、统一安全认证和授权等管理。 系统架构如图 1 所示&#xff0c;IP 地址规划如表 1 所示。 图 1 系统架构图 表 1 IP 地址规划 设备…

docker 利用特权模式逃逸并拿下主机

docker 利用特权模式逃逸并拿下主机 在溯源反制过程中&#xff0c;会经常遇到一些有趣的玩法&#xff0c;这里给大家分享一种docker在特权模式下逃逸&#xff0c;并拿下主机权限的玩法。 前言 在一次溯源反制过程中&#xff0c;发现了一个主机&#xff0c;经过资产收集之后&…

网站开发第一弹---HTML01

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;网站开发flask框架 &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现…

基于pytorch的循环神经网络情感分析系统

任务目标 基于给定数据集&#xff0c;进行数据预处理&#xff0c;搭建以LSTM为基本单元的模型&#xff0c;以Adam优化器对模型进行训练&#xff0c;使用训练后的模型进行预测并计算预测分类的准确率。 数据简介 IMDB数据集是一个对电影评论标注为正向评论与负向评论的数据集…

【AI视野·今日NLP 自然语言处理论文速览 第七十二期】Mon, 8 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Mon, 8 Jan 2024 Totally 17 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers DeepSeek LLM: Scaling Open-Source Language Models with Longtermism Authors DeepSeek AI Xiao Bi, Deli Ch…

深度卷积神经网络

目录 1.AlexNet 2. 代码实现 1.AlexNet (1)特征提取 (2)选择核函数来计算相关性&#xff1a;怎么判断在高维空间里面两个点是如何相关的&#xff0c;如果是线性模型就是做内积。 (3)凸优化问题 (4)漂亮的定理 丢弃法的作用就是因为模型太大了&#xff0c;使用它来对模型做…

无监督学习Principal Component Analysis(PCA)精简高维数据

目录 介绍 一、PCA之前 二、PCA之后 介绍 Principal Component Analysis (PCA) 是一种常用的数据降维和特征提取技术。PCA通过线性变换将高维数据映射到低维空间&#xff0c;从而得到数据的主要特征。PCA的目标是找到一个正交基的集合&#xff0c;使得将数据投影到这些基…

初探UAF漏洞(3)

构造exp #include <iostream> #include <Windows.h>typedef void(*FunctionPointer) ();typedef struct _FAKE_USE_AFTER_FREE {FunctionPointer countinter;char bufffer[0x54]; }FAKE_USE_AFTER_FREE, * PUSE_AFTER_FREE;void ShellCode() {_asm{noppushadmov e…

github上的python图片转excel,pytesseract安装相关问题

问题1&#xff1a;明明都pip install pytesseract&#xff0c;但是就是安装不上 pytesseract 未安装链接: https://pan.baidu.com/s/1I4HzCgO4mITWTcZFkdil6g?pwdafes 提取码: afes 安装后一路next&#xff0c;然后配置环境变量 C:\Program Files\Tesseract-OCR新建一个系统…

c++学习:容器stack栈+queue+map(简易输入法)+deque

目录 stack 模板原型 头文件 模板的成员类型和成员对象和成员函数 栈类模板的容器对象 实例 queue 模板原型 头文件 模板的成员类型和成员对象和成员函数 队列类模板的容器对象 实例 map 模板原型 头文件 模板的成员类型和成员对象和成员函数 关联类模板的容器…

VScode远程连接开发嵌入式开发板

在做嵌入式开发时&#xff0c;很多时候需要远程连接或者远程调试设备&#xff0c;这时可以通过VScode上的插件来很方便的进行远程连接和调试。 ssh远程连接嵌入式开发板&#xff1a; 1、安装vscode ssh远程插件&#xff1a;Remote-SSH。 2、点击""&#xff0c;输入…

构建基于RHEL8系列(CentOS8,AlmaLinux8,RockyLinux8等)的MySQL8.0.32的RPM包

本文适用&#xff1a;rhel8系列&#xff0c;或同类系统(CentOS8,AlmaLinux8,RockyLinux8等) 文档形成时期&#xff1a;2023年 因系统版本不同&#xff0c;构建部署应略有差异&#xff0c;但本文未做细分&#xff0c;对稍有经验者应不存在明显障碍。 因软件世界之复杂和个人能力…

监督学习 - 逻辑回归(Logistic Regression)

什么是机器学习 逻辑回归&#xff08;Logistic Regression&#xff09;虽然名字中包含"回归"一词&#xff0c;但实际上是一种用于解决分类问题的统计学习方法&#xff0c;而不是回归问题。它是一种线性模型&#xff0c;常用于二分类问题&#xff0c;也可以扩展到多分…

Inis博客系统本地部署结合内网穿透实现远程访问本地站点

文章目录 前言1. Inis博客网站搭建1.1. Inis博客网站下载和安装1.2 Inis博客网站测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总…

搭建sprinboot服务环境

搭建sprinboot服务环境 安装jdk安装nginx安装Redis安装MySQL一 下载MySQL二 安装MySQL三 启动mysql服务获取初始化密码四 登陆MySQL五 修改密码六 设置远程访问七 相关问题错误&#xff1a;1819错误&#xff1a;1251 或 2059错误&#xff1a;10060忽略表名大小写 记录搭建sprin…

【Docker】概述与安装

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一. Docker的概述 1.Docker为什么出现 2…

Vue入门五(Vue-CLI项目搭建|vue项目目录介绍|vue项目开发规范|es6导入导出语法)

文章目录 一、Vue-CLI 项目搭建介绍node环境搭建1) 下载与安装2&#xff09;测试是否安装成功 安装vue-cli安装vue脚手架 创建Vue项目1&#xff09;使用命令创建项目2&#xff09;使用图形化界面创建项目 二、vue项目目录介绍1.命令行运行vue项目2.Pycharm中运行项目3.目录结构…

Java基础项目---飞机大战的简易实现

推荐阅读 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;一&#xff09; 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;二&#xff09; 文章目录 推荐阅读前言一、系统分析问题描述总体设计功能流程图 二、程序和算法的介绍FlyingOb…

Open CASCADE学习|参数化球面的奇异性

参数曲面的奇异性是一个相对复杂的概念&#xff0c;它涉及到参数曲面的几何特性和参数化过程中的一些特殊情况。参数曲面通常用于描述三维空间中的复杂形状&#xff0c;通过参数方程将二维参数域映射到三维空间中。然而&#xff0c;在某些情况下&#xff0c;参数曲面可能会表现…

回顾2023,展望未来

回顾2023 重拾博客 CSDN博客创建和写作&#xff0c;几乎是和我正式开始学习编程开始&#xff0c;至今已经6年。刚上编程课的时候&#xff0c;刚上C语言课的时候&#xff0c;老师说可以通过写技术博客来帮助自己更好学习&#xff0c;于是我就开始自己的技术博客编写之旅。 我…