Jetson Nano – YOLOv5 with CSI-2 Camera

Jetson Nano

この記事ではCSI-2カメラを使ってYOLOv5をJetson Nanoで動作させる方法について解説します。こちらの記事はUSBカメラを使用してYOLOv5をJetson Nanoで動作させましたが、今回はCSI-2カメラを使用します。CSI-2カメラはRaspberry Pi Camera V2を使用しました。

Raspberry Pi Camera V2

今回は、予めビルドしたライブラリをダウンロードして実行する方法を解説します。

こちらの記事を参考に、PyTorch、TorchVisionをJetson Nanoにインストールし、こちらの記事を参考に、OpenCVをインストールしても構いません。あるいは、こちらの記事を参考にホストでライブラリをビルドてJetson Nanoにインストールしても構いません。

必要なパッケージをインストールします。 なお今回もpython3.8を使用します。(予めビルドされたパッケージもpython3.8をターゲットにしています)

sudo apt update
sudo apt install -y \
    python3.8 python3.8-dev python3-pip \
    libopenmpi-dev libomp-dev libopenblas-dev libblas-dev libeigen3-dev libcublas-devCode language: Bash (bash)

次に予めビルドしたOpenCVパッケージをダウンロードします。

python3.8 -m pip install -U pip
python3.8 -m pip install gdown
export PATH=.local/bin:$PATH
gdown https://drive.google.com/uc?id=1VPU1oUO0_trI8Dm1AJ5UVTEGzqcnl3HU
gdown https://drive.google.com/uc?id=1Z4yKz_5azGbqq3aslc7k0WAwR-yF4Mgc
gdown https://drive.google.com/uc?id=1ZNio67dove9W5kMHqz_nmvmf1GR2y3hQ
gdown https://drive.google.com/uc?id=1_loSh1aD6_FARGhVNFIBz2W4lSw7dfqN
gdown https://drive.google.com/uc?id=1dWN5QWx-8htYURSELGbj4caqHY1228HL
gdown https://drive.google.com/uc?id=1uMfj78AxtDaIirnR5T_qfWsE4Xf8WdJPCode language: Bash (bash)

なおこちらの記事でYOLOv5を動作させたときにはOpenCVのパッケージを特別にインストールする必要はありませんでしたが、今回OpenCVがGStreamerに対応する必要があるためGStreamer対応のOpenCVパッケージをインストールします。

事前にインストールされているOpenCVパッケージはコンフリクトするため削除し、その後ダウンロードしたOpenCVパッケージをインストールします。

apt list --installed *opencv*|awk -F/ '/opencv/ {print $1}'|sudo xargs apt remove -y
sudo apt install -y ./OpenCV*.debCode language: Bash (bash)

次に予めビルドしたPyTorch、TorchVisionパッケージをダウンロードしインストールします。

# pytorch 1.11.0
gdown https://drive.google.com/uc?id=1hs9HM0XJ2LPFghcn7ZMOs5qu5HexPXwM
# torchvision 0.12.0
gdown https://drive.google.com/uc?id=1m0d8ruUY8RvCP9eVjZw4Nc8LAwM8yuGV
python3.8 -m pip install torch-*.whl torchvision-*.whlCode language: Bash (bash)

YOLOv5をクローンし、必要なpythonパッケージをインストールします。なおopencv-pythonパッケージはpipでインストールしないようにrequirements.txtをコメントアウトします。

git clone https://github.com/ultralytics/yolov5.git
cd yolov5
sed -i 's/^opencv-python/#opencv-python/g' requirements.txt 
python3.8 -m pip install -r requirements.txtCode language: Bash (bash)

YOLOv5はGStreamerに対応していないため以下のパッチファイル(patch.txt)を作成します。

diff --git a/utils/dataloaders.py b/utils/dataloaders.py
index d849d51..b4a5fbc 100644
--- a/utils/dataloaders.py
+++ b/utils/dataloaders.py
@@ -359,7 +359,7 @@ class LoadStreams:
             if s == 0:
                 assert not is_colab(), '--source 0 webcam unsupported on Colab. Rerun command in a local environment.'
                 assert not is_kaggle(), '--source 0 webcam unsupported on Kaggle. Rerun command in a local environment.'
-            cap = cv2.VideoCapture(s)
+            cap = cv2.VideoCapture(self._gstreamer_pipeline(flip_method=0), cv2.CAP_GSTREAMER)
             assert cap.isOpened(), f'{st}Failed to open {s}'
             w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
             h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
@@ -420,6 +420,25 @@ class LoadStreams:
     def __len__(self):
         return len(self.sources)  # 1E12 frames = 32 streams at 30 FPS for 30 years
 
+    def _gstreamer_pipeline(
+        self,
+        capture_width=1280,
+        capture_height=720,
+        display_width=1280,
+        display_height=720,
+        framerate=60,
+        flip_method=0,
+    ):
+        return (
+            "nvarguscamerasrc ! "
+            "video/x-raw(memory:NVMM), "
+            f"width=(int){capture_width}, height=(int){capture_height}, "
+            f"format=(string)NV12, framerate=(fraction){framerate}/1 ! "
+            f"nvvidconv flip-method={flip_method} ! "
+            f"video/x-raw, width=(int){display_width}, height=(int){display_height}, format=(string)BGRx ! "
+            "videoconvert ! "
+            "video/x-raw, format=(string)BGR ! appsink"
+        )
 
 def img2label_paths(img_paths):
     # Define label paths as a function of image paths
Code language: Diff (diff)

上記パッチを当てます。

patch -p1 < patch.txtCode language: Bash (bash)

実行します。

LD_LIBRARY_PATH=/usr/ python3.8 detect.py --source 0Code language: Bash (bash)

LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libgomp.so.1は以下で説明されているワークアラウンドになります。https://forums.developer.nvidia.com/t/error-importerror-usr-lib-aarch64-linux-gnu-libgomp-so-1-cannot-allocate-memory-in-static-tls-block-i-looked-through-available-threads-already/166494

以上です。