基于YOLOv5s的火焰检测在jetson nano边缘计算设备上的部署(使用tensorrt加速,Deepstream视频推流SDK)
前情提要:本文章是我自己一点点的小感悟,是整个大框架的分析与大的流程,不是你们想要的具体过程,但是如果你们仔细阅读下这篇文章,有一个大局的观念,会对项目流程有一个清晰的认识与想法,效果可能比那些细的流程的文章要好些,也因人而异吧,所以提前告知下大家。
咱们来说下这次课设让做的一个基于人体关键点检测的姿势识别或者跌倒检测的一个项目,我打算基于openpose这个算法做,需要用什么VGA网络训练啥的,我这次没研究怎么训练,时间不够了好吧,这次任务就是如何在jetson nano板子上部署是这次的重点,同样说过了jetson xavier最重要的是什么,是jetpack版本,最基本的生态就是Ubuntu18.04这个默认不多说了,为什么之前tx2那么难用,系统储存在emmc里,要虚拟机烧系统nvidia sdk传输,电脑空间不够用了,还要专用USB线,懒得弄了,而且内存还不足,还得挂载sd卡,解锁,写入开机自启动vim命令,空间不足开不了机,命令行都调不出来,你也亲身经过的,花了150,记得奥别忘了。deepstream版本和jetpack版本根本匹配不了,网上生态还没有,没法搞。好了,言归正传,咱们说这回,问王老师借了个nano和USB摄像头,买了两个sd卡,一个tensorflow,一个pytorch。这回吃一堑长一智,先说tensorflow框架,openpose得用tensorflow框架去搞,你说你在板子上肯定用gpu跑吧,谁部署板子用cpu对吧,查了下,对于nano只有一个jetpack版本4.3适用,为什么听我细细道来,首先查询tensorflow适配的cuda版本,一看没有cuda10.2,寄了一大半哈哈哈,最后一看只有cuda10版本,整10版本,那好了,只有一个适合nano的jetpack版本,卡的死死的,(备注:首先我肯定是在windows上部署的,这个毋庸置疑,才能知道版本问题信息),好了,准备sd卡,清空,烧录分区 flash successful,wohooo!!!成功,这个很简单不多说了,进去一系列先设置英文语言,装jtop。sudo upgrade,pip安装,更新一系列东西,装一堆编译的库之类的,这里可以参考下这位博主的博客:Jetson nano部署Yolov5 ——从烧录到运行 1:1复刻全过程_nano yolo_IamYZD的博客-CSDN博客
参考这个做初始部署操作,写的很好,谢谢这位大佬,可以引用下么,如果有侵权请及时联系我,我立刻删除。好了,装好了后,我查了下,tensorflow-gpu还不好装,甚至可能要编译,一提到编译cmake就头大,我很希望找到whl轮文件直接装,这样就会很简单了,wuhooo,你猜怎么着,我找到了,这里参考我的干爹英伟达官网:
Index of /compute/redist/jp/v43/tensorflow-gpu
4.3jetpack版本的tensorflow-gpu轮文件,给大家啦,这样就简单多了我刚好像看了下,通过命令也能直接装,我当时好像没装成功,算了你们自己再看看,反正whl是最简单的方法了,途中有个h5py还是啥的库老版本不匹配,建议先装这个库,再tensorflow-gpu whl文件,这样就装好了,反正也不容易,装好了,就可以拷贝程序直接运行了,记得使用python3命令,pip也用pip3命令,phthon默认指的2版本,再装些库,运行出来帧率低到爆炸,即使是gpu跑的,我觉得大部分原因是poenpose这个算法的原因(因为我只用pytorch框架跑一个项目的时候帧率都没有这样,还没有tensorrt加速加上deepstream),卡成ppt,如下图:


其实还有个程序,检测跌倒的,不过他的tensorflow用的1,你想想,我要用gpu跑,jetpack只能4.3版本,好了满足tensorflow使用gpu了,现在需要torch也用gpu,查官网傻眼了,如下图:

