ByteTrackの動作環境を構築してMOT評価指標で評価してみる (1) Docker環境構築奮闘記

# 経緯
- 物体追跡の挙動理解（データ構造把握➡設計理念習得に繋がるように），評価方法の勉強
- 環境構築が酷く下手なので練習する．できればデバッガを動かせる状態にして中の挙動を確認することができたら嬉しい
- 別にByteTrackを使いこなすわけではないから，程々に把握すればOKであって時間をかけない

# ByteTrackとは(適宜追加)
カメラ動画のYolox物体検出結果を時系列につなげる複数オブジェクト物体追跡(MOT; Multiple-Object Tracking)アルゴリズムの一つ．(OSS)

物体の動きのみを利用して高いMOT指標を出し, SOTA (State-of-the-Art)を達成している．
発明のポイントは以下：
- 以下の2段階のマッチングを行うことで，track by detectionにおけるdetectionのconfidenceの違いをカバーしている：
    - 1段階目：confidenceの高い検出物体を対象に，IoUあるいはRe-ID(ここでは高(ex:512)次元特徴量ベクトル)による類似度計算
    - 2段階目：confidenceの低い検出物体を対象に，IoUによる類似度計算

https://arxiv.org/abs/2110.06864

https://qiita.com/tomo_v/items/f1b9ab396add42c98d3b

"BYTE"アルゴリズムについて詳しく良く書かれている．：

https://aburaku.hatenablog.com/entry/bytetrack

https://zenn.dev/s4k1/scraps/c04087f619daff

https://speakerdeck.com/nekanat/bytetrack-motr-cvmian-qiang-hui-eccv2022lun-wen-du-mihui-fa-biao-zi-liao?slide=15

他にも，最近では以下のように改善アルゴリズムが提案されている，日本でもホットな分野．
（以下の記事にあるDeepSORTは特によく聞く）

https://zenn.dev/elith/articles/a44d50585d5593

https://tech.acesinc.co.jp/entry/2021/11/24/165628

https://deepsquare.jp/2022/10/bot-sort/


#


# 以下，ByteTrackを動作させるまでの環境構築メモ

先人の試みは以下．環境構築が下手なので頗る不安．

https://blog.shikoan.com/yolox-byte-track/

https://chantastu.hatenablog.com/entry/2022/10/26/000446

一先ず以下から`git clone`した．

https://github.com/ifzhang/ByteTrack

上の記事では`pip venv`で動かしているが，日本人の先人が作ったDockerfileもあった．
手前環境がcondaなのも考慮して，
よくわからない状態でも動かせるDockerの理念を信じて，WSL上で後者からやってみよう．
まず，DockerをWSL2上にインストール．

https://qiita.com/nujust/items/d7cd395baa0c5dc94fc5

https://qiita.com/haveAbook/items/0d0ae20a19214f65e7cd

`docker build`でDockerイメージ作成...と思ったが，
以下のlaunch.json等デバッグ環境構築はかなり面倒そう...
一日いっぱい頑張ってみて，無理だったら前者でいく．
（コード試行のためにOSから入れるのは割に合わないか...）

https://torajirousan.hatenadiary.jp/entry/2021/06/24/180632

https://zenn.dev/piroshiki/articles/8b69c848b61ff5

➡できた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421973/4b1b10a0-f1bc-5be6-6905-0129b0689414.png)

デモを試す．（参照：https://chantastu.hatenablog.com/entry/2022/10/26/000446）
➡CPUだとめちゃくちゃ遅いが，できた！

