最近, YOLOv5, YOLOXやDetectron2などを少し触る機会があったので, YOLOv5に続き今回はYOLOXについて少しまとめておく.
1. インストール[1]
以前使っていたYOLOv3では, Darknetと呼ばる機械学習フレームワークが使われていて, 使うにはソースコードのビルドから始める必要があった.
しかし, YOLOXは前回紹介したYOLOv5同様にPyTorchベースとなっており, 導入は至って簡単になっていた.
git clone https://github.com/Megvii-BaseDetection/YOLOX cd YOLOX pip3 install -v -e .
また, 学習済みモデルはGitHubのBencmarkの各モデルのweightsからダウンロードできる.
2. 推論
2.1 まずは動かす[1]
YOLOX/toolsにある demo.py を使うことで簡単に試すことができる.
demo.pyの主な使い方:
usage: YOLOX Demo! [-h] [-expn EXPERIMENT_NAME] [-n NAME] [--path PATH] [--camid CAMID] [--save_result] [-f EXP_FILE] [-c CKPT] [--device DEVICE] [--conf CONF] [--nms NMS] [--tsize TSIZE] [--fp16] [--legacy] [--fuse] [--trt] demo positional arguments: demo demo type, eg. image, video and webcam optional arguments: -h, --help show this help message and exit -expn EXPERIMENT_NAME, --experiment-name EXPERIMENT_NAME -n NAME, --name NAME model name --path PATH path to images or video --camid CAMID webcam demo camera id --save_result whether to save the inference result of image/video -f EXP_FILE, --exp_file EXP_FILE please input your experiment description file -c CKPT, --ckpt CKPT ckpt for eval --device DEVICE device to run our model, can either be cpu or gpu --conf CONF test conf --nms NMS test nms threshold --tsize TSIZE test img size --fp16 Adopting mix precision evaluating. --legacy To be compatible with older versions --fuse Fuse conv and bn for testing. --trt Using TensorRT model for testing.
実際に, asset/dog.jpgに対して試してみる.
$ python tools/demo.py image -n yolox-m -c weights/yolox_m.pth --path assets/dog.jpg --conf 0.25 --nms 0.45 --tsize 640 --save_result --device gpu 2022-08-06 18:12:19.988 | INFO | __main__:main:259 - Args: Namespace(camid=0, ckpt='weights/yolox_m.pth', conf=0.25, demo='image', device='gpu', exp_file=None, experiment_name='yolox_m', fp16=False, fuse=False, legacy=False, name='yolox-m', nms=0.45, path='assets/dog.jpg', save_result=True, trt=False, tsize=640) 2022-08-06 18:12:20.338 | INFO | __main__:main:269 - Model Summary: Params: 25.33M, Gflops: 73.76 2022-08-06 18:12:23.475 | INFO | __main__:main:282 - loading checkpoint 2022-08-06 18:12:23.634 | INFO | __main__:main:286 - loaded checkpoint done. 2022-08-06 18:12:23.689 | INFO | __main__:inference:165 - Infer time: 0.0458s 2022-08-06 18:12:23.690 | INFO | __main__:image_demo:202 - Saving detection result in ./YOLOX_outputs/yolox_m/vis_res/2022_08_06_18_12_23/dog.jpg
実行結果は, YOLOX_outputs/yolox_m/vis_res/<実行日時>の下に保存される.
[実行結果]
このdemo.pyは, videoファイルやWebCamに対応しているので, ちょっとYOLOXを試すには便利である.
また, videoファイルやWebCamの場合に, 結果をファイルではなく画面表示にしたい場合, --save_resultオプションをはずせばよいようである.
2.2 プログラムに組み込む
hubconf.pyをみるとtorch.hub.load()でモデル読み込みできそうである.
以下のようなコードで少し試してみたが, モデルから返されるものが何を表しているのか, まだ理解できていない.
tools/demo.pyのコード内でも, モデルからの戻り値をdecoderやpostprocessといった処理で最終的な結果を求めるいるようなので, そのあたりのコードを読むのが早いかも...
[コード]
from PIL import Image import torch from torchvision import transforms model = torch.hub.load('Megvii-BaseDetection/YOLOX', 'yolox_m') model.eval() size = 640 mean = (0.485, 0.456, 0.406) std = (0.229, 0.224, 0.225) transform = transforms.Compose([ transforms.Resize((size, size)), transforms.ToTensor(), transforms.Normalize(mean, std) ]) # Images path = './assets/dog.jpg' img = Image.open(path) img = transform(img) img = img.unsqueeze(0) print(img.size()) img = img.cuda() # Inference outputs = model(img) print(len(outputs[0])) for i, o in enumerate(outputs[0]): print(o) if i > 5: break
[実行結果]
$ python test.py Using cache found in /home/aska/.cache/torch/hub/Megvii-BaseDetection_YOLOX_main torch.Size([1, 3, 640, 640]) 8400 tensor([7.6943e+00, 9.3128e+00, 1.2603e+01, 1.2553e+01, 7.9179e-06, 1.0559e-01, 1.7156e-03, 1.7036e-03, 6.0711e-04, 1.5599e-03, 7.1275e-04, 1.8696e-03, 1.4855e-03, 6.7176e-04, 5.1386e-02, 1.9798e-03, 1.8498e-02, 3.0284e-03, 3.7629e-03, 6.7058e-03, 2.8468e-03, 3.4253e-03, 4.2198e-03, 5.8339e-04, 3.2932e-03, 1.8269e-03, 1.8186e-03, 5.0404e-04, 1.7456e-03, 5.2425e-03, 7.6647e-03, 5.1070e-03, 9.7925e-03, 3.3584e-03, 5.3853e-03, 1.1997e-03, 5.0846e-03, 2.1916e-03, 6.6734e-03, 4.8659e-03, 1.7003e-02, 7.2317e-03, 1.3732e-03, 1.2921e-02, 2.8179e-03, 1.5988e-03, 3.3012e-03, 7.8191e-04, 3.7639e-03, 2.4020e-03, 3.1916e-03, 7.9135e-04, 7.8313e-04, 5.7559e-04, 1.0090e-03, 2.4977e-04, 6.8479e-04, 5.4240e-04, 1.1124e-03, 1.6486e-03, 7.0233e-04, 1.9160e-02, 1.6596e-03, 3.9372e-03, 5.1253e-04, 7.8131e-04, 1.5905e-03, 2.9914e-03, 1.7840e-03, 6.2621e-04, 7.2095e-04, 4.9870e-04, 2.8188e-03, 2.2828e-03, 2.3395e-03, 6.2264e-04, 2.4125e-03, 1.6030e-03, 4.4610e-03, 5.8182e-03, 2.2958e-03, 1.8902e-03, 1.7898e-03, 2.3416e-03, 9.0996e-04], device='cuda:0', grad_fn=<UnbindBackward0>) tensor([2.2949e+01, 8.5213e+00, 4.2867e+01, 1.2101e+01, 1.7648e-06, 1.6438e-02, 1.5249e-03, 5.2015e-03, 3.6679e-04, 2.0792e-03, 3.4202e-03, 6.6716e-03, 4.2036e-03, 8.7390e-04, 5.3193e-02, 2.0351e-03, 2.8528e-02, 3.8327e-03, 5.1659e-03, 2.4324e-03, 2.4824e-03, 3.2313e-03, 3.4182e-03, 6.1571e-04, 5.8827e-03, 3.8910e-03, 3.0409e-03, 8.1738e-04, 2.2858e-03, 1.8199e-03, 3.1528e-02, 1.0869e-03, 5.4345e-03, 3.0550e-03, 7.7136e-03, 1.1963e-03, 7.6420e-03, 1.1206e-03, 4.5149e-03, 6.2085e-03, 1.1080e-02, 1.0567e-02, 1.7915e-03, 9.5486e-03, 1.3000e-03, 5.8328e-04, 2.3635e-03, 3.8680e-04, 5.5275e-03, 1.1935e-03, 4.6446e-03, 4.6616e-04, 6.0694e-04, 7.5986e-04, 9.7805e-04, 2.1388e-04, 5.4047e-04, 5.6278e-04, 2.6507e-03, 3.6365e-03, 1.2007e-03, 1.2623e-02, 2.2846e-03, 4.2138e-03, 8.9710e-04, 1.0120e-03, 1.1891e-03, 4.4692e-03, 1.2388e-03, 5.6764e-04, 8.1628e-04, 7.2471e-04, 1.7150e-03, 3.6226e-03, 2.1823e-03, 7.0995e-04, 3.7664e-03, 2.1221e-03, 3.5067e-03, 7.2453e-03, 2.3956e-03, 1.4497e-03, 1.4111e-03, 2.8024e-03, 7.5300e-04], device='cuda:0', grad_fn=<UnbindBackward0>) tensor([3.0990e+01, 4.6883e+00, 1.5855e+01, 6.4811e+00, 1.4170e-05, 8.6946e-03, 1.2113e-03, 2.4587e-03, 1.3645e-04, 4.6962e-04, 2.0894e-03, 3.8880e-03, 1.1078e-03, 8.3650e-04, 2.1454e-02, 8.7250e-04, 3.3684e-02, 2.1571e-03, 1.2821e-03, 2.1637e-03, 2.9243e-03, 2.1645e-03, 1.9676e-03, 4.2340e-04, 2.8897e-03, 4.2441e-03, 1.8476e-03, 7.2218e-04, 2.6540e-03, 2.5790e-03, 8.7263e-02, 2.1359e-03, 3.4852e-03, 2.0922e-03, 1.2078e-02, 3.7539e-04, 2.7293e-03, 1.1292e-03, 2.2371e-03, 2.1612e-03, 1.0905e-02, 6.9181e-03, 2.5917e-03, 1.1423e-02, 9.4351e-04, 1.2758e-04, 3.7867e-04, 9.0897e-05, 1.2057e-03, 2.9571e-04, 2.7592e-03, 4.7380e-04, 4.9917e-04, 2.9768e-04, 5.5765e-04, 1.4890e-04, 3.1898e-04, 3.0378e-04, 2.9442e-03, 3.0063e-03, 7.6892e-04, 3.8691e-03, 6.6299e-04, 4.7491e-03, 4.2853e-04, 2.8883e-04, 5.0121e-04, 2.0367e-03, 3.5951e-04, 3.5951e-04, 4.9021e-04, 4.5855e-04, 5.2348e-04, 1.7271e-03, 8.1902e-04, 4.5790e-04, 1.2905e-03, 5.4477e-04, 1.7166e-03, 1.5913e-02, 1.8985e-03, 6.5737e-04, 6.5588e-04, 1.7405e-03, 1.8999e-04], device='cuda:0', grad_fn=<UnbindBackward0>) tensor([2.5376e+01, 4.0762e+00, 1.3846e+01, 6.1333e+00, 1.0600e-05, 2.0251e-02, 5.3332e-03, 4.4227e-03, 8.3353e-04, 5.5645e-04, 2.9111e-03, 5.4296e-03, 2.3911e-03, 1.7596e-03, 1.5120e-02, 1.1515e-03, 2.9016e-02, 2.9078e-03, 2.1932e-03, 3.3128e-03, 5.6649e-03, 4.7033e-03, 5.1827e-03, 6.0941e-04, 2.9631e-03, 5.5180e-03, 2.2740e-03, 1.5990e-03, 2.5645e-03, 4.6219e-03, 5.4289e-02, 4.2163e-03, 1.9492e-03, 4.6035e-03, 8.7890e-03, 4.4365e-04, 2.5614e-03, 1.3223e-03, 1.9735e-03, 9.8936e-04, 9.4190e-03, 1.1180e-02, 4.6972e-03, 9.9733e-03, 9.8692e-04, 2.3109e-04, 4.8360e-04, 8.4651e-05, 4.5905e-04, 2.4309e-04, 4.6909e-03, 5.8992e-04, 4.0057e-04, 2.4423e-04, 3.1995e-04, 1.4784e-04, 1.6616e-04, 2.4884e-04, 1.9574e-03, 1.5605e-03, 7.3846e-04, 4.1165e-03, 1.1137e-03, 5.2221e-03, 6.2287e-04, 5.9351e-04, 8.5668e-04, 3.2289e-03, 6.6670e-04, 4.5442e-04, 4.8352e-04, 5.8179e-04, 4.9103e-04, 2.5232e-03, 1.5868e-03, 7.7611e-04, 1.5224e-03, 6.4201e-04, 1.9740e-03, 3.9136e-02, 2.2274e-03, 6.2510e-04, 9.0220e-04, 1.4826e-03, 1.0536e-04], device='cuda:0', grad_fn=<UnbindBackward0>) tensor([4.3150e+01, 5.2217e+00, 5.9237e+01, 8.0409e+00, 4.6026e-05, 7.6650e-03, 9.3881e-03, 3.0306e-03, 1.1037e-03, 3.5843e-04, 1.7287e-03, 2.4262e-03, 1.5754e-03, 1.3448e-03, 8.0362e-03, 9.1478e-04, 2.5736e-02, 1.7464e-03, 1.1918e-03, 3.3403e-03, 9.0058e-03, 8.1845e-03, 4.9690e-03, 6.9315e-04, 1.5067e-03, 1.8837e-03, 1.8848e-03, 1.2245e-03, 1.9018e-03, 5.0851e-03, 5.8064e-02, 6.4580e-03, 3.6262e-03, 4.4940e-03, 1.1461e-02, 5.8232e-04, 2.1260e-03, 1.3372e-03, 2.8567e-03, 4.3420e-04, 6.0142e-03, 1.1562e-02, 4.4855e-03, 9.3040e-03, 8.6017e-04, 1.7465e-04, 3.5207e-04, 4.3454e-05, 1.4765e-04, 1.3268e-04, 4.6232e-03, 1.3393e-03, 3.8129e-04, 3.6249e-04, 5.2603e-04, 1.2832e-04, 1.4509e-04, 2.6718e-04, 3.4162e-03, 1.9768e-03, 7.0401e-04, 2.6826e-03, 8.2029e-04, 4.2563e-03, 1.0339e-03, 7.0778e-04, 9.0938e-04, 2.5714e-03, 8.2799e-04, 2.9149e-04, 5.7309e-04, 7.6391e-04, 3.5676e-04, 1.6000e-03, 1.0712e-03, 5.4328e-04, 1.4536e-03, 4.8885e-04, 6.1925e-03, 7.7357e-02, 1.5593e-03, 5.5400e-04, 1.8614e-03, 1.3672e-03, 1.0399e-04], device='cuda:0', grad_fn=<UnbindBackward0>) tensor([4.3672e+01, 4.9796e+00, 5.4695e+01, 8.4110e+00, 4.2378e-05, 3.7152e-02, 7.2609e-03, 5.4186e-03, 1.0996e-03, 2.2893e-04, 1.7855e-03, 9.0443e-04, 1.2738e-03, 1.1458e-03, 4.6043e-03, 6.0362e-04, 1.4263e-02, 1.2580e-03, 8.3318e-04, 4.5226e-03, 1.4170e-02, 1.1542e-02, 3.8123e-03, 6.7803e-04, 5.9718e-04, 8.6085e-04, 1.2595e-03, 8.8931e-04, 9.2011e-04, 5.9601e-03, 4.6583e-02, 1.3595e-02, 5.1310e-03, 2.8466e-03, 6.3721e-03, 2.6255e-04, 5.3050e-04, 2.0953e-03, 2.9236e-03, 1.3605e-04, 2.4887e-03, 4.1262e-03, 1.8811e-03, 3.5800e-03, 1.8986e-03, 2.8937e-04, 1.0560e-03, 3.5190e-05, 6.7044e-05, 8.9578e-05, 7.0565e-03, 1.4208e-03, 3.8181e-04, 3.7486e-04, 3.1603e-04, 9.5690e-05, 1.1850e-04, 2.8025e-04, 2.8111e-03, 1.6525e-03, 8.7420e-04, 3.0143e-03, 1.0234e-03, 3.6514e-03, 1.8194e-03, 1.1660e-03, 7.7848e-04, 6.1609e-03, 1.1899e-03, 3.2464e-04, 1.4838e-03, 9.0994e-04, 4.4033e-04, 1.6511e-03, 6.7473e-04, 5.1200e-04, 1.0060e-03, 3.7450e-04, 1.8343e-02, 1.2636e-01, 2.7297e-03, 2.9586e-04, 6.5780e-03, 1.4009e-03, 1.1390e-04], device='cuda:0', grad_fn=<UnbindBackward0>) tensor([4.5466e+01, 5.0685e+00, 4.0250e+01, 7.7549e+00, 3.9817e-05, 2.4447e-02, 6.0872e-03, 4.5984e-03, 1.0590e-03, 1.9622e-04, 1.8204e-03, 6.7255e-04, 8.0434e-04, 1.2053e-03, 4.2662e-03, 3.8003e-04, 8.0306e-03, 8.9485e-04, 1.2357e-03, 2.7095e-03, 1.2295e-02, 8.6489e-03, 2.7488e-03, 5.9257e-04, 3.3415e-04, 6.6812e-04, 9.6260e-04, 5.4891e-04, 4.9030e-04, 3.9388e-03, 2.7665e-02, 1.5951e-02, 3.5841e-03, 4.0708e-03, 2.7535e-03, 1.6875e-04, 2.2656e-04, 1.7948e-03, 2.1046e-03, 1.0515e-04, 1.3151e-03, 2.4002e-03, 1.1338e-03, 1.6914e-03, 1.5343e-03, 5.7032e-04, 2.4214e-03, 3.9016e-05, 7.5202e-05, 8.6900e-05, 8.9044e-03, 1.2577e-03, 4.8342e-04, 4.1056e-04, 4.2154e-04, 8.7507e-05, 1.0438e-04, 2.5445e-04, 2.7925e-03, 1.3228e-03, 8.0930e-04, 6.8353e-03, 1.8464e-03, 3.6939e-03, 3.0071e-03, 3.2028e-03, 7.8906e-04, 1.8844e-02, 2.8863e-03, 5.0880e-04, 2.3517e-03, 1.8288e-03, 6.0317e-04, 2.4827e-03, 7.6710e-04, 5.8524e-04, 1.2037e-03, 5.4698e-04, 6.6327e-02, 1.3798e-01, 4.9280e-03, 2.5574e-04, 7.5485e-03, 1.0157e-03, 8.8340e-05], device='cuda:0', grad_fn=<UnbindBackward0>))
現状では, プログラムにYOLOXを組み込んで利用する場合, tools/demo.pyをベースに改良するのが早そうである.
プログラムでの利用という点では, YOLOv5に比べかなり使いにくそうな感じである.
最後に, 少し面白そうな記事[2]を見つけたので, 紹介しておく.
qiita.com
----
参照URL:
[1] GitHub - Megvii-BaseDetection/YOLOX
[2] YOLOシリーズの速度比較をしてみました - Qiita