mmposeで骨格推定
上記の記事では、パドックで競走馬が歩いている動画を骨格推定して、過去のパドックと比較して当日の調子を推定する、というもの。
自分がやりたいなーと思っているのは、デビュー前2歳馬の馬体写真から骨格推定して、過去の活躍馬の骨格と比較して、今後活躍する馬をピックアップするというやつ。POG向けに面白そう。
ということで、ここで使用されているmmposeを試してみる。
Getting StartedのInstallationに従ってデモが動くところまで進める。今回はローカルのJupyterLabで。
まずmmposeインストールでめちゃめちゃ苦労したので、ポイントだけ。
- mmposeが依存するmmengine、mmcv、mmdet(mmdetはデモスクリプトで使用されている)のインストールが必要
- このうちmmcvは使用しているCUDAやPyTorchのバージョンにあわせてインストール時の指定を変える必要がある。
- ここがうまくできていないと
No module named ‘mmcv._ext’
でコケる。 - mmcvはPyTorchのパッケージ名のバージョンを見ているため、PyTorchのインストールから意識する必要がある
- ここがうまくできていないと
- このうちmmcvは使用しているCUDAやPyTorchのバージョンにあわせてインストール時の指定を変える必要がある。
- mmpose、mmcv、mmdetはバージョンを揃える必要がある。
- それぞれ大きなバージョンアップにより、それぞれが2系統のバージョンを持っている。
- mmpose v1.xの場合は、mmcv v2.X、mmdet v3.Xを使用する必要がある
- 依存パッケージが新しすぎてもダメだったり、とか、依存パッケージが他のパッケージのバージョンに追いついてないとかもある、とかで、どの組み合わせが最適なのかよくわからない。
- mmdetなんかは
AssertionError: MMCV==2.2.0 is used but incompatible. Please install mmcv>=2.0.0rc4, <2.2.0
とかでコケる。 - mmcvを古いバージョンにしてやると
No module named ‘mmcv._ext’
でコケる。 - mmdetのソースを一部修正、上記のバージョンチェック部分を甘めにして回避した。
- mmdetなんかは
- Colab向けチュートリアルのnotebookがあるが、どうも内容が古そう。
- 2024/05/23時点でColabのCUDAは12.2だが、notebookは11.8想定、mmcvが対応しているのは12.1までっぽい。
-
cu121
に書き換えれば動く
-
- mmcvのインストールの箇所で1時間ぐらいかかる。
- 2024/05/23時点でColabのCUDAは12.2だが、notebookは11.8想定、mmcvが対応しているのは12.1までっぽい。
ただ、あまりにも色々躓いたので記憶がやや不確か&推測も多分に含まれるし、あくまでもこの流れでたまたま動いた一例、というメモなのでご注意。
環境
- Python-3.11.4
- CUDA 11.8
- 仮想環境を作成、その中でJupyterLabを起動して実施。
%%bash
# check NVCC version
nvcc -V
echo
# check GCC version
gcc --version
echo
# check python version
python --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2022 NVIDIA Corporation
Built on Wed_Sep_21_10:33:58_PDT_2022
Cuda compilation tools, release 11.8, V11.8.89
Build cuda_11.8.r11.8/compiler.31833905_0
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Python 3.11.4
PyTorchのインストール
もう覚えてないけどwheelは確かビルドに必要だったはず。
%%bash
pip install -U pip wheel
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
バージョンを確認する。
!python -c 'import torch;print(torch.__version__);print(torch.version.cuda)'
2.3.0+cu118
11.8
この+cuXXX
をmmcvが見ているらしく、普通にPyTorchをインストールすると以下のようになるが、これだとダメらしい。
2.3.0
mmengine/mmcv/mmdetのインストール
推奨されているのはMIMという、OpenMMプロジェクト全体で推奨されているパッケージ/モデル管理ツールでのインストールだけど、これだとうまくいかなかったのでpipでやる。(MIM自体はモデルのダウンロードとかでは便利に使えるので後でインストールする)
重要なのは、使っているCUDA/PyTorchのバージョンに合わせて、mmcvをインストールするというところ。それぞれのバージョンも指定したほうが確実な気がするけど、一応今回はこれで動いたということで。
!pip install mmengine
!pip install mmcv -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.3.0/index.html
!pip install mmdet
実際にインストールされたバージョンは以下。
- mmengine-0.10.4
- mmcv-2.2.0
- mmdet-3.3.0
インストールできたらまずmmcvが動作するかを確認。
from mmcv.ops import get_compiling_cuda_version, get_compiler_version
print('cuda version:', get_compiling_cuda_version())
print('compiler information:', get_compiler_version())
以下のように表示されればOK。ここがダメならNo module named ‘mmcv._ext’
になるので、インストール手順が間違っていないかを確認。間違ってなければ、いっそCUDAのバージョンを変えるなりして再度PyTorch/mmcvのインストールをやり直したほうが良いかもしれない。
cuda version: 11.8
compiler information: GCC 9.3
で、mmdet内でmmcvのバージョンを見ているところがある。自分の場合は以下のパスだった。
(snip)
mmcv_minimum_version = '2.0.0rc4'
mmcv_maximum_version = '2.2.0'
(snip)
assert (mmcv_version >= digit_version(mmcv_minimum_version)
and mmcv_version < digit_version(mmcv_maximum_version)), \
f'MMCV=={mmcv.__version__} is used but incompatible. ' \
f'Please install mmcv>={mmcv_minimum_version}, <{mmcv_maximum_version}.'
(snip)
mmcv_maximum_version
を2.2.1
あたりにしておく。
mmposeのインストール
mmposeはソースからインストールする
!git clone https://github.com/open-mmlab/mmpose.git
%cd mmpose
!pip install -r requirements.txt
!pip install -v -e .
mmposeの確認。
# Check MMPose installation
import mmpose
print('mmpose version:', mmpose.__version__)
バージョンが表示されればOK。
mmpose version: 1.3.1
デモ
ではデモを動かす。デモを動かすためにはコンフィグとチェックポイントが必要になる。MIMを使ってダウンロードする。
!pip install -U openmim
!mim download mmpose --config td-hm_hrnet-w48_8xb32-210e_coco-256x192 --dest .
デモで使われている画像はクローンしたレポジトリ内に含まれている。この画像。
デモ用のスクリプトを動かす。
!python demo/image_demo.py \
tests/data/coco/000000000785.jpg \
td-hm_hrnet-w48_8xb32-210e_coco-256x192.py \
td-hm_hrnet-w48_8xb32-210e_coco-256x192-0e67c616_20220913.pth \
--out-file vis_results.jpg \
--draw-heatmap
出力されたファイルを表示
from IPython.display import Image
display(Image("./vis_results.jpg"))
Pythonコードだとこう。
from mmpose.apis import inference_topdown, init_model
from mmpose.utils import register_all_modules
register_all_modules()
config_file = 'td-hm_hrnet-w48_8xb32-210e_coco-256x192.py'
checkpoint_file = 'td-hm_hrnet-w48_8xb32-210e_coco-256x192-0e67c616_20220913.pth'
model = init_model(config_file, checkpoint_file, device='cuda:0') # or device='cpu'
# please prepare an image with person
batch_results = inference_topdown(model, 'tests/data/coco/000000000785.jpg')
print(batch_results)
keypointsが骨格部分のデータっぽい。
[<PoseDataSample(
META INFORMATION
ori_shape: (425, 640)
pad_shape: (256, 192)
input_center: array([320. , 212.5], dtype=float32)
input_scale: array([ 800. , 1066.6666], dtype=float32)
input_size: (192, 256)
dataset_name: 'coco'
flip_indices: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]
img_path: 'tests/data/coco/000000000785.jpg'
img_shape: (425, 640)
batch_input_shape: (256, 192)
DATA FIELDS
gt_instance_labels: <InstanceData(
META INFORMATION
DATA FIELDS
) at 0x7643fa6a1190>
pred_instances: <InstanceData(
META INFORMATION
DATA FIELDS
keypoints: array([[[365.83334 , 83.333336],
[374.16666 , 75.00001 ],
[357.5 , 75.00001 ],
[390.83334 , 75.00001 ],
[357.5 , 83.333336],
[407.5 , 108.333336],
[365.83334 , 116.66667 ],
[440.83334 , 150. ],
[349.16666 , 158.33333 ],
[449.16666 , 166.66667 ],
[307.5 , 175. ],
[440.83334 , 208.33333 ],
[399.16666 , 216.66667 ],
[432.5 , 283.33334 ],
[374.16666 , 275. ],
[474.16666 , 366.66666 ],
[407.5 , 341.66666 ]]], dtype=float32)
keypoint_scores: array([[0.9376108 , 0.93626845, 0.90840936, 0.95710725, 0.91465086,
0.92970216, 0.8663161 , 0.8555557 , 0.9187598 , 0.9389664 ,
0.9539192 , 0.883909 , 0.89276993, 0.92668873, 0.88967854,
0.8596858 , 0.9045249 ]], dtype=float32)
keypoints_visible: array([[0.9376108 , 0.93626845, 0.90840936, 0.95710725, 0.91465086,
0.92970216, 0.8663161 , 0.8555557 , 0.9187598 , 0.9389664 ,
0.9539192 , 0.883909 , 0.89276993, 0.92668873, 0.88967854,
0.8596858 , 0.9045249 ]], dtype=float32)
bbox_scores: array([1.], dtype=float32)
bboxes: array([[ 0., 0., 640., 425.]], dtype=float32)
) at 0x7643f5d82f50>
gt_instances: <InstanceData(
META INFORMATION
DATA FIELDS
bboxes: array([[ 0., 0., 640., 425.]], dtype=float32)
bbox_scales: array([[ 800. , 1066.6666]], dtype=float32)
bbox_scores: array([1.], dtype=float32)
) at 0x7643fa6a0e50>
) at 0x7643fa6a0790>]
というかこれでまだスタートラインだから。。。
参考)