```bash
$ python tools/demo_track.py video --path videos/palace.mp4 -f exps/example/mot/yolox_x_mix_det.py -c model/bytetrack_x_mot20.tar  --save_result --device cpu
2024-04-09 12:57:43.336 | INFO     | __main__:main:316 - Args: Namespace(aspect_ratio_thresh=1.6, camid=0, ckpt='model/bytetrack_x_mot20.tar', conf=None, demo='video', device=device(type='cpu'), exp_file='exps/example/mot/yolox_x_mix_det.py', experiment_name='yolox_x_mix_det', fp16=False, fps=30, fuse=False, match_thresh=0.8, min_box_area=10, mot20=False, name=None, nms=None, path='videos/palace.mp4', save_result=True, track_buffer=30, track_thresh=0.5, trt=False, tsize=None)
2024-04-09 12:57:46.513 | INFO     | __main__:main:326 - Model Summary: Params: 99.00M, Gflops: 793.21
2024-04-09 12:57:46.515 | INFO     | __main__:main:334 - loading checkpoint
2024-04-09 12:57:57.482 | INFO     | __main__:main:338 - loaded checkpoint done.
2024-04-09 12:57:57.827 | INFO     | __main__:imageflow_demo:248 - video save_path is ./YOLOX_outputs/yolox_x_mix_det/track_vis/2024_04_09_12_57_57/palace.mp4
2024-04-09 12:57:57.852 | INFO     | __main__:imageflow_demo:258 - Processing frame 0 (100000.00 fps)
2024-04-09 12:58:55.766 | INFO     | __main__:imageflow_demo:258 - Processing frame 20 (0.37 fps)
2024-04-09 12:59:48.992 | INFO     | __main__:imageflow_demo:258 - Processing frame 40 (0.38 fps)
...
2024-04-09 13:12:35.535 | INFO     | __main__:imageflow_demo:258 - Processing frame 320 (0.38 fps)
2024-04-09 13:13:00.158 | INFO     | __main__:imageflow_demo:298 - save results to ./YOLOX_outputs/yolox_x_mix_det/track_vis/2024_04_09_12_57_57.txt
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421973/7ae63beb-b038-b634-cec9-c4b18a094eac.png)



GPUだとWSL上にCUDAドライバがないようで，認識しない．

```bash
$ python tools/demo_track.py video --path videos/palace.mp4 -f exps/example/mot/yolox_x_mix_det.py -c model/bytetrack_x_mot20.tar  --save_result
2024-04-09 12:48:53.946 | INFO     | __main__:main:316 - Args: Namespace(aspect_ratio_thresh=1.6, camid=0, ckpt='model/bytetrack_x_mot20.tar', conf=None, demo='video', device=device(type='cuda'), exp_file='exps/example/mot/yolox_x_mix_det.py', experiment_name='yolox_x_mix_det', fp16=False, fps=30, fuse=False, match_thresh=0.8, min_box_area=10, mot20=False, name=None, nms=None, path='videos/palace.mp4', save_result=True, track_buffer=30, track_thresh=0.5, trt=False, tsize=None)
Traceback (most recent call last):
  File "tools/demo_track.py", line 372, in <module>
    main(exp, args)
  ...
  File "/usr/local/lib/python3.8/dist-packages/torch/cuda/__init__.py", line 172, in _lazy_init
    torch._C._cuda_init()
RuntimeError: Found no NVIDIA driver on your system. Please check that you have an NVIDIA GPU and installed a driver from http://www.nvidia.com/Download/index.aspx
```

今回はデバッガ起動がゴールなのでGPUモードは使わない．(Dockerに慣れていない)
時間あるときに入れてみる．多分以下が参考．

https://qiita.com/ryohassay/items/15fab8a72847be13d16d

## デバッガ起動
コマンドライン引数付きPythonプログラムの`launch.json`指定

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python Debugger: Current File",
            "type": "debugpy",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "args": [
                "video",
                "--path",
                "videos/palace.mp4",
                "-f",
                "exps/example/mot/yolox_x_mix_det.py",
                "-c",
                "model/bytetrack_x_mot20.tar",
                "--save_result",
                "--device",
                "cpu"
            ]
        }
    ]
}
```

https://zenn.dev/tfukumori/articles/d968ccafd44a77

➡動いた! かなり嬉しい．
簡単に確認すると，メインプログラムは`tools/demo_track.py`の`main()`．
その中で呼び出され，動画ファイルを読み込んでフレームに分解して処理する関数が`imageflow_demo(predictor,...)`．
その中で，`predictor.inference`と`tracker.update()`を反復する感じ．
`BYTETracker`クラスオブジェクトの`tracker`がした画像のように複数トラックをリストで持つとともに，カルマンフィルタの情報も持っている．`Predictor`クラスもある．
状態ベクトルは8次元？(通常のMOTと同じ?) カルマンフィルタに関する記述：
https://github.com/ifzhang/ByteTrack/blob/main/yolox/tracker/kalman_filter.py

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421973/83429728-111e-c410-a985-9f5f1e2d588d.png)