你猜猜看发生什么了, torch最高1.4,能用么,不可能啦,它检测跌倒的用的yolov5,yolov5我印象中最低torch1.6还是多少,反正一定不能1.4,因为与现在的版本差别太大,很多class或者函数都找不到,靠你手往上解决,根本没法的,我在之前tx2试过,你又要1.4的torch使用gpu,又要跑yolov5,不可能的奥,所以这个程序没法在nano上部署,索性放弃了。
下面补充下我在windows如何部署tensorflow-gpu吧,牵扯到tensorflow框架部署都不简单,因为1版本和2版本区别太大了,contrib这个库,还有各种报错,头大,一个静态的模型。一个动态的模型,cpu好部署,gpu还需要点水平,我现在说如何跑gpu:首先你得找匹配tensorflow-gpu的cuda版本,如下链接你先看下,自己心里先有个数
2021最新:TensorFlow各个GPU版本CUDA和cuDNN对应版本整理(最简洁)_cuda12.1对应的cudnn_Kakaluotuo的博客-CSDN博客
看完了吧,你会发现没有对于tensorflow-gpu版本1的没有cuda10.2,哈哈,真好,我*/*/*/&……¥……*,索性换了cuda10版本,装了cudnn,cudnn版本其实那个不是一定匹配的,你运行时会发现它自己读取cudnn某个版本的dll文件没有,你就装哪个cudnn的驱动就行了,好了,装好了,我猜你还是用cpu跑,因为显示加载AX2 blabla。。。,读取不到对应cuda的dll文件,为啥读不到呢,奇了怪,pytorch都是自己自动使用gpu,你tensorflow事情怎么这么多,经过查找,奥,原来你在这个文件夹读取,如下图所示:
看到了吧,这个路径,他在这里读取,你之前不是替换了cuda的bin文件么,现在把所有的bin文件夹下的文件全部copy过来,你肯定会担心这是系统文件,不会搞搞坏了吧,别担心,我一直用着都没事,即使你害怕,后面你想换cuda版本了,想删除了,怎么办,乱了,没事的,你再拷贝一次,替换掉,他会自动选中那些相同文件,你再删除就可以了,聪明不我,哈哈哈哈。好了,现在基本上没啥问题了,这个是我参考这篇博客的,你们可以看下:
解决:运行 tensorflow-gpu相关代码报错/缺少dll文件(无需修改tensorflow版本)_gpudetect.dll下载_Netceor的博客-CSDN博客 不用下载奥,本来就有的,复制粘贴就行。还有个我想起来的报错,我装了tensorflow-gpu,他报错找不到tensorflow,tensorflow和tensorflow-gpu关系可以看下这个奥,讲的也非常不错:
电脑上同时安装了tensorflow和tensorflow-gpu,如何默认使用tensorflow-gpu_tensorflow 和tensorflowgpu_NuerNuer的博客-CSDN博客
哈哈哈,华生看看这篇,有助你更有效率的解决BUG,基本上没啥了,剩下的都是小问题,祝你成功 ,好了windows插完我们言归正传。
tensorflow说完了。我们现在来说正题部署nano,nano确定好版本,我选的jetpack4.5.1,因为我要用deepstream,看好再下手奥,这个确实很重要,这个版本的资料生态在我做之前感觉是最全的,所以你可以跟着我选。

为什么说是感觉,后面说奥,简单先提一下,因为现在很多博主是之前做的,用到的deepstream-yolov5,或者tensorrtx版本都更新了,还有yolov5版本,有的找不到之前版本了,什么engine模型不匹配,onnx的int32和int64运行不了,各种编译错误,实际上都没有沟通好,毕竟不是官方的,都在做得更好,肯定会出现不兼容问题,所以我们做到这个深度需要有什么能力,需要有看英文文档的能力,和github上看英文issues的能力,纯英文食用是第一手资料,就这都有错误,更别说中文搞过来的了,版本就更新不及时了,这个我们后面说。又是烧录,装一堆编译库,跟刚刚tensorflow开头一样,不多阐述了,奥插一句,有时候会遇到核心转储illegal错误,这个有些大佬说和numpy版本有关,当时是装miniconda,archiconda创建新环境pip的错误,base环境好着呢,但是现在是python3运行程序报的这样的错误,我也没搞懂,参考这位大神的,恩能够解决就行:
解决英伟达Jetson平台使用Python时的出现“Illegal instruction(cpre dumped)”错误_python illegal dump_小宋是呢的博客-CSDN博客
好了,初步cmake,所需要的编译等库装好了(根据的就是第一条链接),下面装torch框架,首先你用pip装可以,没问题,还可以运行起来yolov5,但是运行后有个问题,即使你装的torch-gpu版本,他怎么不用gpu跑啊,玩板子玩板子玩的是什么,玩的当然是gpu,你说你用cpu跑,这真的是你还是去耍树莓派吧,此处流汗黄豆,所以我们需要下torch英伟达官网给的适配whl文件,只有这里的torch是链接好nano的gpu,cuda的(此处有请我们的nvidia二爸):
PyTorch for Jetson - Jetson Nano - NVIDIA Developer Forums

