実習:物体検出(YOLOv3) - masuko-shingo/jetson-nano GitHub Wiki

物体検出(YOLOv3)

ここでは,YOLOv3を用いた物体検出を行います.
論文や著者のサイトは末尾の"参考文献"に記述しています.

動作を確認したUSBカメラ

Logicool C310 HD WEBCAM
https://www.amazon.co.jp/dp/B084CC82PH/

Microsoft LifeCam HD5000 7ND-00006
https://www.amazon.co.jp/dp/B003CYMA4U

環境構築

  • ディレクトリを作る
    作業する場所を作ります.
    ここでは,yolov3としていますが,名前はなんでも構いません.
$ mkdir yolov3
$ cd yolov3
  • aptの更新
    まず,aptを更新しておきます.
$ sudo apt-get update
  • CUDAのパスを通す
    CUDA(GPUのドライバ)のパスを通して,GPUを使うための準備をします.
$ export PATH=/usr/local/cuda-10.0/bin${PATH:+:${PATH}}
$ export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
  • Yolov3をcloneする
    Yolov3のリポジトリをgithubからcloneしてきます.
$ git clone https://github.com/AlexeyAB/darknet
$ cd ~/yolov3/darknet #darknetに移動
  • 重みのダウンロード
    重みをダウンロードしてきます.
    ダウンロードする場所はdarknetのままで問題ありません.
$ wget https://pjreddie.com/media/files/yolov3.weights
$ wget https://pjreddie.com/media/files/yolov3-tiny.weights
  • GPU, CUDA, CUDNN, OPENCVを有効にする
    Makefileを編集して,GPU,CUDA,CUDNN,OPENCVを有効にします.
$ sudo vi Makefile

上記のコマンドでMakefileを編集できるようにして, 文頭のパラメータを変更します.
※エディタがvi,vimの場合は" i "で文字を打ち込める(編集できる)ようになります
Makefile変更前

GPU=0
CUDNN=0
OPENCV=0
OPENMP=0
DEBUG=0

変更後

GPU=1
CUDNN=1
OPENCV=1
OPENMP=0
DEBUG=0

  • コンパイル(Make)する
    Makeと打ち込み,コンパイルを行います.
$ Make

物体検出(学習済みモデル)

ここからは,デフォルトで入っている学習済みモデルを用いて,画像認識を行ってみます.

  • ディレクトリの移動
$ cd ~/yolov3/darknet
  • 推定を行う際
$ ./darknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights data/dog.jpg 

※dog.jpgは例
dataに認識したい画像を追加すると他の画像の推定を行える
frame0000を追加した際の例

$ ./darknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights data/frame0000.jpg 

USBカメラを用いた物体検出(学習済みモデル)

ここでは,デフォルトで入っている学習済みモデルを用いて,USBカメラ画像から物体認識を行ってみます.

  • ディレクトリの移動
$ cd ~/yolov3/darknet
  • 推定を行う際
$ ./darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights -c 0

最後の数値0はUSBカメラに当てられている値.
調べたい場合は,ls /dev/ttyUSB*と入力.

$ ls /dev/ttyUSB*

*はワイルドカード

物体検出(自作データセット)

学習済みモデルでは,データセットはCOCOデータセット,ネットワークのモデルは学習済みのモデルを用いて,推論を行っていました.
ここからは,実際にデータセットを作成し,自作データセットでの学習,推論を行います.

データセット作成

まずは,データセットの作成を行います.
この作業は主にPCで行っていきます. 今回はTurtlebot3の画像を使用してデータセットを作成していきますが,他のものでも構いません.

bagファイルから画像を生成する

まずUSBカメラを起動させた状態でbagファイルを取得します. USBカメラを起動した状態でrosbag record -aを行います.
※bagファイルの取得はPCからでも,Nanoからでも構いません.

  • USBカメラの起動
$ roscore
$ roslaunch usb_cam usb_cam-test.launch
  • bagファイルを取得する
    全てのトピックを撮る場合(推奨)
$ rosbag record -a

bagファイルの記録が始まったのを確認したら,認識したい物体を撮影します.
できるだけ様々な環境(背景)で,いろいろな角度の物体を撮影しましょう.

  • bagファイルから画像を取得
$ roscd image_view
$ rosmake image_view --rosdep-install
$ sudo apt-get install aptitude

sudo: aptitude: command not foundと出た場合

$ sudo aptitude install mjpegtools

ディレクトリを作ります.

$ mkdir workspace
$ cd workspace
$ source devel/setup.bash

