TensorRT开始

TensorRT 是 NVIDIA 自家的高性能推理库,其Getting Started[1]列出了各资料入口,如下:

TensorRT开始

本文基于当前的 TensorRT 8.2 版本,将一步步介绍从安装,直到加速推理自己的 ONNX 模型。

安装

TensorRT 下载页[2]选择版本下载,需注册登录。

TensorRT开始

本文选择了TensorRT-8.2.2.1.Linux.x86_64-gnu.cuda-11.4.cudnn8.2.tar.gz,可以注意到与CUDA[3]cuDNN[4]要匹配好版本。也可以准备NVIDIA Docker[5]拉取对应版本的nvidia/cuda[6]镜像,再ADDTensorRT即可。

解压进 $HOME (以免 sudo 编译样例,为当前用户)tar-xzvf TensorRT-*.tar.gz-C$HOME/软链到 /usr/local/TensorRT (以固定一个路径)sudo ln -s$HOME/TensorRT-8.2.2.1/usr/local/TensorRT

之后,编译运行样例,保证 TensorRT 安装正确。

编译样例

样例在TensorRT/samples,说明见Sample Support Guide[7]或各样例目录里的README.md

cd/usr/local/TensorRT/samples/设定环境变量,可见 Makefile.configexportCUDA_INSTALL_DIR=/usr/local/cudaexportCUDNN_INSTALL_DIR=/usr/local/cudaexportENABLE_DLA=exportTRT_LIB_DIR=../libexportPROTOBUF_INSTALL_DIR=编译make -j`nproc`运行exportLD_LIBRARY_PATH=/usr/local/TensorRT/lib:$LD_LIBRARY_PATHcd/usr/local/TensorRT/
./bin/trtexec -h
./bin/sample_mnist -d data/mnist/ --fp16

运行结果参考:

$./bin/sample_mnist-ddata/mnist/--fp16&&&&RUNNINGTensorRT.sample_mnist[TensorRTv8202]./bin/sample_mnist -d data/mnist/ --fp16[12/23/2021-20:20:16][I]BuildingandrunningaGPUinferenceengineforMNIST[12/23/2021-20:20:16][I][TRT][MemUsageChange]Init CUDA:CPU+322,GPU+0,now:CPU333,GPU600(MiB)[12/23/2021-20:20:16][I][TRT][MemUsageSnapshot]Begin constructing builder kernel library:CPU333MiB,GPU600MiB[12/23/2021-20:20:16][I][TRT][MemUsageSnapshot]End constructing builder kernel library:CPU468MiB,GPU634MiB[12/23/2021-20:20:17][I][TRT][MemUsageChange]Init cuBLAS/cuBLASLt:CPU+518,GPU+224,now:CPU988,GPU858(MiB)[12/23/2021-20:20:17][I][TRT][MemUsageChange]Init cuDNN:CPU+114,GPU+52,now:CPU1102,GPU910(MiB)[12/23/2021-20:20:17][I][TRT]Localtimingcacheinuse.Profilingresultsinthisbuilderpasswillnotbestored.[12/23/2021-20:20:33][I][TRT]Sometacticsdonothavesufficientworkspacememorytorun.Increasingworkspacesizemayincreaseperformance,pleasecheckverboseoutput.[12/23/2021-20:20:34][I][TRT]Detected1inputsand1outputnetworktensors.[12/23/2021-20:20:34][I][TRT]Total Host Persistent Memory:8448[12/23/2021-20:20:34][I][TRT]Total Device Persistent Memory:1626624[12/23/2021-20:20:34][I][TRT]Total Scratch Memory:0[12/23/2021-20:20:34][I][TRT][MemUsageStats]Peak memory usage of TRT CPU/GPU memory allocators:CPU2MiB,GPU13MiB[12/23/2021-20:20:34][I][TRT][BlockAssignment]AlgorithmShiftNTopDowntook0.01595mstoassign3blocksto8nodesrequiring57857bytes.[12/23/2021-20:20:34][I][TRT]Total Activation Memory:57857[12/23/2021-20:20:34][I][TRT][MemUsageChange]Init cuBLAS/cuBLASLt:CPU+0,GPU+8,now:CPU1621,GPU1116(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]Init cuDNN:CPU+0,GPU+8,now:CPU1621,GPU1124(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]TensorRT-managed allocation in building engine:CPU+0,GPU+4,now:CPU0,GPU4(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]Init CUDA:CPU+0,GPU+0,now:CPU1622,GPU1086(MiB)[12/23/2021-20:20:34][I][TRT]Loaded engine size:1MiB[12/23/2021-20:20:34][I][TRT][MemUsageChange]Init cuBLAS/cuBLASLt:CPU+0,GPU+8,now:CPU1622,GPU1096(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]Init cuDNN:CPU+1,GPU+8,now:CPU1623,GPU1104(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]TensorRT-managed allocation in engine deserialization:CPU+0,GPU+1,now:CPU0,GPU1(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]Init cuBLAS/cuBLASLt:CPU+0,GPU+8,now:CPU1485,GPU1080(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]Init cuDNN:CPU+0,GPU+8,now:CPU1485,GPU1088(MiB)[12/23/2021-20:20:34][I][TRT][MemUsageChange]TensorRT-managed allocation in IExecutionContext creation:CPU+0,GPU+2,now:CPU0,GPU3(MiB)[12/23/2021-20:20:34][I]Input:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+-:=@@@@@@@@@@@@@@@@@@@%=-@@@**@@@@@@@@@@@@@@:%@-@@@.@@@@@@@@@@@@*+@@@@:*@@@*@@@@@@@@@@@@+@@@@@@@%@@@@@@@@@@@@@@.:%@@.@@@.*@@@@@@@@@@@@@@@-=@@@@.-@@@@@@@@@@@@@@@@@%:+@-:@@@@@@@@@@@@@@@@@@@@%.:-@@@@@@@@@@@@@@@@@@@@@@@+@@@@@@@@@@@@@@@@@@@@@@@@+:@@@@@@@@@@@@@@@@@@@@@@@@+*@@@@@@@@@@@@@@@@@@@@@@@:=@@@@@@@@@@@@@@@@@@@@@@@:@@@@@@@@@@@@@@@@@@@@@@@@-@@@@@@@@@@@@@@@@@@@@@@@+@@@@@@@@@@@@@@@@@@@@@@@*++@@@@@@@@@@@@@@@@@@@@@@**@@@@@@@@@@@@@@@@@@@@@@=@@@@@@@@@@@@@@@@@@@@@@@@.+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[12/23/2021-20:20:34][I]Output:0:1:2:3:4:5:6:7:8:**********9:&&&&PASSEDTensorRT.sample_mnist[TensorRTv8202]./bin/sample_mnist -d data/mnist/ --fp16

快速开始

Quick Start Guide / Using The TensorRT Runtime API[8]

准备教程代码,编译:

gitclone--depth 1 https://github.com/NVIDIA/TensorRT.gitexportCUDA_INSTALL_DIR=/usr/local/cudaexportCUDNN_INSTALL_DIR=/usr/local/cudaexportTRT_LIB_DIR=/usr/local/TensorRT/lib编译 quickstartcdTensorRT/quickstartMakefile.configINCPATHS += -I"/usr/local/TensorRT/include"common/logging.hvoid log(Severity severity, const char* msg) noexcept overridemake运行环境exportPATH=/usr/local/TensorRT/bin:$PATHexportLD_LIBRARY_PATH=/usr/local/TensorRT/lib:$LD_LIBRARY_PATHcdSemanticSegmentation

获取预训练FCN-ResNet-101[9]模型,转成 ONNX:

创建本地环境conda create -n torch python=3.9 -yconda activate torchconda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch -y不然,容器环境docker run --rm -it --gpus all -p 8888:8888 -v `pwd`:/workspace/SemanticSegmentation -w /workspace nvcr.io/nvidia/pytorch:20.12-py3 bash$ pythonexport.py
Exporting ppm image input.ppm
Downloading:"https://github.com/pytorch/vision/archive/v0.6.0.zip"to/home/john/.cache/torch/hub/v0.6.0.zip
Downloading:"https://download.pytorch.org/models/resnet101-5d3b4d8f.pth"to/home/john/.cache/torch/hub/checkpoints/resnet101-5d3b4d8f.pth100%|████████████████████████████████████████|170M/170M [00:27<00:00,6.57MB/s]
Downloading:"https://download.pytorch.org/models/fcn_resnet101_coco-7ecb50ca.pth"to/home/john/.cache/torch/hub/checkpoints/fcn_resnet101_coco-7ecb50ca.pth100%|████████████████████████████████████████|208M/208M [02:26<00:00,1.49MB/s]
Exporting ONNX model fcn-resnet101.onnx

