使用ONNX+TensorRT部署人脸检测和关键点250fps

This article was original written by Jin Tian, welcome re-post, first come with https://jinfagang.github.io . but please keep this copyright info, thanks, any question could be asked via wechat: jintianiloveu

我尽量用尽可能短的语言将本文的核心内容浓缩到文章的标题中,前段时间给大家讲解Jetson Nano的部署,我们讲到用caffe在Nano上部署yolov3,感兴趣的童鞋可以看看之前的文章,然后顺便挖了一个坑:如何部署ONNX模型, 这个问题其实分为两个部分,第一是为什么要用ONNX,第二是如何部署ONNX。本文就是来填这个坑的。

TLTR,本文的核心思想包括:

  • 怎么才能最快速的部署ONNX模型;
  • 当今世界检测人脸和关键点最快的模型是什么?
  • 如何使用ONNX+TensorRT来让你的模型提升7倍加速
  • 我们将向大家介绍我们的新一代人脸检测+比对识别的新一代引擎,有望在GPU上跑到200fps以上,当然也将开源。
  • 如何使用C++在TensorRT上部署ONNX模型。

image

上面是250fps的人脸检测模型,得益于TensorRT的加速。输入尺寸为1280x960.

为什么要用onnx

现在大家都喜欢用pytorch训练模型,而pytorch训练的模型转成pth,用C++推理也很难达到真正的加速效果,因为本质上最耗时的网络前向推理部分并没有太多的加速。并且采用libtorch C++推理pytorch并不是一件简单的事情,除非你的模型可以被trace。

在这种情况之下,引入onnx更合理,从目前整个DL生态来看,onnx具有以下好处:

  • 它的模型格式比基于layer的老一代框架更加细粒度;
  • 它拥有统一化的定义,并且基于任何框架都可以推理他;
  • 它可以实现不同框架之间的互相转化。

前段时间,我们release了一个retinaface的pytorch项目,并且我们想办法将它导出到了onnx模型,当然这期间经过一些修改,没有复杂模型的代码可以在不修改的情况下轻而易举export到onnx,关于这部分代码可以在我们的平台上找到:

http://manaai.cn

我们今天要做的事情,就是在上面的onnx模型的基础上,采用TensorRT来进行推理。先做一个简单的速度对比:

框架 语言 耗时(s) fps
Pytorch python 0.012+0.022 29
ONNXRuntime python 0.008+0.022 34
TensorRT C++ 0.004+0.001 250

可以看到,采用TensorRT对ONNX模型加速,速度提升可以说是天囊之别。并且,采用TensorRT纯C++推理可以在语言层面获得更多的加速。我们实现的TensorRT加速的Retinaface应该是目前来讲面向GPU速度最快的检测方案,并且可以同时生成bbox和landmark,相比于MTCNN,模型更加简单,推理更加快速,准确度更高.

真正落地的算法部署,毫无疑问,假如你的target是GPU,采用ONNX+TensorRT应该是目前最成熟、最优化的方案。假如你的target是一些嵌入式芯片,那么采用MNN也是可以通过onnx轻松实现CPU嵌入式端快速推理的。

既然ONNX和TensorRT这么好,为什么都不用呢?为什么都还在用Python写难看的推理的代码呢?原因也很简单:

  • 入门太难,C++一般人玩不来;
  • 既要懂模型的每一层输入输出,又要懂TensorRT的API,至少要很熟悉。

今天这篇教程便是教大家如何一步一步的实现TensorRT实现最快速的推理。先来看看实际TensorRT加速的效果:

image

看图片看不出啥来,看视频:

image

效果还是非常不错的。

Retinaface模型简单介绍

retinaface是Insightface做的一个动作(DeepInsight), 但是原始的只有MXNet版本,这个网络模型具有小巧精度高特点,并且它是一个带有landmark分支输出的网络,这使得该模型可以输出landmark。

这个网络之所以叫做retina是因为它引入了FPN的结构和思想,使得模型在小尺度的脸上具有更好的鲁棒性。

在这里我们引入一个工具:sudo pip3 install onnxexplorer 可以快速的查看我们的onnx模型的结构,我们需要用到的onnx模型可以从这个地方下载:http://manaai.cn/aicodes_detail3.html?id=46

我们做了一些修改使得pytorch的模型可以导出到onnx,并且我们做了一些特殊的处理,使得onnx模型可以通过 onnx2trt转到TensorRT的engine。

TensorRT C++推理

接下来应该是本文的核心内容了,上面提到的 onnx2trt 可以通过编译 https://gitub.com/onnx/onnx-tensorrt 仓库,来得到 onnx2trt ,通过这个执行程序,可以将onnx转到trt的engine。