## MOT指標の評価
以前に公式の評価スクリプトを見たことがある．
中に公式のものが入っていたら一番良いので探す．
まず`README.md`を見たが，記述無し．
`tools/track.py`に`import motmetrics`の記述有．やはり公式っぽいライブラリ`py-motmetrics`を使っていた．
`demo_track.py`では評価無しだった．
評価するためにどうデータを突っ込んでいるかを早期に把握できれば，それで良しとしたいが，
ライブラリの使い方はしっかり理解したいので，`tools/track.py`をREADME.mdに沿って動作させる．
`bytetrack_x_mot20.pth.tar`は以下でダウンロードした．

```python
gdown.download('https://drive.google.com/uc?id=1HX2_JpMOjOIj1Z9rJjoet9XNy_cCAs5U', 'bytetrack_x_mot20.pth.tar', quiet=False)
```
➡またGPUが無いと怒られてしまったので入れる．こちらはマストのようだ．
`nvcc --version`はDockerイメージ上でも認識するが，
`nvidia-smi`はWSL上で認識するがDockerイメージ上では認識しない状態．
具体的な状態がわからない...
(沼ってきた...)

`demo_track.py`の`--device gpu`では`exp.get_model().to(args.device)` (=device(type='cuda'))で以下のエラー．

```bash
Exception has occurred: RuntimeError
Found no NVIDIA driver on your system. Please check that you have an NVIDIA GPU and installed a driver from http://www.nvidia.com/Download/index.aspx
  File "/workspaces/ByteTrack/tools/demo_track.py", line 325, in main
    model = exp.get_model().to(args.device)
  File "/workspaces/ByteTrack/tools/demo_track.py", line 372, in <module>
    main(exp, args)
RuntimeError: Found no NVIDIA driver on your system. Please check that you have an NVIDIA GPU and installed a driver from http://www.nvidia.com/Download/index.aspx
```

`track.py`では，`assert num_gpu <= torch.cuda.device_count()`でAssertionError

```bash
(track.py:332605): Gtk-WARNING **: 03:16:42.513: Locale not supported by C library.
        Using the fallback 'C' locale.
Traceback (most recent call last):
  File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/user/.vscode-server/extensions/ms-python.debugpy-2024.4.0/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 39, in <module>
    cli.main()
  File "/home/user/.vscode-server/extensions/ms-python.debugpy-2024.4.0/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 430, in main
    run()
  File "/home/user/.vscode-server/extensions/ms-python.debugpy-2024.4.0/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 284, in run_file
    runpy.run_path(target, run_name="__main__")
  File "/home/user/.vscode-server/extensions/ms-python.debugpy-2024.4.0/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 321, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "/home/user/.vscode-server/extensions/ms-python.debugpy-2024.4.0/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 135, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/home/user/.vscode-server/extensions/ms-python.debugpy-2024.4.0/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 124, in _run_code
    exec(code, run_globals)
  File "/workspaces/ByteTrack/tools/track.py", line 283, in <module>
    assert num_gpu <= torch.cuda.device_count()
AssertionError
```


ここら辺の気がすると思って，`/etc/docker/daemon.json`を追加したら，dockerそのものが
動かなくなった．泣きたい．

https://qiita.com/tkusumi/items/f275f0737fb5b261a868

nvidia-dockerをインストールして，`docker run --gpus all --rm nvidia/cuda nvidia-smi`する必要があるようだ．

https://qiita.com/ksasaki/items/b20a785e1a0f610efa08

nvidia-dockerをインストールしたら，今度は以下のエラー．加えてなぜか`nvcc`コマンドが通らなくなった...
WSL上のCUDAバージョンと合わせるのが，良いと思うのでWSL上で`sudo apt install nvidia-cuda-toolkit`したが，Windowsでインストールすべきだったか...
もうごちゃごちゃになってきた．


```bash
$ docker run --gpus all --rm nvidia/cuda nvidia-smi
Unable to find image 'nvidia/cuda:latest' locally
docker: Error response from daemon: manifest for nvidia/cuda:latest not found: manifest unknown: manifest unknown.
See 'docker run --help'.
```

タグ指定が必要らしいが，ubuntu22.04に合うタグが無い．もう本題から離れすぎて訳が分からない．
適当なタグで良いかもなので，入れてみたがダメ．

https://alpacatech.hateblo.jp/entry/2023/03/15/180003

https://hub.docker.com/r/nvidia/cuda/tags?page=2&page_size=&name=11.4%20&ordering=