再用trtexec将 ONNX 转成 TensorRT engine:

$ trtexec --onnx=fcn-resnet101.onnx --fp16 --workspace=64--minShapes=input:1x3x256x256 --optShapes=input:1x3x1026x1282 --maxShapes=input:1x3x1440x2560 --buildOnly --saveEngine=fcn-resnet101.engine
...
[01/07/2022-20:20:00] [I] Engine builtin406.011sec.
&&&& PASSED TensorRT.trtexec [TensorRT v8202] ...

随机输入,测试 engine:

$trtexec--shapes=input:1x3x1026x1282--loadEngine=fcn-resnet101.engine...[01/07/2022-20:20:00][I]===Performancesummary===[01/07/2022-20:20:00][I]Throughput:12.4749qps[01/07/2022-20:20:00][I]Latency:min=76.9746ms,max=98.8354ms,mean=79.5844ms,median=78.0542ms,percentile(99%)=98.8354ms[01/07/2022-20:20:00][I]End-to-End Host Latency:min=150.942ms,max=188.431ms,mean=155.834ms,median=152.444ms,percentile(99%)=188.431ms[01/07/2022-20:20:00][I]Enqueue Time:min=0.390625ms,max=1.61279ms,mean=1.41182ms,median=1.46136ms,percentile(99%)=1.61279ms[01/07/2022-20:20:00][I]H2D Latency:min=1.25977ms,max=1.53467ms,mean=1.27415ms,median=1.26514ms,percentile(99%)=1.53467ms[01/07/2022-20:20:00][I]GPU Compute Time:min=75.2869ms,max=97.1318ms,mean=77.8847ms,median=76.3599ms,percentile(99%)=97.1318ms[01/07/2022-20:20:00][I]D2H Latency:min=0.408447ms,max=0.454346ms,mean=0.425577ms,median=0.423004ms,percentile(99%)=0.454346ms[01/07/2022-20:20:00][I]Total Host Walltime:3.2866s[01/07/2022-20:20:00][I]Total GPU Compute Time:3.19327s[01/07/2022-20:20:00][I]Explanationsoftheperformancemetricsareprintedintheverboselogs.[01/07/2022-20:20:00][I]&&&&PASSEDTensorRT.trtexec[TensorRTv8202]...

运行教程,使用 engine:

$./bin/segmentation_tutorial[01/07/2022-20:20:34][I][TRT][MemUsageChange]Init CUDA:CPU+322,GPU+0,now:CPU463,GPU707(MiB)[01/07/2022-20:20:34][I][TRT]Loaded engine size:132MiB[01/07/2022-20:20:35][I][TRT][MemUsageChange]Init cuBLAS/cuBLASLt:CPU+520,GPU+224,now:CPU984,GPU1065(MiB)[01/07/2022-20:20:35][I][TRT][MemUsageChange]Init cuDNN:CPU+115,GPU+52,now:CPU1099,GPU1117(MiB)[01/07/2022-20:20:35][I][TRT][MemUsageChange]TensorRT-managed allocation in engine deserialization:CPU+0,GPU+131,now:CPU0,GPU131(MiB)[01/07/2022-20:20:35][I]RunningTensorRTinferenceforFCN-ResNet101[01/07/2022-20:20:35][I][TRT][MemUsageChange]Init cuBLAS/cuBLASLt:CPU+0,GPU+10,now:CPU966,GPU1109(MiB)[01/07/2022-20:20:35][I][TRT][MemUsageChange]Init cuDNN:CPU+0,GPU+8,now:CPU966,GPU1117(MiB)[01/07/2022-20:20:35][I][TRT][MemUsageChange]TensorRT-managed allocation in IExecutionContext creation:CPU+0,GPU+722,now:CPU0,GPU853(MiB)
TensorRT开始

实践

以上给到了官方样例与教程的编译使用。这里,另外找了个 RVM 的模型,从头开始试一试。