在这里,假如你是新手,有一点需要注意:

  • 并不是所有的onnx都能够成功转到trt engine,除非你onnx模型里面所有的op都被支持;
  • 你需要在电脑中安装TensorRT 6.0,因为只有TensorRT6.0支持动态的输入。

闲话不多说,假如我们拿到了trt的engine,我们如何进行推理呢?总的来说,分为3步:

  1. 首先load你的engine,拿到一个 ICudaEngine, 这个是TensorRT推理的核心;
  2. 你需要定位你的模型的输入和输出,有几个输入有几个输出;
  3. forward模型,然后拿到输出,对输出进行后处理。

当然这里最核心的东西其实就两个,一个是如何导入拿到CudaEngine,第二个是比较麻烦的后处理。

 IBuilder* builder = createInferBuilder(gLogger);assert(builder != nullptr);nvinfer1::INetworkDefinition* network = builder->createNetwork();auto parser = nvonnxparser::createParser(*network, gLogger);if ( !parser->parseFromFile(modelFile.c_str(), static_cast<int>(gLogger.reportableSeverity) ) ){cerr << "Failure while parsing ONNX file" << std::endl;}IHostMemory *trtModelStream{nullptr};// Build the enginebuilder->setMaxBatchSize(maxBatchSize);builder->setMaxWorkspaceSize(1 << 30);if (mTrtRunMode == RUN_MODE::INT8) {std::cout << "setInt8Mode" << std::endl;if (!builder->platformHasFastInt8())std::cout << "Notice: the platform do not has fast for int8" << std::endl;
//    builder->setInt8Mode(true);
//    builder->setInt8Calibrator(calibrator);cerr << "int8 mode not supported for now.\n";} else if (mTrtRunMode == RUN_MODE::FLOAT16) {std::cout << "setFp16Mode" << std::endl;if (!builder->platformHasFastFp16())std::cout << "Notice: the platform do not has fast for fp16" << std::endl;builder->setFp16Mode(true);}ICudaEngine* engine = builder->buildCudaEngine(*network);assert(engine);// we can destroy the parserparser->destroy();// serialize the engine, then close everything downtrtModelStream = engine->serialize();trtModelStream->destroy();InitEngine();

这个是我们维护的 onnx_trt_engine的一部分,这段代码的作用是直接将你之前生成的trt engine,导入到你的ICudaEngine之中。大家如果需要完整的code,可以在我们的MANA平台上转到并下载:

http://manaai.cn

大家可以看到,假如你想对模型进行进一步的加速,实际上也是在这上面进行。当你拿到你的 iCudaEngine之后,剩下的事情就是根据你的model的output name拿到对应的输出。整个过程其实还是可以一气呵成的,唯一可能复杂一点的是你需要动态allocate对应大小size的data。

 auto out1 = new float[bufferSize[1] / sizeof(float)];auto out2 = new float[bufferSize[2] / sizeof(float)];auto out3 = new float[bufferSize[3] / sizeof(float)];cudaStream_t stream;CHECK(cudaStreamCreate(&stream));CHECK(cudaMemcpyAsync(buffers[0], input, bufferSize[0], cudaMemcpyHostToDevice, stream));
//  context.enqueue(batchSize, buffers, stream,nullptr);context.enqueue(1, buffers, stream, nullptr);CHECK(cudaMemcpyAsync(out1, buffers[1], bufferSize[1], cudaMemcpyDeviceToHost, stream));CHECK(cudaMemcpyAsync(out2, buffers[2], bufferSize[2], cudaMemcpyDeviceToHost, stream));CHECK(cudaMemcpyAsync(out3, buffers[3], bufferSize[3], cudaMemcpyDeviceToHost, stream));cudaStreamSynchronize(stream);// release the stream and the bufferscudaStreamDestroy(stream);CHECK(cudaFree(buffers[0]));CHECK(cudaFree(buffers[1]));CHECK(cudaFree(buffers[2]));CHECK(cudaFree(buffers[3]));

这是如何从TensorRT推理的结果转到我们的CPU上来,并且通过Async来同步数据,最终你拿到的数据将在你事先定义好的buffer里面,再进行后处理即可。

由于C++代码过于庞大和复杂,这些代码将会开源到我们的MANA AI平台。当然我们花费了很多力气来编写教程,并且提供源码,如果你对AI感兴趣,而缺乏一个好的学习群体和导师,不妨加入我们的会员计划,我们是一个致力于打造工业级前沿黑科技的AI学习者群体。

我们pytorch的训练代码可以在这里找到:

http://manaai.cn/aicodes_detail3.html?id=46

TensorRT部署完整的代码可以在这里找到:

http://manaai.cn/aicodes_detail3.html?id=48

