当前位置:   article > 正文

yolov5+tensorrt加速,部署在边缘计算设备(AGX、TX2、NX等)上,成功实现

yolov5+tensorrt加速,部署在边缘计算设备(AGX、TX2、NX等)上,成功实现

今天是20240329,我见有人问我,我看了下现在的YOLOv5_6.1——7.0的版本是支持未改网络结构的.pt在export.py直接转.engine的,6.1以前的版本不可以直接转,至于master大家可以去试试

————————————————————————————————————————————————————————————————————————————————————————————————

说在前面,之前做项目遇到了需要对yolov5进行tensorrt加速,然后部署在边缘设备上,写本篇主要是为了记住加速的步骤,见别的很多大佬先转换的.wts,现在已经不用那么复杂了,有更简洁的方法,如果能对大家有帮助,我也很开心。

一、首先yolov5的环境配置就不说了,网上资料已经很多了。

二、再者,CUDA和CUDNN安装以及完整训练步骤,也不说了网上资料依然已经很多了。

三、主要记录下tensorrt,tensorrt的安装,在csdn上也能搜到很多,截止到我写这篇文章的时候,大家普遍用的tensorrt8.x的版本,TensorRT 同时支持 C++ 和 Python。因为yolov5是python写的,所以我也主要用python的。

   转换网络权重文件主要分为未修改网络的权重文件,和自行修改网络后的权重文件。

    其中未修改网络的权重文件可以直接把yolov5源码训练得到的.pt转换为tensorrt支持的.engine文件,这个.engine在yolov5的detect.py里可以直接调用,当然也可以自己写推理代码

    自行修改网络后的权重文件是先将yolov5源码训练得到的.pt文件转换成.onnx,再把.onnx转化为优化后的.onnx,最后再把优化后的.onnx转换为tensorrt支持的.engine,这个.engine在yolov5的detect.py里可以直接调用,当然也可以自己写推理代码。

    首先.pt文件可以通过yolov5自带的export.py这个程序去直接转化,如果是未修改网络的权重文件,可以在export.py程序里,最下面的parse_opt函数里修改参数如下:

然后右击运行,如果环境配好的话,等几分钟就可以转换好了,我的这个yolov5版本是随时更新的yolov5_master版本,不同的版本可能不太一样,不过大同小异。(有些比较老的版本不能直接转.engine,如果不能转,就看我下面的自行修改网络后的权重文件转.engine,步骤是一样的。)转换.engine后,可以在yolov5的detect.py里可以直接调用,当然也可以自己写推理代码。

     如果训练后得到自行修改网络后的权重文件,首先在yolov5自带的export.py里,修改

然后右击运行,如果环境配好的话,等几秒钟就可以转换好了,转换好后会得到一个.onnx的文件,这个.onnx是未优化后的,得在一键转换 Caffe, ONNX, TensorFlow 到 NCNN, MNN, Tengine这里进行优化(感谢这位大佬)。主要是onnx转onnx,得到优化后的.onnx后,通过下面的代码去转换成.engine。
 

  1. import tensorrt as trt
  2. import os
  3. EXPLICIT_BATCH = 1 << (int)(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
  4. TRT_LOGGER = trt.Logger()
  5. def get_engine(onnx_file_path, engine_file_path=""):
  6. """Attempts to load a serialized engine if available, otherwise builds a new TensorRT engine and saves it."""
  7. def build_engine():
  8. """Takes an ONNX file and creates a TensorRT engine to run inference with"""
  9. with trt.Builder(TRT_LOGGER) as builder, builder.create_network(
  10. EXPLICIT_BATCH
  11. ) as network, builder.create_builder_config() as config, trt.OnnxParser(
  12. network, TRT_LOGGER
  13. ) as parser, trt.Runtime(
  14. TRT_LOGGER
  15. ) as runtime:
  16. config.max_workspace_size = 1 << 32 # 4GB
  17. builder.max_batch_size = 1
  18. # Parse model file
  19. if not os.path.exists(onnx_file_path):
  20. print(
  21. "ONNX file {} not found, please run yolov3_to_onnx.py first to generate it.".format(onnx_file_path)
  22. )
  23. exit(0)
  24. print("Loading ONNX file from path {}...".format(onnx_file_path))
  25. with open(onnx_file_path, "rb") as model:
  26. print("Beginning ONNX file parsing")
  27. if not parser.parse(model.read()):
  28. print("ERROR: Failed to parse the ONNX file.")
  29. for error in range(parser.num_errors):
  30. print(parser.get_error(error))
  31. return None
  32. # # The actual yolov3.onnx is generated with batch size 64. Reshape input to batch size 1
  33. # network.get_input(0).shape = [1, 3, 608, 608]
  34. print("Completed parsing of ONNX file")
  35. print("Building an engine from file {}; this may take a while...".format(onnx_file_path))
  36. plan = builder.build_serialized_network(network, config)
  37. engine = runtime.deserialize_cuda_engine(plan)
  38. print("Completed creating Engine")
  39. with open(engine_file_path, "wb") as f:
  40. f.write(plan)
  41. return engine
  42. if os.path.exists(engine_file_path):
  43. # If a serialized engine exists, use it instead of building an engine.
  44. print("Reading engine from file {}".format(engine_file_path))
  45. with open(engine_file_path, "rb") as f, trt.Runtime(TRT_LOGGER) as runtime:
  46. return runtime.deserialize_cuda_engine(f.read())
  47. else:
  48. return build_engine()
  49. def main():
  50. """Create a TensorRT engine for ONNX-based YOLOv3-608 and run inference."""
  51. # Try to load a previously generated YOLOv3-608 network graph in ONNX format:
  52. onnx_file_path = "best0605-sim.onnx"
  53. engine_file_path = "best0605-sim.engine"
  54. get_engine(onnx_file_path, engine_file_path)
  55. if __name__ == "__main__":
  56. main()

 主要是把倒数几行的.onnx和.engine输入输出路径和名字改一下就好,环境都配置好的话,运行代码需要两三分钟,之后就可以得到.engine,转换.engine后,可以在yolov5的detect.py里可以直接调用,当然也可以自己写推理代码。
下图左侧是tensorrt加速后的显存占用率,右侧是未加速的显存占用率,可见tensorrt加速后,占用资源明显低于未加速的,GPU占用内存从3.8G降到了1.6G,这对一些计算能力不足边缘设备去运行yolov5提供了很大的方便,同时节省的算力也可以用来运行其他的功能等。

如果遇到报错,要不是环境配置问题,要不就是版本问题,另外如果提示opest什么的错误,可以尝试修改一下这个数字:多试几次。

最后还有很重要的提醒一下,onnx文件可以跨设备使用,但是在转换.engine时,最好还是在那个设备上用,就用那个设备去转,要不然如果在一台设备上转的.engine,却在另一台设备上用的话,可能会因为版本问题而报错。

还有就是在转engine时,设备会很吃电,供电电压也不能太小,我之前在AGX上转,有一次没用220v供电,而是用的电池供电,导致还没转完,就断电关机了。
以上就是我对yolov5进行tensorrt加速的过程,我主要是在windows11系统和AGX的Ubuntu18.04和TX2的Ubuntu18.04上进行的,都成功了,并且资源利用也大大减小了。有什么问题欢迎在评论区问我。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/468640
推荐阅读
相关标签
  

闽ICP备14008679号