准备模型

Robust Video Matting (RVM)[10]稳定视频抠像,可在任意视频上做实时高清抠像。有Webcam Demo[11]可以网页上体验。

准备 ONNX 模型rvm_mobilenetv3_fp32.onnx[12],其推断文档[13]给出了模型输入输出:

  • 输入: [src,r1i,r2i,r3i,r4i,downsample_ratio]src:输入帧,RGB 通道,形状为[B, C, H, W],范围为0~1rXi:记忆输入,初始值是是形状为[1, 1, 1, 1]的零张量downsample_ratio下采样比,张量形状为[1]只有downsample_ratio必须是FP32,其他输入必须和加载的模型使用一样的dtype
  • 输出: [fgr,pha,r1o,r2o,r3o,r4o]fgr, pha:前景和透明度通道输出,范围为0~1rXo:记忆输出

准备输入图像input.jpg[14]。不用视频,保持代码简单些。

准备环境

  • Anaconda[15]
  • PyTorch[16]
condacreate -n torch python=3.9 -ycondaactivate torchcondainstall pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch -yRequirementshttps://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.htmlrequirementspipinstall onnx onnxruntime-gpu==1.10

运行 ONNX 模型

rvm_onnx_infer.py[17]:

importonnxruntimeasortimportnumpyasnpfromPILimportImage读取图像withImage.open(input.jpg)asimg:
    img.load()HWC [0,255] > BCHW [0,1]src = np.array(img)
src = np.moveaxis(src,-1,0) .astype(np.float32)
src = src[np.newaxis, :] /255.载入模型sess = ort.InferenceSession(rvm_mobilenetv3_fp32.onnx, providers=[CUDAExecutionProvider])创建 io bindingio = sess.io_binding()在 CUDA 上创建张量rec = [ ort.OrtValue.ortvalue_from_numpy(np.zeros([1,1,1,1], dtype=np.float32),cuda) ] *4downsample_ratio = ort.OrtValue.ortvalue_from_numpy(np.asarray([0.25], dtype=np.float32),cuda)设置输出项fornamein[fgr,pha,r1o,r2o,r3o,r4o]:
    io.bind_output(name,cuda)推断io.bind_cpu_input(src, src)
io.bind_ortvalue_input(r1i, rec[0])
io.bind_ortvalue_input(r2i, rec[1])
io.bind_ortvalue_input(r3i, rec[2])
io.bind_ortvalue_input(r4i, rec[3])
io.bind_ortvalue_input(downsample_ratio, downsample_ratio)

sess.run_with_iobinding(io)

fgr, pha, *rec = io.get_outputs()只将 `fgr` 和 `pha` 回传到 CPUfgr = fgr.numpy()
pha = pha.numpy()合成 RGBAcom = np.where(pha >0, fgr, pha)
com = np.concatenate([com, pha], axis=1)+ alphaBCHW [0,1] > HWC [0,255]com = np.squeeze(com, axis=0)
com = np.moveaxis(com,0,-1) *255img = Image.fromarray(com.astype(np.uint8))
img.show()

运行:

pythonrvm_onnx_infer.py--model"rvm_mobilenetv3_fp32.onnx"--input-image"input.jpg"--precisionfloat32--show

结果(背景透明):

TensorRT开始

ONNX 转成 TRT 模型

trtexec将 ONNX 转成 TensorRT engine:

exportPATH=/usr/local/TensorRT/bin:$PATHexportLD_LIBRARY_PATH=/usr/local/TensorRT/lib:$LD_LIBRARY_PATHtrtexec --onnx=rvm_mobilenetv3_fp32.onnx --workspace=64 --saveEngine=rvm_mobilenetv3_fp32.engine --verbose

发生问题:

[01/08/2022-20:20:36][E][TRT]ModelImporter.cpp:773:Whileparsingnodenumber3[Resize ->"389"]:[01/08/2022-20:20:36][E][TRT]ModelImporter.cpp:774:---Beginnode---[01/08/2022-20:20:36][E][TRT]ModelImporter.cpp:775:input: "src"input: "386"input: "388"output: "389"name: "Resize_3"op_type: "Resize"attribute{name:"coordinate_transformation_mode"s:"pytorch_half_pixel"type: STRING
}attribute{name:"cubic_coeff_a"f: -0.75type: FLOAT
}attribute{name:"mode"s:"linear"type: STRING
}attribute{name:"nearest_mode"s:"floor"type: STRING
}[01/08/2022-20:20:36][E][TRT]ModelImporter.cpp:776:---Endnode---[01/08/2022-20:20:36][E][TRT]ModelImporter.cpp:779:ERROR:builtin_op_importers.cpp:3608InfunctionimportResize:[8]Assertionfailed:scales.is_weights() && "Resizescalesmustbeaninitializer!"

这时,需要动手改动模型了。

首先,安装必要工具:

snapinstallnetron
pipinstallonnx-simplifier
pipinstallonnx_graphsurgeon--index-url https://pypi.ngc.nvidia.com

之后,Netron[18]查看模型Resize_3节点:

TensorRT开始

发现其scales输入是依据downsample_ratio得到的,即[1,1,downsample_ratio,downsample_ratio],可用ONNX GraphSurgeon[19]修改成常量。

最后,模型改动步骤如下:

ONNX 模型简化,并改为静态输入尺寸python-m onnxsim rvm_mobilenetv3_fp32.onnx rvm_mobilenetv3_fp32_sim.onnx \
--input-shape src:1,3,1080,1920 r1i:1,1,1,1 r2i:1,1,1,1 r3i:1,1,1,1 r4i:1,1,1,1ONNX GraphSurgeon 修改模型pythonrvm_onnx_modify.py -i rvm_mobilenetv3_fp32_sim.onnx --input-size 1920 1280trtexec 将 ONNX 转成 TensorRT enginetrtexec--onnx=rvm_mobilenetv3_fp32_sim_modified.onnx --workspace=64 --saveEngine=rvm_mobilenetv3_fp32_sim_modified.engine

rvm_onnx_modify.py[20]:

defmodify(input: str, output: str, downsample_ratio: float =0.25)->None:print(f\nonnx load:{input})
    graph = gs.import_onnx(onnx.load(input))

    _print_graph(graph)update node Resize_3: scalesresize_3 = [nforningraph.nodesifn.name ==Resize_3][0]
    print()
    print(resize_3)

    scales = gs.Constant(388,
        np.asarray([1,1, downsample_ratio, downsample_ratio], dtype=np.float32))

    resize_3.inputs = [iifi.name !=388elsescalesforiinresize_3.inputs]
    print()
    print(resize_3)remove input downsample_ratiograph.inputs = [iforiingraph.inputsifi.name !=downsample_ratio]remove node Concat_2concat_2 = [nforningraph.nodesifn.name ==Concat_2][0]
    concat_2.outputs.clear()remove unused nodes/tensorsgraph.cleanup()

    onnx.save(gs.export_onnx(graph), output)

ONNX 与 TRT 模型输出差异

可用Polygraphy[21]查看 ONNX 与 TRT 模型的输出差异。

首先,安装

安装 TensorRT Python APIcd /usr/local/TensorRT/python/
pipinstalltensorrt-8.2.2.1-cp39-none-linux_x86_64.whlexportLD_LIBRARY_PATH=/usr/local/TensorRT/lib:$LD_LIBRARY_PATH
python -c"import tensorrt; print(tensorrt.__version__)"安装 Polygraphy,或者通过 TensorRT/tools/Polygraphy 源码安装python -m pipinstallcolored polygraphy--extra-index-url https://pypi.ngc.nvidia.com

运行 ONNX 与 TRT 模型,对比输出误差:

运行ONNX模型,保存输入输出polygraphyrunrvm_mobilenetv3_fp32_sim_modified.onnx--onnxrt--val-range[0,1]--save-inputsonnx_inputs.json--save-outputsonnx_outputs.json运行TRT模型,载入ONNX输入输出,对比输出的相对误差与绝对误差polygraphyrunrvm_mobilenetv3_fp32_sim_modified.engine--model-typeengine--trt--load-inputsonnx_inputs.json--load-outputsonnx_outputs.json--rtol1e-3--atol1e-3

可见fp32精度误差在1e-3以内,PASSED