ディレクトリ内でlaunchファイルを作成します.

$ vim export.launch

launchファイルに以下の内容を記述します.

<launch>
   <node pkg="rosbag" type="play" name="rosbag" args="-d 2 /home/masuko/2022-01-12-16-48-01.bag"/>
   <node name="extract" pkg="image_view" type="extract_images" respawn="false" output="screen" cwd="ROS_HOME">
     <remap from="image" to="/image_raw"/>
   </node>
</launch>
~

/home/masuko/2022-01-12-16-48-01.bagの部分は,recordした任意のbagファイルが存在するパスに当てはめてください.
/image_rawの部分は,rosbag infoで確認できます.

$ rosbag info 2022-01-12-16-48-01.bag
中略
topics:      /camera_info                                        838 msgs    : sensor_msgs/CameraInfo               
             /image_raw                                          838 msgs    : sensor_msgs/Image                    
             /image_raw/compressed                               838 msgs    : sensor_msgs/CompressedImage          
             /image_raw/compressed/parameter_descriptions          1 msg     : dynamic_reconfigure/ConfigDescription
             /image_raw/compressed/parameter_updates               1 msg     : dynamic_reconfigure/Config           
             /image_raw/compressedDepth/parameter_descriptions     1 msg     : dynamic_reconfigure/ConfigDescription
             /image_raw/compressedDepth/parameter_updates          1 msg     : dynamic_reconfigure/Config           
             /image_raw/theora                                   841 msgs    : theora_image_transport/Packet        
             /image_raw/theora/parameter_descriptions              1 msg     : dynamic_reconfigure/ConfigDescription
             /image_raw/theora/parameter_updates                   1 msg     : dynamic_reconfigure/Config           
             /image_view/output                                  838 msgs    : sensor_msgs/Image                    
             /image_view/parameter_descriptions                    1 msg     : dynamic_reconfigure/ConfigDescription
             /image_view/parameter_updates                         1 msg     : dynamic_reconfigure/Config           
             /rosout                                             852 msgs    : rosgraph_msgs/Log                     (3 connections)
             /rosout_agg                                         838 msgs    : rosgraph_msgs/Log

作成したlaunchファイルを実行します.

$ roslaunch export.launch
中略
[rosbag-1] process has finished cleanly
log file: /home/masuko/.ros/log/e7529e8c-737a-11ec-aa06-7c7635a4ab69/rosbag-1*.log

取得した画像は,~/.rosディレクトリ内に生成されています.
※500枚程度生成されます.
生成された画像を確認

$ cd ~/.ros
$ ls
frame0000.jpg
...

任意のディレクトリ作成します.
※workspaceは例

$ cd ~/workspace
$ mv ~/.ros/frame*.jpg workspace/

で画像を移動させます.

[参考]:http://wiki.ros.org/ja/rosbag/Tutorials/Exporting%20image%20and%20video%20data

アノテーション(ラベリング)

ここでは,labelImgというアノテーションツールを用います.
labelImgはpascalVOC形式,YOLO形式どちらの形式でもアノテーションできるツールです.
Yolo_Labelというツールもありますが,ここではlabelImgでのアノテーション手順を示していきます.

使用するツール:labelImg
https://github.com/tzutalin/labelImg/tree/98e88371adc0203e170a7aa423e1b22df0570589

Yolo_Labelの場合はこちら:
https://github.com/masuko-shingo/jetson-nano/wiki/%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%84%E3%83%BC%E3%83%ABYolo_Label%E3%82%92%E4%BD%BF%E3%81%86%E5%A0%B4%E5%90%88

アノテーションツールのインストール

pip3のインストール
※pip3が入ってない場合

$ sudo apt install python3-pip
  • アノテーションツールをインストール
    pip3で
$ pip3 install labelImg

※インストールできない場合,こちらのissueを試してください.
url:https://github.com/masuko-shingo/jetson-nano/issues/8

ラベリング

  1. 前項目でインストールができたら,labelImgでツールを起動
$ labelImg

起動時の画面
doc_annotation0_Screenshot from 2022-01-19 14-11-56

2. 「ディレクトリを開く」で,生成したjpg画像が格納されているディレクトリを開いてください.

doc_annotation1_Screenshot from 2022-01-18 14-56-43

  1. YOLO形式でアノテーションを行いたいため,「PascalVOC」を選択して「YOLO」と表示された状態にします.
    doc_annotation2 Diagram drawio

  2. 「矩形を作成する」を選択して矩形(バウンディングボックス)を作成します.
    認識したい物体をドラッグで囲みます.

    doc_annotation2_Screenshot from 2022-01-19 15-06-51

  3. ラベル名を設定します.
    ここでは例としてtb3とします.
    doc_annotation3_Screenshot from 2022-01-19 15-07-02