你们自己看吧,我装的是如上图的版本,这时有人问了,yolov5不是只能跑至少python3.8么,其实不会的,nvidia帮我们解决了这个问题,3.6是可以跑YOLOv5的,反正我的yolov5-7.0没有报错,其实我还训练了yolov5-5.0,他在运行这个报错了,需要高版本python,所以你如果单纯用torch跑yolov5(不用tensorrt加速和deepstream),你就用yolov5-7.0最新的训练,视频出来帧率还行,真的,但是因为没有完全调用gpu所以肯定没有tensorrt的加速快,这是肯定的,如果你用tensorrt加速和deepstream,用yolov5-5.0训练吧,因为可能模型文件不一样,后面转onnx或者engine可能会出问题,没有考证猜的,因为其他能找到的博主都是用yolov5-5.0搞得,虽然官方github项目说支持所有yolov5版本,但是以防万一,你自己看吧好吧。好了,pytorch跑yolov5成功了,如下图所示:

程序里的arguments改视频实时(摄像头代码-1,0,1都有可能,就这三个数字都试下吧),图片视频路径很简单,很方便,唯一什么问题呢,GPU没有开发完全,所以我们不满足于当下,需要加速,人嘛,都是这样的,人之本性便是贪婪永无止境,不过学习上的贪婪叫卷,卷卷更健康,是好事好吧,我们在学习技能知识,继续开干。好,隔了一天,我们继续,我们先来说使用tensorrt加速,tensorrt是英伟达调用开发板的驱动,和tensorrtx区别下哈,对于本次项目yolov5,tensorrtx是个转engine模型的项目程序,是王新宇老师开发的,在这里我们感谢老师对我们的帮助,还有幸跟他成为微信好友,朋友圈真的很厉害,永远向他学习,我们言归正传,先下载这个代码,链接在这里:
GitHub - wang-xinyu/tensorrtx at yolov5-v6.0
一定特别注意奥,这个转engine格式的项目是分yolov5版本的,因为我用v5.0版本训练的,而且v5.0版本的yolov5网上生态资料比较全,所以我点击tags选择v5.0版本下载,然后修改class-num,编译一些操作,这时可以参考下这位博主的博客:
yolov5s模型转tensorrt+deepstream检测+CSI和USB摄像头检测_yolov5s.engine_hhhhhhky的博客-CSDN博客
这是我最喜欢的博主,是我的启蒙老师,所以我当时是以他为主,在这里好好感谢这位大佬,
转成engine格式模型文件后,tensorrtx自带的cpp和python文件只能识别文件夹的图片,输入图片文件夹,吐出来整个图片文件夹,视频什么的没法实现,现在有两种方法:1.使用大佬写的程序cpp或者python程序视频检测,我还没找到导入视频检测的代码,只有视频实时检测的cpp和python代码,我都试了一下,我所有找到的python程序卡住了对于我,没法用,卡的只能重启板子,cpp的程序可以用,还是刚那位我最爱的博主,代码直接替换原来的yolov5.cpp,执行命令:
sudo ./yolov5 -v yolov5s.engine
wohuuu成功,当然摄像头参数-1,0,1都有可能,试一下就可以了,看下,帧率13,如下图所示,