[I]     PASSED | All outputs matched | Outputs: [r4o,r3o,r2o,r1o,fgr,pha]
[I] PASSED | Command: /home/john/anaconda3/envs/torch/bin/polygraphy run rvm_mobilenetv3_fp32_sim_modified.engine --model-type engine --trt --load-inputs onnx_inputs.json --load-outputs onnx_outputs.json --rtol1e-3--atol1e-3

也试了fp16,其精度损失就比较大,FAILED

[E]     FAILED | Mismatched outputs: [r4o,r3o,r2o,r1o,fgr,pha]
[!] FAILED | Command: /home/john/anaconda3/envs/torch/bin/polygraphy run rvm_mobilenetv3_fp16_sim_modified.engine --model-type engine --trt --load-inputs onnx_inputs.json --load-outputs onnx_outputs.json --rtol1e-3--atol1e-3

运行 TRT 模型

这里以 TensorRT C++ runtime APIs 为例,将转出的 RVM TRT 模型运行起来。完整代码见rvm_infer.cc[22]

1. 载入模型:创建runtime,反序列化 TRT 模型文件的数据

staticLogger logger{Logger::Severity::kINFO};autoruntime =std::unique_ptr(nvinfer1::createInferRuntime(logger));autoengine = runtime->deserializeCudaEngine(engine_data.data(), fsize,nullptr);

遍历全部输入输出bindings

autonb = engine->getNbBindings();for(int32_ti =0; i < nb; i++) {autois_input = engine->bindingIsInput(i);autoname = engine->getBindingName(i);autodims = engine->getBindingDimensions(i);autodatatype = engine->getBindingDataType(i);// ...}
EngineName=Unnamed Network 0DeviceMemorySize=148 MiBMaxBatchSize=1BindingsInput[0]name=src dims=[1,3,1080,1920] datatype=FLOATInput[1]name=r1i dims=[1,1,1,1] datatype=FLOATInput[2]name=r2i dims=[1,1,1,1] datatype=FLOATInput[3]name=r3i dims=[1,1,1,1] datatype=FLOATInput[4]name=r4i dims=[1,1,1,1] datatype=FLOATOutput[5]name=r4o dims=[1,64,18,32] datatype=FLOATOutput[6]name=r3o dims=[1,40,36,64] datatype=FLOATOutput[7]name=r2o dims=[1,20,72,128] datatype=FLOATOutput[8]name=r1o dims=[1,16,144,256] datatype=FLOATOutput[9]name=fgr dims=[1,3,1080,1920] datatype=FLOATOutput[10]name=pha dims=[1,1,1080,1920] datatype=FLOAT

之后,分配好所有bindingsdevice内存:

autonb = engine->getNbBindings();std::vector<void*> bindings(nb,nullptr);std::vector<int32_t> bindings_size(nb,0);for(int32_ti =0; i < nb; i++) {autodims = engine->getBindingDimensions(i);autosize = GetMemorySize(dims,sizeof(float));if(cudaMalloc(&bindings[i], size) != cudaSuccess) {std::cerr<<"ERROR: cuda memory allocation failed, size = "<< size
        <<" bytes"<<std::endl;returnfalse;
  }
  bindings_size[i] = size;
}

到此,准备工作就好了。

2. 前处理:输入数据处理成输入格式,存进输入bindings

用 OpenCV 读取图像,缩放成src的输入尺寸。再把数据从BGR [0,255]处理成RGB [0,1]。因batch=1,所以处理时可忽略。

// img: HWC BGR [0,255] u8autoimg = cv::imread(input_filename, cv::IMREAD_COLOR);if(src_h != img.rows || src_w != img.cols) {
  cv::resize(img, img, cv::Size(src_w, src_h));
}// src: BCHW RGB [0,1] fp32autosrc = cv::Mat(img.rows, img.cols, CV_32FC3);
{autosrc_data = (float*)(src.data);for(inty =0; y < src_h; ++y) {for(intx =0; x < src_w; ++x) {auto&&bgr = img.at(y, x);/*r*/*(src_data + y*src_w + x) = bgr[2] /255.;/*g*/*(src_data + src_n + y*src_w + x) = bgr[1] /255.;/*b*/*(src_data + src_n*2+ y*src_w + x) = bgr[0] /255.;
    }
  }
}if(cudaMemcpyAsync(bindings[0], src.data, bindings_size[0],
    cudaMemcpyHostToDevice, stream) != cudaSuccess) {std::cerr<<"ERROR: CUDA memory copy of src failed, size = "<< bindings_size[0] <<" bytes"<<std::endl;returnfalse;
}