ONNX+TensorRT相关推荐

  1. 【mmdeploy】mmseg转ONNX/TensorRT,附推理代码

    目录 1.关于mmdeploy 2.环境安装 2.1预编译安装(Linux-x86_64, CUDA 11.x, TensorRT 8.2.3.0): 2.2预编译安装(Linux-x86_64, C ...

  2. Pytorch → ONNX → TensorRT

    Pytorch → ONNX → TensorRT 由于实验室与应急减灾中心关于道路检测的项目需加快推理速度,在尝试手动融合模型的Con层和bn层发现推理速度提升不明显之后,我的"mento ...

  3. pytorch C++部署模型 ONNX tensorRT

    (1) C++部署pytorch模型(上) (2) TensorRT5介绍及Pytorch转TensorRT5代码示例 TensorRT的使用步骤:(假设以及有一个训练好的模型) (1) 根据模型创建 ...

  4. 部署教程 | ResNet原理+PyTorch复现+ONNX+TensorRT int8量化部署

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 1简介 这是[集智书童]第一次录制视频的PPT课件,这里公开给大家 ...

  5. 用于ONNX的TensorRT后端

    用于ONNX的TensorRT后端 解析ONNX模型以使用TensorRT执行. 另请参阅TensorRT文档. 有关最近更改的列表,请参见changelog. 支持的TensorRT版本 Maste ...

  6. onnx 测试_用于ONNX的TensorRT后端

    用于ONNX的TensorRT后端 解析ONNX模型以使用TensorRT执行. 另请参阅TensorRT文档. 有关最近更改的列表,请参见changelog. 支持的TensorRT版本 Maste ...

  7. onnx 测试_pytorch onnx onnxruntime tensorrt踩坑 各种问题

    做了一个小测试,发现pytorch onnx tensorrt三个库的版本存在微妙的联系,在我之前的错误实验中,PyTorch==1.3.0/1.4.0:Onnx==1.6.0:tensorrt=7. ...

  8. 一文玩转tensorrt onnx+tensorrtx

    文章目录 前言 一.浅谈tensorrt 二.tensorrtx的使用学习轨迹 1.tensorrtx-初出茅庐 2.崭露头角-tensorrtx 3.身手不凡-ONNX 4.风云叱咤-ONNX 5. ...

  9. TensorRT ONNX 基础

    TensorRT ONNX 基础 tensorRT从零起步迈向高性能工业级部署(就业导向) 课程笔记,讲师讲的不错,可以去看原视频支持下. 概述 TensorRT 的核心在于对模型算子的优化(合并算子 ...

最新文章

  1. C++中Delete时堆错误(Heap Corruption)的原因
  2. Spring Boot学习笔记(1)
  3. SmartTemplate学习入门一
  4. Shell编程之通配符和用户自定义变量
  5. CVE-2021-1675: Windows Print Spooler远程代码执行漏洞
  6. 11.15PMP试题每日一题
  7. 我就是认真:Linux SWAP 深度解读(必须收藏)
  8. c# 实现圆形的进度条(ProgressBar)
  9. 为什么平方损失函数不适应于分类问题?——从概率论的角度
  10. 数字未来,NFT未来,Game Farmer创始人胡烜峰在IGS上讲述FoxNFT和他的故事
  11. Eclipse常用便捷设置
  12. php生成word并下载
  13. 真的会有大牛市吗老大?前提条件是破2万美刀,差一刀都不行!
  14. 解决Centos8自带Firefox实现播放声音与视频-Linux、VMware
  15. JavaScript实现外溢动态的心
  16. 一个 简约 干净 纯净的网址导航 净搜导航
  17. 客流量总是少?是你门店选址出了问题!
  18. 大数据竞赛-----DC竞赛ANC
  19. 认证 (authentication) 和授权 (authorization) 的区别.md
  20. 数据应用案例之“客户画像体系”

热门文章

  1. LINUX自旋锁详解
  2. 对频率论(Frequentist)方法和贝叶斯方法(Bayesian Methods)的一个总结
  3. 解析jsonarra_使用JSONReader或JSONObject / JSONArray解析JSON数据
  4. m1芯片 服务器,m1服务器地址
  5. java 方法不同_java同一个类不同方法间的同步
  6. 计算机的工作原理题,计算机工作原理试题期中试卷
  7. VSCODE常见问题(设置为4个空格)
  8. protobuf-2.6.1生成java文件
  9. 分数序数之和c语言,用c语言求解:有一分数序列2/1,3/2,5/3,8/5,13/8,21/13,…求这个数列的前20项之和....
  10. 软件测试工具按用途分分为哪几类,以测试的形态分软件测试可以分为哪几类?...