真的实时检测很快,摸了板子烫的爆炸,真的是开发到极致了,同样是jtop的gpu显示满格100,这里才是真正的调用完全,甚至比我之后说的deepstream帧率要高, 其中实时视频检测达到13fps已经很满意了,好了,tensorrt视频实时检测搞完了,但是没法视频导入检测,现在只剩最后一种方法 2.使用deepstream部署多路视频流,这样用nvidia的官方sdk不论是视频实时检测,还是实时检测,更重要的多路视频管道并行处理都是最佳的选择!好了我们接下来说使用最难的部署deepstream。
如何使用deepstream部署,这里首先强调下,版本一定要选对奥,还是我开头说的,jetpack和deepstream的版本是对应的,所以上回我在tx2部署的时候出了点小问题,就是因为版本问题。前景提要,英伟达官方的deepstream工具包目前没有yolov5的代码,他只有faster rcnn等等和最高yolov3的开发包,所以我们需要下载deepstream-yolov5,这两者的关系是deepstream-yolov5作用是编译文件和前端的txt参数部署,实际调用的内核还是opt-nvidia-deepstream5.1文件夹里的,网上现有的有两个大佬写的,一个是:
DanaHan的这个记为1:
https://github.com/DanaHan/Yolov5-in-Deepstream-5.0
还有一个是marcoslucianops的这个记为2:
https://github.com/marcoslucianops/DeepStream-Yolo
这两个大佬都写的非常厉害,只是我在阐述我自己在板子上因为各种原因和自己对于yolov5试验的结果,我用了yolov5-5.0和yolo-7.0都试过了,结果大差不差其中7版本在2编译好像错误等等我忘了,试了太多回了,已经完全记岔了,所以这里你们可以自己试试或者就跟着我走,不要嫌麻烦,我就用的5.0版本的pt文件成功了,所以这里我们用v5.0举例。
总体来说,有三种大的方向,一:使用wangxinyu的tensorrtx先转出wts中转文件再转出engine模型直接用在deepstream
二:使用2的export_yolov5转出onnx模型在2的deepstream内部转成engine模型用,这样才适配,onnx才是最通用的
三:使用2的老版本有个gen_wts_yolov5.py转成wts和cfg格式的文件在deepstream中共同转成engine模型,但是因为看issues这种方法兼容报错太多了,被博主舍弃了,更新掉了,博主现在的推崇方法是方法二,可以看下他的yolov5官方文档。
我们先说方法一,因为各个项目的版本都在持续更新,wangxinyu老师的yolov5-5.0和yolov5-7.0 pt文件转成的engine模型都无法直接在2_deepstream项目里直接调用成功(期间肯定需要编译,CUDA-10.2 make生成so文件),比较好一点的是2_deepstream编译不会发生错误,正常的生成so文件,但是最终改各种txt参数后,进行运行会报奇怪的错误,网上也没有比较好的解决方法,可能的问题在于目前的tensorrtx版本生成的engine模型文件不兼容2_deepstream项目。下面我们说下1_deepstream项目,在导入wangxinyu的engine模型进行编译时,修改了makefile里cuda10.2,但是还是编译报错,生不成so文件,说是yolo.cpp还是yolo.o有问题,所以就在这里戛然而止了。
我们再来看方法二,是2_deepstream项目的官方说明,因为原来的版本使用wts和cfg(网络架构文件)格式的文件生成engine文件总是出现版本兼容问题,issues问题很多,所以老师将这种方法用更通用的onnx模型转engine方法替代了,这里附上yolov5官方说明链接:
https://github.com/marcoslucianops/DeepStream-Yolo/blob/master/docs/YOLOv5.md
这里按他的步骤走就可以了,一切正常,一直到在txt中加入onnx模型,等他自己生成engine文件,但是提示onnx int64位,不能转出来,而tensorrt只能支持int32位,所以我们需要降模型维度,我第一次使用一个项目进行降维:
GitHub - aadhithya/onnx-typecast: Script to typecast ONNX model parameters from INT64 to INT32.
成功降维,但是继续deepstream内部转engine时,这个int64不报错了,其他某个报错int64也需要降维,没看懂,所以这个路也走不通,还有一种是利用onnxsim这个库进行降维,但是因为各种版本不对应,这个库一直要么没装上,要么装上了降维也报错,所以也没法。这个最有希望的方法二也没有走通。
我们最后来看一下方法三,实际上这个同时转出wts和cfg的gen_wts_yolov5.py代码已经绝迹了,我废了好大得劲才找到一个,但是因为这个代码可能也是有迭代更新版本的还有适用于yolov5的版本,最终按照教程也没有成功。项目地址放在底下了,大家可以参考下,当时找到因为太激动了,还在issues站了一楼:
GitHub - tangjunjun966/DeepStream-Yolo-master: deepstream使用yolov5的详细教程与代码文件
转了engine放在2_deepstream项目也是报错,具体报啥错我也忘了,总之就是调不好。
难道真的得不到结果了么??不,下面是振奋人心的时刻,我在这两个deepstream-yolov5项目里选来选去,试来试去,辗转反侧。最终还是大奶涵老师这个1_deepstream项目成功了!
当时1_deepstream项目有一个很大的问题,编译出错,他代码本身的问题,所以用这个代码试验的比较少,但是有一次在美广吃饭的时候我在刷csdn,偶然间发现解决的办法,链接放在下面:
NVIDIA Jetson NX基于Deepstream5.0部署TensorRT+YOLOv5-v5.0实现目标检测识别详细学习笔记_Yan_uuu的博客-CSDN博客