3. 推理:将bindings给到engine执行上下文进行推理

autocontext =std::unique_ptr(
    engine->createExecutionContext());if(!context) {returnfalse;
}boolstatus = context->enqueueV2(bindings.data(), stream,nullptr);if(!status) {std::cout<<"ERROR: TensorRT inference failed"<<std::endl;returnfalse;
}

4. 后处理:从输出bindings取出数据,根据输出格式处理数据

cv::Mat接收输出的前景fgr和透明通道pha

autofgr = cv::Mat(src_h, src_w, CV_32FC3);// BCHW RGB [0,1] fp32if(cudaMemcpyAsync(fgr.data, bindings[9], bindings_size[9],
    cudaMemcpyDeviceToHost, stream) != cudaSuccess) {std::cerr<<"ERROR: CUDA memory copy of output failed, size = "<< bindings_size[9] <<" bytes"<<std::endl;returnfalse;
}autopha = cv::Mat(src_h, src_w, CV_32FC1);// BCHW A [0,1] fp32if(cudaMemcpyAsync(pha.data, bindings[10], bindings_size[10],
    cudaMemcpyDeviceToHost, stream) != cudaSuccess) {std::cerr<<"ERROR: CUDA memory copy of output failed, size = "<< bindings_size[10] <<" bytes"<<std::endl;returnfalse;
}
cudaStreamSynchronize(stream);

再将fgrpha合成RGBA数据,并复原成原尺寸:

// Compose `fgr` and `pha`autocom = cv::Mat(src_h, src_w, CV_8UC4);// HWC BGRA [0,255] u8{autofgr_data = (float*)(fgr.data);autopha_data = (float*)(pha.data);for(inty =0; y < com.rows; ++y) {for(intx =0; x < com.cols; ++x) {auto&&elem = com.at(y, x);autoalpha = *(pha_data + y*src_w + x);if(alpha >0) {/*r*/elem[2] = *(fgr_data + y*src_w + x) *255;/*g*/elem[1] = *(fgr_data + src_n + y*src_w + x) *255;/*b*/elem[0] = *(fgr_data + src_n*2+ y*src_w + x) *255;
      }else{/*r*/elem[2] =0;/*g*/elem[1] =0;/*b*/elem[0] =0;
      }/*a*/elem[3] = alpha *255;
    }
  }
}if(dst_h != com.rows || dst_w != com.cols) {
  cv::resize(com, com, cv::Size(dst_w, dst_h));
}

5. 运行得到的抠像结果(背景透明):

TensorRT开始

最后

想入门 TensorRT 的,动手实践一下吧!

脚注

[1] Getting Started:https://developer.nvidia.cn/tensorrt-getting-started

[2] TensorRT 下载页:https://developer.nvidia.cn/nvidia-tensorrt-download

[3] CUDA:https://developer.nvidia.cn/cuda-toolkit

[4] cuDNN:https://developer.nvidia.cn/cudnn

[5] NVIDIA Docker:https://github.com/NVIDIA/nvidia-docker

[6] nvidia/cuda:https://hub.docker.com/r/nvidia/cuda

[7] Sample Support Guide:https://docs.nvidia.com/deeplearning/tensorrt/sample-support-guide/index.html

[8] Quick Start Guide / Using The TensorRT Runtime API:https://docs.nvidia.com/deeplearning/tensorrt/quick-start-guide/index.htmlruntime

[9] FCN-ResNet-101:https://pytorch.org/hub/pytorch_vision_fcn_resnet101/

[10] Robust Video Matting (RVM):https://github.com/PeterL1n/RobustVideoMatting

[11] Webcam Demo:https://peterl1n.github.io/RobustVideoMatting//demo

[12] rvm_mobilenetv3_fp32.onnx:https://github.com/PeterL1n/RobustVideoMatting/releases/download/v1.0.0/rvm_mobilenetv3_fp32.onnx

[13] 推断文档:https://github.com/PeterL1n/RobustVideoMatting/blob/master/documentation/inference_zh_Hans.md