```bash
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2021 NVIDIA Corporation
Built on Thu_Nov_18_09:45:30_PST_2021
Cuda compilation tools, release 11.5, V11.5.119
Build cuda_11.5.r11.5/compiler.30672275_0
```

```bash
$ sudo apt install nvidia-container-toolkit
$ sudo nvidia-ctk runtime configure --runtime=docker
$ sudo systemctl restart docker
$ sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
```

dockerコンテナ外でここまではいけるんだけど，コンテナ内で認識してくれない．
コンテナ内：
```bash
user@85a...a15:/workspaces/ByteTrack$ docker run  --runtime=nvidia --rm nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
bash: docker: command not found
```

コンテナ外：
```bash
$ sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
Unable to find image 'nvidia/cuda:11.6.2-base-ubuntu20.04' locally
11.6.2-base-ubuntu20.04: Pulling from nvidia/cuda
96d54c3075c9: Pull complete
a3d20efe6db8: Pull complete
bfdf8ce43b67: Pull complete
ad14f66bfcf9: Pull complete
1056ff735c59: Pull complete
Digest: sha256:a0dd581afdbf82ea9887dd077aebf9723aba58b51ae89acb4c58b8705b74179b
Status: Downloaded newer image for nvidia/cuda:11.6.2-base-ubuntu20.04
Wed Apr 10 05:45:19 2024
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 510.68.01    Driver Version: 512.59       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  On   | 00000000:01:00.0  On |                  N/A |
| 30%   32C    P8    21W / 170W |    874MiB / 12288MiB |     13%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A        24      G   /Xwayland                       N/A      |
+-----------------------------------------------------------------------------+
```

以下の試行でできた
1点目として，Dockerfileに原因があるだろうと見て下のサイト等を見ながら，
FROM文にhttps://hub.docker.com/r/nvidia/cuda/tags
の内容を入れればよいのか！と気づいた．
以下を加えたところうまくいって，`tools/demo_track.py`を`--device gpu`で動かせた．
やはりバージョンは適当だし，むしろubuntu22.04なのに動いている．

```Dockerfile:Dockerfile
FROM nvidia/cuda:11.4.3-runtime-ubuntu18.04
```

https://zenn.dev/miyatsuki/articles/db220deeb28900

2点目として，nvidiaのruntimeがデフォルトになっていなかった．

https://qiita.com/tsota/items/59948952591fd4a443be

dockerコンテナ内でnvidia-smiコマンドが通っている様子↓
```bash
user@a9c...784:/workspaces/ByteTrack$ nvidia-smi
Wed Apr 10 07:15:58 2024       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 510.68.01    Driver Version: 512.59       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  On   | 00000000:01:00.0  On |                  N/A |
| 30%   38C    P8    21W / 170W |   1207MiB / 12288MiB |      5%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A        24      G   /Xwayland                       N/A      |
+-----------------------------------------------------------------------------+
```

# 次回(T.B.D)
- `tools/track.py`を動かしてMOT評価する
- デバッガを使ってデータ構造を把握する

MOT評価指標については，以下にも使い方が書いてある．
マイフレームの結果を`MOTAccumulator`に蓄積して評価するようだ．
真値GTと推定値の`1-IoU`をスコアとして，bounding boxがかぶらない物体は0点のようだ．

https://tech-blog.optim.co.jp/entry/2021/07/07/100000#py-motmetrics%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9

https://github.com/cheind/py-motmetrics

# 個人の所感
DeepSORTの環境もByteTrackリポジトリ内に入っていた．(`tools/track_deepsort.py`)
これらもGPU環境作って動かしたい．結果的にDockerで構築して良かったことになる．
ただDockerは大がかりで苦手．今後は可能ならば直接Python実行できるならそうした方が良い．
今回は自分がDockerfile頭の`FROM nvcr.io/nvidia/tensorrt:21.09-py3`の意味を理解していなかったように，Dockerfileの1行1行の意味を理解する必要があった．(まだ知識が足りていない)
小規模デバイスにデプロイする用の開発であって，ハイスペックなPCなら不器用な自分は避けた方が良い．
イメージを都度削除しないと，自分のPCストレージが圧迫されそう．

ここまで丸二日かかった．もう少し早くできないものか...
断片的な知識で構築するから穴にはまって時間がかかるのだろう．本を通しで読んで勉強する必要がある(自戒)．