这是本次deepstream部署最关键的一步,我按照他的方法后,成功编译出so文件,然后修改config.txt文件和yolov5-config.txt文件,执行命令:
LD_PRELOAD=./libmyplugins.so deepstream-app -c deepstream_app_config_yoloV5.txt
成功跑出一路视频,wohuuu成功,然后理论上改batchsize ,n*m,source_num即可,但是调整成多路视频并行处理时发生报错,这个后面有时间在搞吧,实在是弄不动了,展示图如下图所示:

视频地址:https://live.csdn.net/v/305144
fps他说是13左右,但是实际上感觉没有tensorrt视频检测那么快, 但是他有优点可以多路,实现多种功能易修改等,毕竟英伟达开发的SDK,只能说是咱不太会用,其视频流管道集成化处理非常厉害。
最后再来说下deepstream-yolov5里的两个txt文件:config_infer_primary_yoloV5.txt和config_infer_primary.txt的关系,总体关系就是config_infer_primary.txt是deepstream调用执行的文件,config_infer_primary.txt文件引用config_infer_primary_yoloV5.txt文件,config_infer_primary.txt调用deepstream的内核运行,两个txt文件的参数都得研究修改。
还有一个建立虚拟隔离环境的问题,我们在PC端上有anaconda,虚拟隔离环境用惯了,确实非常好,在jetson arrch64架构也有achieconda,miniconda,mambaforge这些管理包,但是我搞了有些时间,最终还是不建议装虚拟环境,有以下原因:1.如果是小的项目,建个虚拟隔离环境玩一玩都是可以的,但是如果是一体化比较大的工程,内置python版本是固定的3.6,绑定好的cuda和tensorrt等库,你建立虚拟环境也只能用python3.6,没多少能动态变化的东西(当然除了现在的orin新板子可以用jetpack5内置的python版本是3.8),而且会例如import tensorrt找不到,甚至需要软连接过去,没有任何的实用性与意义。2.版本基本上都是卡的很死,装一个框架基本上就不会变了,是程序适不适合部署在板子上的玩法,以板子为主,所以我建议好的方式是准备多个卡,每个sd卡部署一个固定框架,比如用pytorch和tensorflow1或tensorflow2等等去分,这是一个比较不错的选择。
还有就是远程控制的方法,我试了ssh,vnc等等ip连接方法,我没搞通,不知道为啥原因总是连接失败找不到,说实话,我试了这么多远程控制方法,不如装todesk,上电搞个开机启动,fps还高,还稳定,不比前几个香?有现成的东西为什么要用以前的方法,这是你会发现,当nano插外接显示器时,todesk的显示是正常的,当nano没有外接显示器,todesk只显示全屏的一小部分显示不全,是因为nano没有检测到显示,只有单独远程,所以降低了gpu消耗和性能消耗,使屏幕显示不全,这时可以买一个几块钱的虚拟hdmi接头,欺骗nano外接了显示器,就显示正常了,这样的解决方案是最有效的,比那些软件修改分辨率或者修改显示服务代码可靠保险多了。
顺便提下nano联网方式,反正我的nano网线一直不稳定,连上网得看运气,这里可以推荐方法三:我的手机有USB联网开关,这是我目前见到的nano联网性价比最高的一种方法了。
Jetson Nano主板的五种联网方法_jetson nano怎么联网_知识海洋溺水的鱼儿的博客-CSDN博客
以上就是本次实验所有的内容与感悟,后面如果有时间的话,我到时候把代码开源到github,环境上传docker,大家可以直接用,如果有什么问题,可以在评论区@我,欢迎大家的讨论与交流。再次感谢以上文章中帮助我的老师与朋友们,我们一起加油!
持更。。。。。。。