[14] input.jpg:https://github.com/ikuokuo/start-deep-learning/blob/master/practice/RVM/input.jpg

[15] Anaconda:https://www.anaconda.com/products/individual

[16] PyTorch:https://pytorch.org/get-started/locally/

[17] rvm_onnx_infer.py:https://github.com/ikuokuo/start-deep-learning/blob/master/practice/RVM/rvm_onnx_infer.py

[18] Netron:https://github.com/lutzroeder/netron

[19] ONNX GraphSurgeon:https://github.com/NVIDIA/TensorRT/tree/main/tools/onnx-graphsurgeon

[20] rvm_onnx_modify.py:https://github.com/ikuokuo/start-cuda/blob/master/samples/tensorrt/rvm_onnx_modify.py

[21] Polygraphy:https://github.com/NVIDIA/TensorRT/tree/master/tools/Polygraphy

[22] rvm_infer.cc:https://github.com/ikuokuo/start-cuda/blob/master/samples/tensorrt/rvm_infer.cc

主题测试文章,只做测试使用。发布者:觉鸟网,转转请注明出处:https://www.jueniao.cn/n/21255.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年6月13日 10:31
下一篇 2022年6月13日 10:33

相关推荐

  • 老车主眼馋!新款特斯拉ModelS亮相中国台湾:中控屏可左右倾斜

    5月4日消息,近期特斯拉新款Model S/X正式亮相中国台湾市场,亮相的车型为2022款小改款车型,相比2021款全新Model S/X,新车在车灯以及内饰方面进行了细微调整。 2022款Model S此前已经在美国市场发布,相比2021年夏天交付的首批Model S Plaid版有了部分升级。新车使用了全新的矩阵式前大灯和LED尾灯,灯腔内部进行了升级,…

    2022年6月21日
    5400
  • 市面上一万多的二手新能源汽车便宜的二手绿牌纯电动轿车有哪些

    大家好,我是老杳,一个理想主义者,喜欢寻找诗和远方,有一辆属于自己的座驾非常必要。 以前开过燃油车,是台标致206,开得再省也要五毛钱一公里,一百块油不敢怎么跑就见底了,并且动不动限号限行,大部分时间趴在窝里,使用价值太低,所以换车决定选择新能源纯电动车,新车又太贵,动辄五万十万,没有开过新能源车,心里也没底,只能先买台二手新能源车跑跑试试,在某鱼上搜索,二…

    2022年6月27日
    2300
  • 区分speak,talk,say,tell

    Hello,everyone!今天我们分享的是 speak/talk/say/tell的区别。 四朵金花,今日绽放,每朵花都不一样,看看怎么不同吧,学英语的朋友,都离不开这几个词语都区分。 ▲say是讲,说的意思,强调说话内容。一般作及物动词,常用于直接引述所说的话或间接叙述所说的话。例如: Say it in Chinese please. 请用汉语说。(…

    2022年6月18日
    2700
  • 备战6·18,realme推出中文品牌标识“真我”和多款新品

    新京报贝壳财经讯(记者许诺)五月将尽,6·18电商大促日渐升温。5月26日下午,OPPO旗下手机品牌realme线上举办了真我618盛典。realme副总裁、中国区总裁徐起在活动上宣布启用全新中文品牌logo——真我realme。 作为OPPO旗下原本针对印度等境外市场推出的子品牌,realme从2019年开始进军国内市场,近期推出的一些新机型号也均以真我为…

    智能科技 2022年6月25日
    3900
  • 1分钟从涨停到闪崩!“世界铜王”旗下大牛股巨震,新能源两大千亿级龙头双双涨停

    7月21日上午,锂矿板块再度迎来爆发。行业龙头赣锋锂业涨停,股价创历史新高,总市值为2529亿元。 截至上午收盘,沪指涨0.6%,报3558.11点;深成指涨1.13%,报15180.93点;创业板指涨1.98%,报3532.5点。两市半日合计成交额7405.1亿元。 上午A股主要股指走势图 来源:Wind 锂矿板块大涨 21日,Wind锂矿指数上涨 ,板块…

    2022年6月15日
    3000

发表回复

您的电子邮箱地址不会被公开。

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信