ラベル名を設定後は,
6. 「保存する」もしくは'ctrl+s'でアノテーション結果を保存します.
doc_annotation4_Screenshot from 2022-01-19 15-07-15

※「表示」の「自動で保存する」にチェックをいれると手間が省けます.

  • 保存したディレクトリにテキストファイルがあるか確認します.
    保存できていれば,ラベル名が記述されているclasses.txtと,画像に対応したtxtファイルが生成されています.
$ cd test/label
$ ls
classes.txt frame0293.txt

YOLO形式のtxtファイルの内容について

# 0 0.373437 0.445833 0.365625 0.562500

最初の数値0は,クラス数を意味している数字であり,0の場合はクラス数が1つ,1の場合はクラス数が2つということになります.
次の4つの数値0.373437 0.445833 0.365625 0.562500は,画像内におけるバウンディングボックスの座標を意味します.
左からx座標,y座標,幅(width),高さ(height)となっています.画像内左上が(x,y)(0,0)になっています.


これで,アノテーション作業は終了です. 次の項目では,学習(トレーニング)に入っていきます.

学習

作成したデータセットで学習させます. これにより,データセットのクラスを認識するモデルが生成されます. まずは,学習を始める準備を行います.

darknet53.conv74のダウンロード

特徴抽出器darknet53.conv74のダウンロードをします.

$ cd ~/yolov3/darknet/build/darknet/x64/
$ wget https://pjreddie.com/media/files/darknet53.conv.74

yolov3.cfgの編集

yolov3.cfgの編集を行います.

  • batch,subdivisionsの設定
    まず,batch,subdivisionsを# Testingから# Trainingに切り替えます.
    文頭のパラメータを編集 (1行〜7行目)
[net]
# Testing
# batch=1
# subdivisions=1
# Training
batch=64
subdivisions=16
...
  • max_batchesの設定
    次に,max_batchesの値を変更します.
    設定する値は,クラス数*2000を目安に変更します.
    ※訓練画像の枚数以上の値となるようにしてください.
    クラス数が1の際(20行目)例:
max_batches = 2000
  • stepsの設定
    次に,stepsの値を変更します.
    設定する値は,max_batchesの0.8倍,0.9倍を目安に変更します.
    クラス数が1の際(20行~22行目)例:
max_batches = 2000
policy=steps
steps=1600,1800
  • width,heightの設定
    次に,width,heightを設定します.
    設定する値は,416か,32の倍数に変更します.
    (8行,9行目)
width=416
height=416
  • [yolo]層のclassesを設定する 3つあるyolo層(推定層)のclassesの値を変更します. クラス数が1の際(610行目)例
[yolo]
mask = 6,7,8
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=1
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1

クラス数が1の際(696行目)例

[yolo]
mask = 3,4,5
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=1
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1

クラス数が1の際(783行目)例

[yolo]
mask = 0,1,2
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=1
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1
  • [yolo]層直前の[convolutional]層,filtersを設定する
    [yolo]層(推定層)直前にある

編集後 yolov3.cfgと同内容の,yolo-obj.cfgファイルを作成します.
※yolov3.cfgの内容をコピーして,yolo-obj.cfgファイルを作成しても問題ありません.

$ vi yolo-obj.cfg

学習を回す

$ ./darknet detector train build/darknet/x64/data/obj.data cfg/yolo-obj.cfg darknet53.conv.74

推論

最後に,自作データセットで学習させたモデルを用いて画像認識を行っていきます. ここは,学習済みモデルを用いた際と同じ流れになります.

参考文献

Yolov3論文: https://arxiv.org/abs/1804.02767

Yolov3サイト: https://pjreddie.com/darknet/yolo/

使用するリポジトリ: https://github.com/AlexeyAB/darknet

ドキュメント

・はじめに
https://github.com/masuko-shingo/jetson-nano/blob/main/README.md
・Jetson Nano環境構築
https://github.com/masuko-shingo/jetson-nano/wiki/Jetsonnano%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89
・実習:SLAM, Navigation(Turtlebot3)
https://github.com/masuko-shingo/jetson-nano/wiki/%E5%AE%9F%E7%BF%92%EF%BC%9ASLAM,-Navigation(Turtlebot3)

⚠️ **GitHub.com Fallback** ⚠️