1. はじめに
こんにちは!この記事は、ドコモアドベントカレンダー2022の18日目の記事になります。 投稿者はNTTドコモ サービスイノベーション部の春山です。 普段は画像認識AIを用いたスポーツ、自動運転などにおける課題解決を専門としております。
今回のアドベントカレンダー期間はW杯⚽️真っ只中! そして今日はW杯決勝の日!ということでサッカーに関する記事になります! ※昨年もサッカーに関する記事でした。
2. リフティングカウンターを作ろう!
本記事では画像認識AIを使ってリフティングカウンターを作っていきます。目指すものは、リフティングを行なっている動画を解析すると自動でリフティング回数をカウントしてくれるというものです。 ※リフティングとは手以外を使いボールを地面に下ろさずに蹴り続けることです。
今回は、上図のように物体検出と姿勢推定の画像認識技術を使ってリフティングカウンターを作っていきます。
2.1 画像認識AI
まず解析対象となる動画の全フレームに対して物体検出と姿勢推定を行います。 本記事では、画像内からサッカーボールを検出するために物体検出AIを使います。 また、姿勢推定では左右の足首の座標を検出します。 実際にリフティング動画に物体検出と姿勢推定を行なった結果が以下になります。
動画貼り付けができずgifなのでかなりカクカクですが、動画から物体検出と姿勢推定ができていることが確認できます。
2.2 後処理
2.2.1. 足首とボールの中心の距離を算出
足首とボールの中心の距離の算出を行います。まず2.1で物体検出により得られたボールの座標から、ボールの中心の座標を算出します。さらに、このボールの中心と足首との距離を算出します。ここでは、その距離の変動をみることで、リフティングが行われているか地点を特定しようという目論みです。ちなみに、距離の算出対象とする足首はサッカーボールに近い方の足首としています。これは、ボールとの距離が近い足が蹴り足になるだろう、という仮定のもと決めております。 実際に上の動画において、算出した足首とボールの中心の距離のグラフが以下になります。
2.2.2. ノイズ除去(グラフの平滑化)
足首とボールの中心の距離(distance)が小さくなっているところでリフティングが行われていることが推測されます。このグラフから極小値を算出して、その極小値が存在するフレームをリフティングを行なった点としたいところですが、ノイズが乗ってしまっていることが確認できます。時折distanceが300を超えるような高い値を記録していますが、これは人間の頭をボールと誤認識しているため起こってしまっています。このような誤認識に限らず、画像認識AI自体の精度のブレ、また撮影者の手ブレなどからノイズが乗ってしまっているようです。 このノイズを除去するために高速フーリエ変換(FFT)と逆高速フーリエ変換(IFFT)という手法を用います。 FFTはある信号の周波数特性を解析することができ、IFFTでは周波数特性から信号への変換が可能となります。これらをノイズ除去として使う場合は、まず、ある信号にFFTを適用することで周波数特性を解析します。次に、その周波数特性からある周波数帯を作為的にカットしてIFFTすることで、ある信号から特定の周波数帯がカットされた(ノイズ除去)信号を作ることが可能となります。 それでは実際に上記の信号(足首とボールの中心の距離の変動)に対してノイズ除去を行なっていきます。 まずは上記の信号に対してFFTを行った結果が以下になります。
続いて、周波数帯をカットオフします。今回は周波数が0.01 [Hz]を超える部分をカットしました。その結果が以下になります。
続いて、カットオフした周波数帯を用いて元の信号に対してIFFTを行います。その結果が以下になります。
赤線で示しているのがFFTおよびIFFTによりノイズ除去された後の信号となります。 このグラフであれば、極小値を算出することでリフティングを行なったフレームの特定ができそうです。 この赤線の極小値が存在するフレームは以下のように求められました。
[ 77 208 328 468 603 737 846]
つまり、このフレームでリフティングが行われていたことになり、この動画でのリフティング回数は7回となります。 あとはこのフレーム地点でリフティングが行われているとして、回数を動画にプロットするだけです。
2.3 出力結果
動画(gif)の上部にカウントされたリフティング回数をプロットしております。
このようにしっかりとリフティングカウントができていることが確認できました。
2.4 コード
ここでは、本手法の主な部分であった、FFTおよびIFFTによるノイズ除去のコードを記載いたします。
import numpy as np import matplotlib.pyplot as plt from scipy.signal import argrelmin ### 足首とボールの中心の距離を取得(今回は予め保存済み) data = np.load('tests/distance.npy') N = len(data) # フレーム数 dt = 1 # サンプリング周期 t = np.arange(0, N*dt, dt) # 時間軸 ### 高速フーリエ変換(FFT) F = np.fft.fft(data) amp = 150 # 振幅 # FFTの複素数結果を絶対値に変換 F_abs = np.abs(F) # 振幅をもとの信号に揃える F_abs_amp = F_abs / N * 2 # 交流成分 F_abs_amp[0] = F_abs_amp[0] / 2 # 直流成分 # 横軸のデータ作成 fq = np.linspace(0, 1.0/dt, N) # 周波数軸 ### IFFTによるノイズ除去 fc = 0.01 # カットオフの周波数 F[(fq > fc)] = 0 # カットオフを超える周波数のデータをゼロにする # カットオフした周波数でIFFT F_ifft = np.fft.ifft(F) # IFFT F_ifft_real = F_ifft.real # 実数部の取得 # IFFT後の信号から極小値が存在するフレーム番号を算出 arg_r_min,arg_r_max=argrelmin(F2_ifft_real),argrelmax(F2_ifft_real) print(arg_r_min[0])
最終行による出力は以下になります。
[ 77 208 328 468 603 737 846]
3. まとめ
本記事では、自動でリフティング回数をカウントしてくれる、リフティングカウンターを作ってみました。リフティングには頭や肩、膝などを使ったり、テクニカルなやり方もあります。今回はそこまでの対応はできておらず、足先を使うことを前提としていました。今後は、打撃音と紐づけるなど拡張を行っていきたいと思います。
今回作ったリフティングカウンターように、画像認識技術である物体検出と姿勢推定を組み合わせて行うことで様々な解析が可能となります。この組み合わせ次第で従来難しかった課題が解決できるかもしれません。サッカーだけではなく、バスケットボール、テニス、卓球、ゴルフなど応用先は様々考えられます。 NTTドコモでは画像認識AIを適用したゴルフスイング解析アプリ「GOLFAI」をリリースしています。
また、NTTドコモでは、ドコモ画像認識プラットフォームにて、本記事で扱った物体検出、姿勢推定にとどまらず、一般物体認識、特定物体認識、文字認識、類似画像検索、顔認証技術を提供しております。 もちろん、上で述べたようなスポーツに限らず、様々な領域にも応用できる技術となっています。 少しでも気になった方が是非↓リンクへアクセスしてみてください。
4. 参考文献
高速フーリエ変換(FFT)、逆高速フーリエ変換(IFFT): momonoki2017.blogspot.com