自作の物体検出アプリのFPSを改善したい!
ゲームの動画からユーザー名を黒塗りしたい!と願望からスタートし、処理速度改善のためにVC++にまで手を出したのですが、それだけでは物体検出の処理速度は改善しませんでした。
何か手はないか?と考えを巡らせていたのですが、入力テンソルの形状に無駄があり、対応することで処理速度を約2倍に改善できました。
今は生成AIがホット、物体検出は既に枯れた技術であり"何を今さら"という内容に感じられる方も多いとは思いますが、あまりまとまったものも見かけなかったので、(改善できた嬉しさから)ここに記録しておきます。
結論:入力テンソルを正方形ではなく、入力画像の形状に合わせると効率があがるよ!
詳しい方からは"何を今さら"という声が聞こえてくるようですが、
入力テンソルを正方形ではなく、入力画像の形状に合わせることで物体検出の推論処理の効率が上がり、FPSをあげることが可能です。
精度と処理速度は基本的に相反するものですが、今回は入力テンソルの形状を正方形から長方形に変更することで、精度は従来のまま、処理速度を改善することができました。
入力テンソルと、実際の入力画像の形状
アプリの物体検出には、Ultralytics YOLOv8を利用しています。
デフォルトの入力テンソル(入力解像度)は、imgsz=640
となっています。
これは、640x640を意味しています。
ユーザーのパソコンや設定によってゲームの解像度(≒動画の解像度)は異なりますが、恐らく多いのは1920x1080、大きいものでは4kの3840×2160あたりまでが多くなります。
16:9が多いだろうと思いますが、FF14では横長のゲーム画面とした方が周りをよく目視することができ有利なため、私は2560x1080というかなり横長の画面でプレイしています。
アプリで検出対象としているユーザー名は、入力画像の中ではかなり小さい物体のため、これまでimgsz=1280
(1280x1280)で利用していました。
Ultralytics yolov8では、入力画像の縦と横の大きい方をimgsz
に合わせて縮小してくれるのですが、既に書いた通り、ゲーム画面の多くは横長で、16:9が一番多いと考えられます。
そのため、入力テンソルでは下図のように縮小され推論されますが、特に画像が無い部分も推論するためムダが多いことがわかります。
長方形(矩形)入力テンソル形状の検討
私のアプリの場合、ほとんど16:9の横長のはずなので、1280x720が良いだろう、と考えました。ただyolov8は32ピクセル単位に区切って処理を行っているとのことで、1280x720に一番近い1280x736とすることにしました。
Ultralytics yolov8での学習
学習時にも長方形の入力テンソルとし、長方形のまま学習させます。
results = model.train(data='my_yolov8m1.yaml',epochs=3000,batch=12,device=0,imgsz=[736,1280],rect=True,save_period=10,patience=150
ここで大事な部分は、imgsz=[736,1280]
とrect=True
です。
縮小サイズはリスト[height,width]で指定します。またそのままでは画像がリサイズされて正方形になるらしい(?)のでrect=True
と書いて矩形での学習を指定します。長方形にすることで必要メモリも圧縮できるようです。
ONNX、TensorRTへのエクスポート
ONNXで利用するだけであれば、
model.export(format="onnx",imgsz=[736,1280],half=True)
half=True
でFP16による処理速度改善を狙いします。
出力したONNXからTensorRTに更にエクスポートする場合には、
model.export(format="onnx",imgsz=[736,1280],dynamic=True)
half=True
,dynamic=True
は排他利用のため、ONNXからTensorRTにエクスポートしたい場合にはdynamic=True
とします。
アプリに改善適用結果
アプリに改善を適用した結果、当方の環境(intel 11400F,Geforce4700tiSUPER)では、次のようになりました。
1280x1280 | 736x1280 | |
---|---|---|
ONNX(DirectML) | 16FPS | 34FPS |
TensorRT | 28FPS | 42FPS |
TensorRTが伸び悩んでいるのは、CPUの負荷が100%になっているためで、より良いCPUであれば更に処理速度が伸びるのだろうと思います。
まとめ
カメラなど入力画像のアスペクト比に入力テンソル形状を合わせると、パフォーマンスアップするよ!