References
知乎:Jetson nano部署YOLOV8并利用TensorRT加速推理实现行人检测追踪
「解析」Jetson 开启 Shell远程访问
在上文部署yolov8基础上
开启ssh服务
Jetson上下载东西有时需要魔法,开启ssh服务可以方便PC端和边缘设备传输信息
安装ssh
sudo apt-get update
sudo apt-get install openssh-server
sudo apt-get install ssh
# 开启ssh服务
sudo systemctl start ssh
配置防火墙
作者在实现远程连接的过程中关闭了防火墙,下面是针对ufw防火墙的一些shell命令,可以参考
sudo apt update
sudo apt install ufw # 安装下 ufw
sudo ufw status verbose # 检查 ufw状态
# Status: inactive # 表示已激活防火墙
sudo ufw allow ssh # 允许ssh访问,22端口
# Rules updated
# Rules updated (v6)
sudo ufw enable # 启用防火墙
sudo ufw disable # 关闭防火墙
查看是否已经开启ssh
sudo service ssh status
远程连接Jetson NX
保证PC端和Jetson开发板在同一局域网内
# Linux查看ip地址
ifconfig
# win下查看ip地址
ipconfig
对于有线网络,查看eth0下面的inet对应的ip地址,对于无线网卡,查看wlan0下面的ip地址
详细使用什么软件参考零基础入门Jetson Nano——远程连接
TensorRT Pybind
这是知乎博主Dovahlore提供的方法,作者本人跟着做了一遍,但是在YOLO导出时依旧显示没有tensorrt,本文在后面给出其他处理方法。
Jetpack中的TensorRT不能直接在python3.8环境中使用,所以我们需要对TensorRT利用pybind11对python相进性绑定。pybind的方法。参考原链接
在Jetson中创建一个external目录,并将pybind11克隆到其中。
sudo mkdir external && cd external
git clone https://github.com/pybind/pybind11.git
这里因为是通过sudo创建的文件夹,直接 git clone会报错,需要添加文件读写权限,git clone 项目报错 could not create work tree dir ‘xxx.xxx.xx‘: Permission denied,报这个错误的原因就是正在写入或者克隆 git 仓库的目录没有写入的权限。
在external文件夹的上一层执行
//再执行
sudo chmod o+w dirname
从官方获取python源代码,下载对应的python版本。将python源码中Include路径下的内容拷贝到external/python3.8/include中。
加入头文件Python.h
下载libpython3.8-dev并解压得到usr文件夹
在文件的下载目录下执行
ar x <libpython...>.deb # 对应的deb文件
tar -xvf data.tar.xz
然后将解压出的./usr/include/aarch64-linux-gnu/python3.8目录下的pycongfig.h拷贝到external/python3.8/include路径中。
在Jetson中将TensorRT与其子模块克隆到本地。选择分支release/8.2。
git clone -b release/8.2 https://github.com/nvidia/TensorRT
cd TensorRT
git submodule update --init --recursive
修改TensorRT/python/bash.sh中的内容。
bash.sh中找到以下内容:
#原内容
PYTHON_MAJOR_VERSION=${PYTHON_MAJOR_VERSION:-3}
PYTHON_MINOR_VERSION=${PYTHON_MINOR_VERSION:-8}
TARGET=${TARGET_ARCHITECTURE:-x86_64}
CUDA_ROOT=${CUDA_ROOT:-/usr/local/cuda}
ROOT_PATH=${TRT_OSSPATH:-/workspace/TensorRT}
EXT_PATH=${EXT_PATH:-/tmp/external}
WHEEL_OUTPUT_DIR=${ROOT_PATH}/python/build
- 将TARGET修改为-aarch64。
- 将ROOT_PATH改为你TensoRT对应的绝对路径。
- 将EXT_PATH改为你创建的external对应的绝对路径
PS:这里修改地址很容易出错,填写路径不对导致找不到文件夹
#修改后如下:
PYTHON_MAJOR_VERSION=${PYTHON_MAJOR_VERSION:-3}
PYTHON_MINOR_VERSION=${PYTHON_MINOR_VERSION:-8}
TARGET=${TARGET_ARCHITECTURE:-aarch64}
CUDA_ROOT=${CUDA_ROOT:-/usr/local/cuda}
ROOT_PATH=${TRT_OSSPATH:-/home/dovahlore/TensorRT}
EXT_PATH=${EXT_PATH:-/home/dovahlore/external}
WHEEL_OUTPUT_DIR=${ROOT_PATH}/python/build
最后运行bash.sh。运行前检查setuptools是否为最新版本。
pip install -U pip setuptools
bash ./build.sh
完成后在TensorRT/python/build/dist找到tensorrt-8.2.3.0-cp38-none-linux_aarch64.whl,conda环境中安装。
python -m pip install build/dist/tensorrt-*.whl
执行后在虚拟环境查看 pip list
具体操作请参考开头给出的知乎博文
TensorRT软连接
上文的方法作者在实现过程中生成TensorRT版本为8.2,可能是因为和本机Jetpack自带的TensorRT8.4版本不兼容,所以在YOLO导出过程中依旧不能调用TensorRT,下文给出解决方法。
打开jtop可以查看到自带的tensorrt版本
References
jetson 系列 安装完jetpack/已安装 tensorrt 在虚拟环境中仍然报 no module named tensorrt >> 在虚拟环境建立软连接
由于ModuleNotFoundError: No module named ‘tensorrt’安装TensorRT-python发现报错
[orin] nvidia orin 上配置tensorrt | 解决虚拟环境中路径无法import的问题
jetson xavier在使用tensorRT对yolov5加速时,报错ModuleNotFoundError: No module named ‘tensorrt‘
建立软连接
Jetpack已经安装tensorrt但是虚拟环境里面没有
查看tensorrt库安装在哪:
sudo find / -name tensorrt*
进入虚拟环境目录下
查看虚拟环境所在位置
conda info --envs
进入该目录下的 lib/python3.8/site-packages
cd /home/xiluo/miniforge-pypy3/envs/yolov8/lib/python3.8/site-packages
设置软连接
ln -s /usr/lib/python3.6/dist-packages/tensorrt
or
ln -s /usr/lib/python3.6/dist-packages/tensorrt/tensorrt.so
上述工作做完可以在虚拟环境中import tensorrt,但是执行TensorRT.__version__会提示没有 “version”属性,
解决办法
需要把原系统中的tensorrt组件复制过来就解决问题了。
tensorrt的python包位于这个路径下:
cd /usr/lib/python3.8/dist-packages/
把目录下的tensorrt-8.4.1.5.dist-info和tensorrt两个文件夹拷贝到虚拟环境的site-packages文件夹下(我的虚拟环境名为:yolov8)
cd /usr/lib/python3.8/dist-packages/
sudo cp -r tensorrt-8.4.1.5.dist-info/ ~/miniforge-pypy3/envs/yolov8/lib/python3.8/site-packages/tensorrt-8.4.1.5.dist-info
sudo cp -r tensorrt ~/miniforge-pypy3/envs/yolov8/lib/python3.8/site-packages/tensorrt
如果命令行出错可以直接鼠标粘贴复制
验证是否导入成功
python
import tersorrt
tensorrt.__version__
通过 pip list 也可以看到tensorrt已经安装成功
YOLOv8部署
在PC上改造数据集并训练YOLOV8模型,再将训练好的模型上传到在Jetson上利用TensorRT转换为.engine模型。
在yolo环境中运行pt2engine.py脚本将.pt模型转换为.engine模型。
from ultralytics import YOLO
# Load a model
model = YOLO('path/to/best.pt') # load a custom trained
# Export the model
model.export(format='engine',half=True,simplify=True)
执行出错 提示没有onnxsim
执行报错 No matching distribution found for onnxruntime-gpu
解决方法
去直接访问Jetson Zoo - eLinux.org下载对应的版本,作者是Jetpack5.0.2,python3.8
要注意:onnxruntime-gpu, cuda, cudnn三者的版本要对应,否则会报错 或 不能使用GPU推理。
onnxruntime-gpu, cuda, cudnn版本对应关系详见: 官网
然后重新使用pip3来安装就好:
pip3 install onnxruntime_gpu-1.11.0-cp38-cp38-linux_aarch64.whl
Processing ./onnxruntime_gpu-1.11.0-cp38-cp38-linux_aarch64.whl
Collecting flatbuffers
Downloading flatbuffers-2.0-py2.py3-none-any.whl (26 kB)
Requirement already satisfied: numpy>=1.22.3 in /home/hekun/.local/lib/python3.8/site-packages (from onnxruntime-gpu==1.11.0) (1.22.4)
Requirement already satisfied: protobuf in /home/hekun/.local/lib/python3.8/site-packages (from onnxruntime-gpu==1.11.0) (4.21.0)
Installing collected packages: flatbuffers, onnxruntime-gpu
Successfully installed flatbuffers-2.0 onnxruntime-gpu-1.11.0
附上知乎博主Dovahlore的两份代码,分别推理视频和摄像头
视频推理
#detect_track.py
from ultralytics import YOLO
import cv2
model = YOLO('best.engine', task='detect')
# Open the video file as source
video_path = "path/to/video"#该为你要推理的视频路径
cap = cv2.VideoCapture(video_path)
#use camera
#cap = cv2.VideoCapture(0)
#cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
#cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 640)
#cap.set(cv2.CAP_PROP_FPS,120)
# Loop through the video frames
count=0
max_id=0
font = cv2.FONT_HERSHEY_SIMPLEX
while cap.isOpened():
t1 = cv2.getTickCount()
# Read a frame from the video
success, frame = cap.read()
if success:
# Run YOLOv8 tracking on the frame, persisting tracks between frames
results=model.track(source=frame)
for result in results:
if result.boxes.id is not None:
print(result.boxes.id.cpu().numpy().astype(int))
if count<result.boxes.id.cpu().numpy().astype(int)[-1]:
count=result.boxes.id.cpu().numpy().astype(int)[-1]
# Visualize the results on the frame
annotated_frame = results[0].plot()
#fps
t2 = cv2.getTickCount()
time = (t2 - t1) / cv2.getTickFrequency()
fps = int(1/time)
#plot annotate
cv2.putText(annotated_frame,"total %d"%count,[40,40], cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0))
cv2.putText(annotated_frame, "fps %d" % fps, [40, 80], cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0))
# Display the annotated frame
cv2.imshow("YOLOv8 onnx Tracking", annotated_frame)
# Break the loop if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# Break the loop if the end of the video is reached
break
# Release the video capture object and close the display window
cap.release()
cv2.destroyAllWindows()
CSI摄像头
#detect2track.py
from ultralytics import YOLO
import cv2
import torch
import time
model = YOLO('best.engine', task='detect')
# Open the video file
#video_path = "video/video4.mp4"
#cap = cv2.VideoCapture(video_path)#video
#cap = cv2.VideoCapture(0)#USB
#CSI camera
cap = cv2.VideoCapture('nvarguscamerasrc ! video/x-raw(memory:NVMM), width=1280, height=720, format=(string)NV12,framerate=(fraction)20/1 ! nvvidconv ! video/x-raw, format=(string)BGRx ! videoconvert ! video/x-raw, format=(string)BGR ! appsink' , cv2.CAP_GSTREAMER)
count=0
max_id=0
font = cv2.FONT_HERSHEY_SIMPLEX
while cap.isOpened():
# Read a frame from the video
success,frame = cap.read()
if success:
loop_start=cv2.getTickCount()
# Run YOLOv8 tracking on the frame, persisting tracks between frames
results=model.track(source=frame,persist=True)
for result in results:
if result.boxes.id is not None:
if count<result.boxes.id.cpu().numpy().astype(int)[-1]:
count=result.boxes.id.cpu().numpy().astype(int)[-1]
#fps
loop_time=cv2.getTickCount()-loop_start
total_time=loop_time/(cv2.getTickFrequency())
fps=int(1/total_time)
# Visualize the results on the frame
annotated_frame = results[0].plot()
cv2.putText(annotated_frame,"total %d"%count,[40,40], cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0))
cv2.putText(annotated_frame,"fps %d"%fps,[40,80], cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0))
# Display the annotated frame
cv2.imshow("YOLOv8 onnx Tracking", annotated_frame)
print(fps)
# Break the loop if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# Break the loop if the end of the video is reached
break
# Release the video capture object and close the display window
cap.release()
cv2.destroyAllWindows()