物体検出のYOLOをJetson Nanoでやってみます。
以前やったのはYOLOv3でしたが今回は趣向を変えてコンテナ+YOLOv4+TensorRTでやってみます。
また、姿勢推定では、torch2trtというツールを使いましたが、今回はONNXを介してTensorRTで重みを最適化してみます。
チュートリアルはtensorrt_demos のDemo#5ですが、上で書いたようにちょっとアレンジしています。
USBカメラを使った物体検出もやってみました。
なお、Step1~Step6では作業に4時間くらいはかかります。
環境構築
Jetson Nano 、Jetpack 4.4.1(L4T R32.4.4)、NVIDIAコンテナ
Nanoの初期設定はこちらをご参照ください。
コンテナイメージはnvcr.io/nvidia/l4t-ml:r32.4.4-py3です。
作業環境を作成します。
ホスト側で作業用ディレクトリを作成
1 |
mkdir work-tensorrt-demos |
ダウンロードしたファイルの解凍先をこのディレクトリにします。
こういうディレクトリ構造になります。jetsonは適宜ご自分のアカウント名で置き換えてください。
/home/jetson/work-tensorrt-demos/tensorrt_demos-master
Step1:コンテナ作成
イメージを取ってきます。
1 |
sudo docker pull nvcr.io/nvidia/l4t-ml:r32.4.4-py3 |
コンテナの作成
sudo docker create -it --name my_tensorrt_demos --gpus all --network host -e DISPLAY=$DISPLAY --device /dev/video0:/dev/video0 -v /home/jetson/work-tensorrt-demos/tensorrt_demos-master:/work -v /tmp/.X11-unix/:/tmp/.X11-unix nvcr.io/nvidia/l4t-ml:r32.4.4-py3
起動
1 |
sudo docker start -i my_tensorrt_demos |
アップデート&アップグレードして他のパッケージをインストール
1 2 3 4 5 6 7 8 9 10 11 |
apt update apt upgrade -y apt install python-pip python3-pip -y python3 -m pip install --upgrade pip apt install wget apt install nano apt install unzip apt install libcanberra-gtk* -y |
Step2:OpenCV 4.1.1 のインストール
shellファイル作成
1 |
nano install_opencv4.1.1_Nano.sh |
以下のコードをコピー・ペースト
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#!/bin/bash # # Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. # # NVIDIA Corporation and its licensors retain all intellectual property # and proprietary rights in and to this software, related documentation # and any modifications thereto. Any use, reproduction, disclosure or # distribution of this software and related documentation without an express # license agreement from NVIDIA Corporation is strictly prohibited. # if [ "$#" -ne 1 ]; then echo "Usage: $0 <Install Folder>" exit fi folder="$1" user="nvidia" passwd="nvidia" echo "** Remove other OpenCV first" apt purge *libopencv* echo "** Install requirement" apt update apt install -y build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev apt install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev apt install -y python2.7-dev python3.6-dev python-dev python-numpy python3-numpy apt install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev apt install -y libv4l-dev v4l-utils qv4l2 v4l2ucp apt install -y curl apt update echo "** Download opencv-4.1.1" cd $folder curl -L https://github.com/opencv/opencv/archive/4.1.1.zip -o opencv-4.1.1.zip curl -L https://github.com/opencv/opencv_contrib/archive/4.1.1.zip -o opencv_contrib-4.1.1.zip unzip opencv-4.1.1.zip unzip opencv_contrib-4.1.1.zip cd opencv-4.1.1/ echo "** Apply patch" sed -i 's/include <Eigen\/Core>/include <eigen3\/Eigen\/Core>/g' modules/core/include/opencv2/core/private.hpp echo "** Building..." mkdir release cd release/ cmake -D WITH_CUDA=ON -D CUDA_ARCH_BIN="5.3,6.2,7.2" -D CUDA_ARCH_PTX="" -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.1.1/modules -D WITH_GSTREAMER=ON -D WITH_LIBV4L=ON -D BUILD_opencv_python2=ON -D BUILD_opencv_python3=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .. make -j3 make install echo 'export PYTHONPATH=$PYTHONPATH:'$PWD'/python_loader/' >> ~/.bashrc source ~/.bashrc echo "** Install opencv-4.1.1 successfully" echo "** Bye :)" |
インストール実行
1 2 3 |
mkdir opencv chmod 755 install_opencv4.1.1_Nano.sh sh install_opencv4.1.1_Nano.sh opencv |
確認
Python3(python2)
>>>import cv2
何もなければOK
Step3:ONNX 1.4.1 インストール
既存のONNX(1.7.0)を削除
(新しいバージョンでは不具合がでるそうで、1.4.1が指定されています)
1 |
pip3 uninstall onnx -y |
バージョン指定(1.4.1)してインストール
1 2 |
apt install protobuf-compiler libprotoc-dev pip3 install onnx==1.4.1 |
Step4:protobuf-3.8.0 インストール
shellファイル作成
1 2 3 |
cd / nano install_protobuf-3.8.0.sh |
以下のコードをコピー・ペースト
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#!/bin/bash set -e folder=${HOME}/src mkdir -p $folder echo "** Install requirements" apt install -y autoconf libtool echo "** Download protobuf-3.8.0 sources" cd $folder if [ ! -f protobuf-python-3.8.0.zip ]; then wget https://github.com/protocolbuffers/protobuf/releases/download/v3.8.0/protobuf-python-3.8.0.zip fi if [ ! -f protoc-3.8.0-linux-aarch_64.zip ]; then wget https://github.com/protocolbuffers/protobuf/releases/download/v3.8.0/protoc-3.8.0-linux-aarch_64.zip fi echo "** Install protoc" unzip protobuf-python-3.8.0.zip unzip protoc-3.8.0-linux-aarch_64.zip -d protoc-3.8.0 cp protoc-3.8.0/bin/protoc /usr/local/bin/protoc echo "** Build and install protobuf-3.8.0 libraries" export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp cd protobuf-3.8.0/ ./autogen.sh ./configure --prefix=/usr/local make -j$(nproc) make check make install ldconfig echo "** Update python3 protobuf module" # remove previous installation of python3 protobuf module apt install -y python3-pip pip3 uninstall -y protobuf pip3 install Cython cd python/ python3 setup.py build --cpp_implementation python3 setup.py test --cpp_implementation python3 setup.py install --cpp_implementation echo "** Build protobuf-3.8.0 successfully" |
インストール実行
1 2 |
chmod 755 install_protobuf-3.8.0.sh sh install_protobuf-3.8.0.sh |
確認
1 |
protoc --version |
Step5:準備
「plugins /」サブディレクトリに移動し、「yolo_layer」プラグインをビルド
1 2 |
cd /work/plugins make |
以下のファイルが作成されます。
libyolo_layer.so
YOLO(cfg、weights)をダウンロード
1 2 |
cd /work/yolo ./download_yolo.sh |
以下のファイルがダウンロードされます。
Creating yolov3-tiny-288.cfg and yolov3-tiny-288.weights
Creating yolov3-tiny-416.cfg and yolov3-tiny-416.weights
Creating yolov3-288.cfg and yolov3-288.weights
Creating yolov3-416.cfg and yolov3-416.weights
Creating yolov3-608.cfg and yolov3-608.weights
Creating yolov3-spp-288.cfg and yolov3-spp-288.weights
Creating yolov3-spp-416.cfg and yolov3-spp-416.weights
Creating yolov3-spp-608.cfg and yolov3-spp-608.weights
Creating yolov4-tiny-288.cfg and yolov4-tiny-288.weights
Creating yolov4-tiny-416.cfg and yolov4-tiny-416.weights
Creating yolov4-288.cfg and yolov4-288.weights
Creating yolov4-416.cfg and yolov4-416.weights
Creating yolov4-608.cfg and yolov4-608.weights
Creating yolov4-csp-256.cfg and yolov4-csp-256.weights
Creating yolov4-csp-512.cfg and yolov4x-csp-512.weights
Creating yolov4x-mish-320.cfg and yolov4x-mish-320.weights
Creating yolov4x-mish-640.cfg and yolov4x-mish-640.weights
テスト用画像をダウンロードしておく
1 2 3 |
cd /work mkdir Pictures wget https://raw.githubusercontent.com/pjreddie/darknet/master/data/dog.jpg -O /work/Pictures/dog.jpg |
Step6:TensorRT最適化
Step5で取得したデータはいろいろあります。YOLOv3とYOLOv4。
画像サイズが288、416、608のもの(サイズは32の倍数)。
ネットワークモデルは5種類。
通常のモデル以外に
tiny:conv layer数などを減らして、より軽量化したモデル、通常の1/10くらいのサイズ
SPP:Spatial Pyramid Pooling Based YOLO
CSP:Cross Stage Partial connections
mish:活性化関数
画像サイズ416のYOLOv4、tinyモデルでやってみます。
1 |
cd /work/yolo |
ONNXに変換
weights,cfg ー>onnx
1 |
python3 yolo_to_onnx.py -m yolov4-tiny-416 |
以下のファイルが作成されます。
yolov4-tiny-416.onnx
TensorRTエンジンに変換
onnxー>trt
1 |
python3 onnx_to_tensorrt.py -m yolov4-tiny-416 |
以下のファイルが作成されます。
yolov4-tiny-416.trt
In case “onnx_to_tensorrt.py” fails (process “Killed” by Linux kernel), it could likely be that the Jetson platform runs out of memory during conversion of the TensorRT engine. This problem might be solved by adding a larger swap file to the system. Reference: Process killed in onnx_to_tensorrt.py Demo#5.
「onnx_to_tensorrt.py」が失敗した場合(Linuxカーネルによる「Killed」プロセス)、TensorRTエンジンの変換中にJetsonプラットフォームのメモリが不足している可能性があります。 この問題は、より大きなスワップファイルをシステムに追加することで解決できる可能性があります。
killされないまま、プロセスに不具合が生じて完了しない場合もあります。10分以上経過しても終了せずjetson-statsを見てもCPUがどれもフル稼働していないような場合はコンテナを再起動してonnx_to_tensorrt.pyを再実行してみてください。
USBカメラを使う場合は、描画にtkinter + canvas を使うので、tkinter をインストールしておきます。
1 |
apt install python3-tk -y |
これで道具は一通りそろったので、コンテナを終了しておきます。
Ctrl + D で抜ける。
Step7:実行
Test the TensorRT “yolov4-tiny-416” engine with the “dog.jpg” image.
TensorRT「yolov4-tiny-416」エンジンを「dog.jpg」画像でテストします。
ホスト側でxhostを実行
1 |
sudo xhost si:localuser:root |
コンテナを起動して以下を実行
1 2 3 4 |
sudo docker start -i my_tensorrt_demos cd /work python3 trt_yolo.py --image /work/Pictures/dog.jpg -m yolov4-tiny-416 |
こんな感じ。
USBカメラを使ってみます。
こんな感じで物体検出します。
YOLOv4-tiny-416のTensorRTエンジンを使った場合。
この例では、Windowの下に赤字で検出した人の数を表示しています。
例えば、コードはこんな感じ。
category_numberやモデル名、画像サイズなどはハードコードしています、必要なら適宜変更してくださいませ。
詳しくは、trt_yolo.pyやtrt_yolo_cv.pyをご参照ください。
もうちょい細かくデータを取得したい場合は、utils/visualization.py などをご参照ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# -*- coding: utf-8 -*- import tkinter as tk import cv2 from PIL import Image,ImageTk import numpy as np import pycuda.autoinit from utils.yolo_classes import get_cls_dict from utils.visualization import BBoxVisualization from utils.yolo_with_plugins import get_input_shape, TrtYOLO root=tk.Tk() root.title("camera") root.geometry("416x416") root.resizable(width=False, height=False) canvas=tk.Canvas(root, width=416, height=416, bg="white") canvas.pack() def capStart(): print('camera-start') try: global c, vis, trt_yolo letter_box = False category_number = 80 model_name = "yolov4-tiny-416" c = cv2.VideoCapture(0) cls_dict = get_cls_dict(category_number) vis = BBoxVisualization(cls_dict) h, w = get_input_shape(model_name) trt_yolo = TrtYOLO(model_name, (h, w), category_number, letter_box) print('width:'+str(w)+'px/height:'+str(h)+'px') except: import sys print("error") print(sys.exec_info()[0]) print(sys.exec_info()[1]) c.release() cv2.destroyAllWindows() def up():#change update global img conf_th=0.3 ret, frame = c.read() if ret: frame = frame[0:720, 0:720] size = (416,416) frame = cv2.resize(frame,size) boxes, confs, clss = trt_yolo.detect(frame, conf_th) frame = vis.draw_bboxes(frame, boxes, confs, clss) img = ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))) canvas.create_image(0,0,image=img,anchor="nw") else: print("up failed") root.after(1,up) capStart() up() root.mainloop() |
NanoとXavier NX とでは、検出精度に差はないと思われますが、カメラのパフォーマンスを含めると….(まぁ、当然ですけど)
Leave a Reply