JetsonNano国产套件成功部署YoloV5手把手图解教程

2022年是新冠疫情的第三个年头,各行各业都不太景气赚钱越来越难了。为了让自己别太消沉,我开始找些有兴趣的事情来搞一下。于是在笔记本上部署了YoloV5,训练了几个模型,本意就是做着玩,没想到其中有些功能被朋友看上了,要部署一套试用。这对我来说就有点麻烦了,直接给他放个工控机成本有点高而且不太专业,从网上查了一下,发现原来还有jetson-nano这个东西,价格不贵体积还小,感觉正适合我,就打算入手一个。结果一打听,Nvidia原厂的主板没货而且挺贵。国产jetson-nano套件有货,价格也相对便宜一些。我抱着尝试的想法买了一块,折腾两周后终于练成神功,成功部署、运行了YoloV5。这期间遇到不少困难,跟卖家有过多次沟通,人家很配合,但因为没有客户在他们这个板子上部署过YoloV5,所以无法提供详细的教程。为了感谢卖家的帮助,同时也为了让自己以后再搭建部署的时候能有个依据,本人以注册CSDN后最为认真的态度制作了以下教程,希望能帮助到有相同需求的朋友。

首先是准备工作,我的主板如下图:

产品名称:Jetson NX国产套件

型号/规格:P3668

买主板的时候只是一个裸板,风扇、电源适配器、Wifi模块都是单买的,卖家就有,建议一次采购好,要不后面很麻烦(跟老板套套磁也没准能他送给你,别说是我说的哟^_^)。我就忘记了电源适配器的事,结果老板很仗义,直接送个我了一个。电源适配器是12V,48W的,输入100V~240V 5A 50/60Hz,输出12V-4A,可能在市面上很常见,我不懂硬件所以没有自己去找,直接跟老板要的,老板很痛快直接送给我一个,但是快递进北京之前要统一消杀,结果耽误了好几天时间。

下图就是完整的jetson-nano套件三大件,有了这些就能开机、联网了。当然Wifi模块不是必须的,主要看你的网络环境。

这里我再补充个重要的事情,咱们这个主板的镜像是ubuntu18.4,不能装其他操作系统,主板自带的存储空间是16G,但是ubuntu系统镜像上去之后就已经占用14G+了,留给咱们部署的空间只有1G+。搭建YoloV5环境还要安装、更新很多包,1G+空间肯定是不够的,所以建议大家提前采购个固态硬盘,一定要买M.2接口的,买错了用不了。我买的是金士顿250G SSD固态硬盘 M.2结口(NVMe协议),大概200元出头。咱们搭建环境之前得先把操作系统从主板自带的存储空间迁移到自己的固态硬盘上,这样才有足够的空间部署和运行YoloV5,我后面的教程里会详细的教你怎么迁移。另外这个Jetson NX国产套件还能插tf卡,但是tf卡不能用来迁移操作系统,只能作为扩展空间使用。由于我250G的固态硬盘已经够用了,所以就没有再插tf卡。下图就是我买的固态硬盘:

好了,书归正传,下面就要正式开始搭建环境了。拿到Jetson NX国产套件之后,老板给我发了一个《Jetson-Nano 国产套件使用手册》的PDF文档,里面介绍了怎么刷机和安装常用软件,介绍的挺详细,但是没有说怎么部署YoloV5,而且里面提供的刷机包还有问题,刷了之后进不去ubuntu系统,所以如果你只是想部署YoloV5,果断放弃这个文档吧,按照我的教程向下进行就可以了。我发现文档里面的刷机包有问题之后找老板反应,老板给我了一个新的刷机包,经过测试是正常的。我把百度网盘的地址放出来,如果下载不了啦,请大家给我留言。

链接:https://pan.baidu.com/s/1Yz7U7gr7yUSXSa4yGjj0vQ

提取码:59ks

现在要开始刷机了,Jetson-Nano 国产套件的快递盒子里除了主板之外,还有一个小塑料袋,装着一根杜邦线、一个跳线帽和一根刷机线。杜邦线我不知道是干嘛用的,跳线帽会用到,千万别弄丢了。下图就是随主板一起快递来的杜邦线和跳线帽:

刷机前,主板先不要通电,用跳线帽把主板上的FC REC和GND短接起来,如下图:

然后找一台安装了Ubuntu18.04系统的电脑(如果你没有ubuntu系统的电脑可以自己安装一下,非常方便,没弄做过的朋友参考这两篇文章https://blog.csdn.net/fu6543210/article/details/79722615,https://blog.csdn.net/syp_net/article/details/108738198,我就是第一次装ubuntu,很顺利就弄好了。除了直接安装外,还可以做虚拟机安装,我找了个旧电脑直接装上了就没做虚拟机,有兴趣的朋友可以研究一下怎么用虚机安装)。然后用刷机线把Jetson-Nano 国产套件和电脑连接起来,如下图:

现在用这台ubuntu系统的电脑去下载前面百度网盘的镜像包,我是在windows上下载完,用U盘传到ubuntu电脑上面的。下载地址这里再发一遍:

链接:https://pan.baidu.com/s/1Yz7U7gr7yUSXSa4yGjj0vQ

提取码:59ks

下载后会看到下面6个文件:

打开readme.txt参考,先将文件合并:

cat JetPack_4.6_Linux_JETSON_NANO_TARGETS.tar.gz* > JetPack4.6_Linux_JETSON_NANO_TARGETS.tar.gz

文件合并后会多出来一个叫做JetPack4.6_Linux_JETSON_NANO_TARGETS.tar.gz的文件。如下图:

然后解压这个文件:

sudo tar -zxvf JetPack4.6_Linux_JETSON_NANO_TARGETS.tar.gz

执行完成后,会出现一个新的目录,如下图:

现在给Jetson-Nano 国产套件插上电源适配器,插上之后主板上会亮起绿的的小灯。如下图:

在Ubuntu18.04的电脑上打开一个终端,测试Jetson-Nano 国产套件与电脑的连接情况。

输入lsusb命令,如果出现Nvidia Corp.就说明已经连接成功,可以开始下一步了。如下图:

从终端进入前面创建的JetPack4.6_Linux_JETSON_NANO_TARGETS/ Linux_for_Tegra这个目录下面,执行脚本刷机:

sudo ./flash.sh -r jetson-nano-devkit-emmc mmcblk0p1

刷机的时间比较长,但是和后面要进行的操作比起来,就算是挺快的了。当终端显示

*** The target t210ref has been flashed successfully. ***

Reset the board to boot from internal eMMC.

就完成刷机了。如下图:

把Jetson-Nano 国产套件的HDMI口连接到一台显示器上,能看到主板的系统已经刷好了。如下图:

好了,如果你也看到这个界面就说明刷机成功了。现在给你的Jetson-Nano 国产套件插上鼠标、键盘和Wifi模块。然后关掉主板和刚才刷机用的Ubuntu电脑,注意是通过操作系统关机(power off),不是直接断电啊,关机完成后主板上面的绿灯会自己熄灭,此时测试拔掉主板的电源适配器。如下图:

到这里,你刷机用的Ubuntu18.04这台电脑就完成了他的历史使命,可以关机了。咱们后面的操作再也不会用到它了。关机后拔掉连接在Jetson-Nano 国产套件上的刷机线,再取掉主板上的连接FC REC和GND的短接帽。这个不太好取,用手基本上弄不下来,建议用镊子加下来,别把引脚弄坏了。然后把咱们采购的固态硬盘插在主板上,接口在主板的底下。插上之后就像下图这样:

现在Jetson-Nano 国产套件已经准备就绪,可以开机啦。主板没有开关,把电源适配器插上就开机了。开机后主板上的绿灯会亮起来,屏幕也会进入登陆界面。可以看到主板用户是nvidia,点击一下输入密码。默认密码也是nvidia。输入完密码后按回车,主板进入操作系统。如下图:

说实话,我还是挺喜欢nvidia这个绿色桌面背景的,很有冲击力,叫上帝之眼是吧?进入系统之后,我们先要让主板能够上网。点击右上角的箭头,从下拉菜单中找到自己的Wifi网络,然后输入密码,点击Connect建立连接。如下图:

正常的话,主板现在就应该可以联网了。咱们下面要开始挂载固态硬盘了。点击左上角的Search your computer,输入disks。点击后如下图:

点击搜索出来的Disks进入这个APP。可以看到最上面就是我250G的固态硬盘,下面那个SD Card Reader DG4016就是主板自带的16G存储空间。咱们选中新插入的这块250G硬盘(橙色表示选中状态,我这个默认就选中了,)。点击后如下图:

在键盘上按组合键ctrl+f进入格式化界面。点击后如下图:

不用改选项,直接点Format按钮就行了。格式化前先进行确认。点击后如下图:

可以看到,选中的是250G的金士顿英硬盘。确定硬盘选择没问题,直接点击Format。点击后如下图:

输入nvidia用户的密码,然后点击authenticate。点击后如下图:

这个格式化的过程非常快,一瞬间就执行完了。现在咱们250G的固态硬盘已经格式化好了,准备开始分区,点击volumes下面的+加号创建分区(Create partition unallocated space),点击后如下图:

这里创建分区,我只分了一个区,大小是250G,所以直接点击Next就可以了。如果要把固态硬盘分成多个区,根据自己的想法调整每个区的大小就可以了。分配好区的大小点击Next。点击后如下图:

这里输入卷的名称,咱们就命名成为ssd吧。在Volumes Name里面输入ssd,然后点击Create。点击后如下图:

这里输入nvidia用户的密码,按下authenticate再次进行确认。此时分区创建成功,准备进行挂载。点击后如下图:

可以看到,这个界面volumes的下面有个小三角,类似播放器的play键(Mount selected partition),点击它挂载这个分区。点击后,小三角变成正方形,类似播放器的stop键。点击后如下图:

现在咱们250G的金士顿固态硬盘已经挂载到Jetson-Nano 国产套件上了。打开终端验证一下,输入命令

df -lh

显示如下:

可以看到我们250G的硬盘挂载到了/media/nvidia/ssd这个目录下,硬盘设备号是/dev/nvme0n1p1,总空间是229G,目前可用空间是217G。而咱们Jetson-Nano 国产套件上自带的存储空间,设备号是/dev/mmcblkop1,只有14G,镜像操作系统已经使用了12G,目前可用空间只有1.3G了。这点空间根本不足以搭建YoloV5的运行环境。所以下面咱们要开始迁移操作系统了。目的是把操作系统从主板自带存储空间迁移到咱们250G的固态硬盘上面。我们在终端进入到250G固态硬盘的挂载目录下,执行命令:

git clone https://github.com/jetsonhacks/rootOnNVMe.git

这个命令要主板能连接互联网才能执行,执行成功后会在/media/nvidia/ssd下面新增一个rootOnNVMe目录。如下图:

进入新创建的rootOnNVMe目录,修改rootOnNVME 文件中的以下三个文件:

copy-rootfs-ssd.sh

data/setssdroot.sh

data/setssdroot.service

需要将以上三个文件中对应的设备号改成/dev/nvme0n1p1。改完之后如下图:

上图是copy-rootfs-ssd.sh,下图是data/setssdroot.service

上图是data/setssdroot.service,下图是data/setssdroot.sh

准备就绪,下面执行copy-rootfs-ssd.sh命令:

./ copy-rootfs-ssd.sh

执行后需要输入nvidia用户的密码,然后开始复制操作。这个速度还是比较快的,我主板大概能执行到80到110MB/s,一会功夫就能执行完。执行完成后如下图:

下面开始执行setup-service.sh命令:

./setup-service.sh

执行后,这里也需要输入nvidia用户的密码,但是这个输入密码的位置跟上面的的命令不太一样。不是在终端输入,而是在弹出窗口中输入。这个命令的执行速度非常快。执行完成后如下图:

现在咱们【新硬盘的挂载】和【迁移操作系统到250G固态硬盘】的任务就完成了,执行reboot命令重启一下主板。重新输入密码进入操作系统后,打开终端,输入df -lh命令,设备号是/dev/nvme0n1p1的250G固态硬盘已经挂载到了操作系统根目录下。而主板自带的16G存储空间(设备号/dev/mmcblkop1)已经被挂载到了/media/nvidia/********-****-****-****-****的这个目录下了。请注意,虽然操作系统已经迁移,但是主板自带的16G存储空间的文件也不能删除,最好不要动。因为250G固态硬盘仅作为系统盘(rootfs 和用户区),系统的启动引导依然是通过主板自带的16G存储空间或EMMC,比如升级设备树dtb还是在主板自带的16G存储空间或EMMC 中。执行df -lh命令后如下图:

接下来咱们开始更新系统包,执行命令:

sudo apt-get update

执行完成后如下图:

这个执行比较快,有人说可以换清华的镜像,速度会更快。我这网络还可以,就没有换。下面执行命令:

sudo apt-get upgrade

这个就比较慢了耐心等吧,执行后如下图:

执行时间特别长,我这里执行大概用了一个小时。完成后如下图:

因为是国外的网站,执行过程中有可能会更新失败,所以要仔细看一下。如果更新失败了就再执行一次命令。确定执行完成了就开始下一步,安装pip3,执行下面命令:

sudo apt-get install python3-pip python3-dev -y

执行完成后如下图:

由于咱们jetson-nano国产套件的镜像里已经安装了最新的pip,这里其实没有安装。姑且写在这里,避免朋友们因为这个坑受阻。

到现在为止咱们主板的操作系统还是英文的,接下来咱们把它改成中文的。点击左侧的系统设置(System  Settings),如下图:

打开系统设置窗口后,点击Language Support(语言支持)图标。打开新的窗口,会提示“The Language Support is not installed completely”(支持语言尚未完全安装),这里点击Install进行安装就可以了。如下图:

安装之前会要求输入nvidia用户的密码,输入后点击authenticate,正式开始安装。如下图:

安装过程也比较长,等这就行。安装中有可能通讯失败,重新安装就可以了。访问国外的网站确实不太稳定。安装完成后,把Language菜单最下面的“汉语”选项拖动到菜单顶端,然后关闭Language Support窗口就可以了。如下图:

现在在终端里执行命令:

Reboot

重启jetson-nano国产套件,重启后可以看到系统已经变成中文了。进入系统后会看到一个对话窗口,询问是否将标准文件夹更新到当前语言。这些目录名径长会在命令中出现,为了方便,我建议就别改了。勾选“不要再次询问我”,然后点击“保留旧的名称”。如下图:

接下来安装jtop,用来在终端查看自己电脑cpu和gpu情况,其实咱们jetson-nano国产套件的镜像也已经安装了,我这里也记录一下。执行命令:

sudo -H pip3 install jetson-stats

sudo jtop

执行完成后,如下图:

这个功能和windows的任务管理器差不多。按Q键就能退出这个界面了。

下面咱们开始修改jetson-nano国产套件的显存,在终端输入命令:

sudo gedit /etc/systemd/nvzramconfig.sh

执行后如下图:

修改nvzramconfig.sh文件:

在打开的文档中找到mem值,修改mem的值,如下:

修改之前mem = $((("${totalmem}"/2/"${NRDEVICES}")*1024))

修改之后mem = $((("${totalmem}"*2/"${NRDEVICES}")*1024))

把 / 修改为 *

修改之后如下图:

保存退出,然后执行reboot重启jetson-nano国产套件。再次进入系统后打开终端,执行命令:

free -h

可以看到“交换”(swap)已经变为7.7G了。如下图:

接下来咱们配置cuda。jetson-nano国产套件镜像是自带cuda的,而且环境变量都给配置好了,咱们需要稍微改一下环境变量。执行命令:

gedit ~/.bashrc

执行后如下图:

可以看到,在.bashrc文件的最后两行就是cuda的环境变量,咱们把这两行注释掉,然后把下面三行复制进去:

export PATH=/usr/local/cuda-10.2/bin${PATH:+:${PATH}}

export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

export CUDA_ROOT=/usr/local/cuda

如下图:

保存退出,然后执行命令:

source ~/.bashrc

让环境变量修改生效。生效后可以再执行命令:

nvcc -V

查看自己的cuda版本。如下图:

可以看到,咱们cuda的版本是10.2。看到这个就说明环境变量配置成功,可以开始配置所需的库了。执行命令:

sudo apt-get install build-essential make cmake cmake-curses-gui -y

执行后如下图:

执行命令:

sudo apt-get install git g++ pkg-config curl -y

执行后如下图:

执行命令:

sudo apt-get install libatlas-base-dev gfortran libcanberra-gtk-module libcanberra-gtk3-module -y

执行后如下图:

执行命令:

sudo apt-get install libhdf5-serial-dev hdf5-tools -y

执行后如下图:

执行命令:

sudo apt-get install nano locate screen -y

执行后如下图:

执行命令:

sudo apt-get install libfreetype6-dev -y

执行后如下图:

执行命令:

sudo apt-get install protobuf-compiler libprotobuf-dev openssl -y

执行后如下图:

执行命令:

sudo apt-get install libssl-dev libcurl4-openssl-dev -y

执行后如下图:

执行命令:

sudo apt-get install cython3 -y

执行后如下图:

执行命令:

sudo apt-get install gfortran -y

执行后如下图:

执行命令:

sudo apt-get install libjpeg-dev -y

执行后如下图:

执行命令:

sudo apt-get install libopenmpi2 -y

执行后如下图:

执行命令:

sudo apt-get install libopenblas-dev -y

执行后如下图:

执行命令:

sudo apt-get install libjpeg-dev zlib1g-dev -y

执行后如下图:

到此为止,配置所需要的库就已经安装完了。如果网络正常,这个环节用时不会太久。

下满咱们开始安装opencv所需要的支持包。

执行命令:

sudo apt-get install build-essential -y

执行后如下图:

执行命令:

sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev -y

执行后如下图:

执行命令:

sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff5-dev libdc1394-22-dev -y

执行后如下图:

执行命令:

sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev liblapacke-dev -y

执行后如下图:

执行命令:

sudo apt-get install libxvidcore-dev libx264-dev -y

执行后如下图:

执行命令:

sudo apt-get install libatlas-base-dev gfortran -y

执行后如下图:

执行命令:

sudo apt-get install ffmpeg -y

执行后如下图:

现在安装opencv所需要的包都已经安装完了。接下来咱们开始安装cmke。先下载,执行命令:

wget http://www.cmake.org/files/v3.13/cmake-3.13.0.tar.gz

执行后如下图:

执行完成后,可以看到当前目录下多了个cmake-3.13.0.tar.gz的文件,下面对这个文件进行解压缩。执行命令:

tar xpvf cmake-3.13.0.tar.gz cmake-3.13.0/

执行后如下图:

解压缩完成后,会出现一个新目录cmake-3.13.0,进入这个目录。执行命令:

cd cmake-3.13.0/

然后再执行命令:

./bootstrap --system-curl

执行这个命令的时间会很长,我感觉得有20分钟,耐心等待吧。可以下楼去抽根华子了,很有可能你抽完回来了,这边还没执行完。执行完成后如下图:

下面开始编译,执行命令:

make -j4

这个执行时间也很长,不过终端会输出进度,可以根据这个时间再去抽根华子了。这里善意提醒一句:吸烟有害健康,保持社交距离。执行完成后如下图:

编译完成后,再次修改环境变量。执行命令:

echo 'export PATH=~/cmake-3.13.0/bin/:$PATH' >> ~/.bashrc

执行完成后,系统会自己在.bashrc最后加上一句export PATH=~/cmake-3.13.0/bin/:$PATH

然后执行命令:

source ~/.bashrc

让修改的环境变量生效。

下面安装exfat-utils用来解决大容量U盘兼容的问题,执行命令:

sudo apt-get install exfat-utils

执行完成后如下图:

到此jetson-nano国产套件的系统环境已经配置好了,后面开始配置YoloV5所需要的环境。咱们使用的是torch 1.8和torchvision 0.9。这两个文件可以从百度网盘下载,下面是下载地址:

链接:https://pan.baidu.com/s/1cGS-gYdnEvT-9M0ve3hacg

提取码:01F6

如果这个地址失效了,请朋友们给我留言。

下载后把文件夹放到jetson-nano国产套件的桌面上就可以了,目录名叫pytorch-torchvision,里面有一个文件:torch-1.8.0-cp36-cp36m-linux_arrch64.whl

还有一个目录:torchvision

如下图:

在这个目录中按鼠标右键,选择“在终端中打开”,然后输入sudo pip3 install,再把文件torch-1.8.0-cp36-cp36m-linux_arrch64.whl拖入到终端里,并按回车执行。如下图:

关于上面这个环节,为什么要拖入whl执行,我也不明白。但是之前尝试的时候直接输入命令执行,YoloV5运行有问题。但是按照拖动的方式执行,YoloV5执行成功了。所以我就迷信的这样做了,如果谁知道拖动跟直接输入命令的区别,希望不吝赐教。

下面再安装几个包,否则安装后面torchvision时会报错。执行命令:

sudo apt-get install libjpeg-dev

执行后如下图:

执行命令:

sudo pip3 install pillow

执行后如下图:

接下来进入pytorch-torchvision这个目录。执行命令:

cd torchvision

然后执行命令:

export BUILD_VERSION=0.9.0

再执行命令:

sudo python3 setup.py install

这个执行又要很长时间,感觉20分钟起步吧。烟瘾大的朋友可以再去抽一根了。感觉咱们这个部署教程特别费烟。安装过程中可能会有一些具体代码的警告,类似下图:

不用管它,耐心等着就行了。执行完成后,如下图:

现在我们验证一下torch和torchvision有没有安装好。

先reboot重启jetson-nano国产套件,然后在终端执行命令:

python3

进入python3中,逐行输入:

import torch

import torchvision

print(torch.cuda.is_available())

如果输出True就说明安装成功了。如下图:

执行quit()退出python3。

下面继续安装YoloV5所需要的包。先安装matplotlib 3.2.2。执行命令:

sudo pip3 install matplotlib==3.2.2

执行后如下图:

更新Cython,执行命令:

sudo pip3 install --upgrade Cython

执行后如下图:

卸载python-numpy,执行命令:

sudo apt-get remove python-numpy

执行后如下图:

安装numpy 1.19.4,执行命令:

sudo pip3 install numpy==1.19.4

numpy安装需要挺长时间。执行后如下图:

安装scipy 1.4.1.,执行命令:

sudo pip3 install scipy==1.4.1.

这个执行时间也特别长。执行后如下图:

执行命令:

sudo pip3 install tqdm==4.61.2

执行后如下图:

执行命令:

sudo pip3 install seaborn==0.11.1

执行后如下图:

执行命令:

sudo pip3 install scikit-build==0.11.1

这个安装很慢,耐心等吧。执行后如下图:

执行命令:

sudo pip3 install opencv-python==4.5.3.56

这个同样安装很慢,我这大概执行了一个小时,继续耐心等吧。执行后如下图:

执行命令:

sudo pip3 install tensorboard==2.5.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

tensorboard依赖包很多,也得等挺长一阵。安装执行后如下图:

执行命令:

sudo pip3 install PyYAML==5.4.1

执行后如下图:

执行命令:

sudo pip3 install thop

执行后如下图:

执行命令:

sudo pip3 install pycocotools

执行后如下图:

执行命令:

sudo pip3 install future

执行后如下图:

好了,至此咱们YoloV5的环境已经搭建完成了,把咱们Yolo工程copy到jetson-nano国产套件上面吧。我直接把工程放到了桌面。先打开你工程下的detect.py文件,看看里面有没有下面这句:

from anyio._core import _threads

如果有,就把这句注释掉。这句在windows下推理没有问题,在jetson-nano国产套件下就会报错。

然后再进入下面python3.6d的目录:

cd /usr/local/lib/python3.6/dist-packages/torch/nn/modules/

打开activation.py文件

sudo vi activation.py

把self.inplace删除,我是注释掉了。

    def forward(self, input: Tensor) -> Tensor:

        # return F.hardswish(input, self.inplace)

        return F.hardswish(input)

如下图:

回到Yolo工程所在的目录,在终端执行命令:

python3 detect.py --source inference/images --weights best.pt

图像推理成功,如下图:

换上USB摄像头,执行也没有问题。

到此,部署大功告成。希望大家部署顺利。