物体検出を用いてジャグリング(3ボールカスケード)の回数をカウントする

はじめに

WFHの気分転換でたまにジャグリングをしていて、これ最近の物体検出技術を使えば回数をカウントする仕組みが割と簡単に作れるのでは?と思ったので試しに動画から3ボールカスケードの回数をカウントする仕組みを作成しました。

実施手順

以下の手順で実施しました。

  1. 動画からボールの座標をyolov5を用いて抽出
  2. 抽出した座標を元にカウントロジックを作成

1. yolov5を用いた物体検出

公式にあるyolov5の学習済みデータにはsports ballというラベルが含まれているので、それを用いてボールの位置の検出を行います。 学習済みモデルを使うのであれば公式チュートリアルに従って git cloneしてsourceのファイルを差し替えるだけでできます。 物体検出後の動画はこんな感じ

youtu.be

人がperson、ボールがsports ballというクラスで検出されていることがわかります。 良く見ると手元に近い位置だと赤いボールはapple、黄色いボールはbananaと誤判定されていたりします。

2. カウントロジック作成

物体検出時に実行するdetect.pyの引数に--save-txtとつけることで下記のようなフレームごとの座標を得ることができます。

f:id:rmizutaa:20210121161601p:plain

ここで得られる5つの列はそれぞれ所属クラス、x軸の中心点、y軸の中心点、幅、高さを示します。また、値は0-1の間に正規化されています。 所属クラス0がperson、32がsports ballにあたります。

参考:https://github.com/ultralytics/yolov5/wiki/Train-Custom-Data

このデータを用いて回数をカウントするロジックを考えます。

横軸をフレーム番号、縦軸をy座標としてプロットすると以下のようになりました。

f:id:rmizutaa:20210121160946p:plain

青色のラインがsports ballの中心点、オレンジ色のラインがpersonの上限点になります。 特徴としては、人の体と重なっている部分は検出されないケースが多いですが、頂点近くの放物線は割と正確に検出できていそうです。 そのため今回は最も高い位置にあるボールのy座標が2回連続で上昇、その後2回連続で下降したタイミングを検知したら1回とカウントすることにしてみます。 このロジックを適用すると、回数がカウントされるタイミングは図の赤線部分となりました。

f:id:rmizutaa:20210121161005p:plain

このロジックで良い感じにカウントができていそうです。 確認のためカウントを動画の左下に表示した結果が以下になります。動画は0.25倍速です。

youtu.be

まとめ

yolov5を使って3ボールカスケードの回数をカウントする仕組みを作成しました。 ここではうまくいったサンプルを紹介しましたが、学習済みモデルをそのまま使っているので精度にはやや問題があります。 例えばボールの色によってはうまく物体検出ができません。私は5色のボールを所持していて今回は赤、黄、銀のボールを使用したのですが、青や黒のボールを用いた時は検出がうまく行えませんでした。良く見ると銀のボールも赤や黄に比べると少し検出精度が悪かったりします。 また、体と重なる部分も検出がうまくできていないので、ボールを高くあげないケースではうまくカウントができませんでした。 このあたりを改善したい場合はデータセットを集めてfine tuningする必要がありそうかなと思っています。

使用したコードはこちらになります。