DataTennis.NET

データテニスドットネット

【OpenCVを使ったスポーツ画像解析1(モーショントラッキング)】テニス選手の移動量や軌跡をデータ化する

公開日:
最終更新日:2018/07/27

      2018/07/27

テニスの4大大会(全豪、全仏、全英、全米)では、選手の総移動量が、データとして記録されサイトで公開されます。

錦織圭は、サーブよりもストローク戦でポイントを稼ぐ選手ですので、この数字が比較的高い傾向があります。
ときにマラソンマンなんて言われたりします。

↓は、全仏オープン マリー錦織戦のstats情報ですが、下から2つが
DISTANCE COVERED (M)、DISTANCE COVERED/PT. (M)とあります。これは、試合のポイント中の総移動距離と、1ポイントあたりの移動距離となります。
相手がマリーなので、あまり数値に差がないですが。

distance-nishikori-murray

こういう情報を、画像処理を使って試合の動画から自動で取得できないか、トライしてみようと思ってます。
4大大会以外でもどんな感じかをみてみたいですし、一般選手のデータ解析にも応用できるかと。

Python(スクリプト言語)+OpenCV(画像処理ライブラリ)+contrib(オプション)
の組み合わせで、↓の動画のように選手の移動をトラッキングするのは簡単にできたりします。

Pythonコードは↓です。
一番最初のフェデラーの位置をバウンディングボックスで指定すれば、そのあとの動きは計算ライブラリが自動でやってくれます。
トラッキングのタイプは、BOOSTING MIL KCF TLD MEDIANFLOW GOTURNの6種類があるのですが、ここでは、MILを使っております。

今後は、移動軌跡を測定したり、選手以外のボールをトラッキングしたりとやっていく予定です。

スポーツ画像解析リンク
・【OpenCVを使ったスポーツ画像解析1】テニス選手の移動量や軌跡をデータ化する
・【OpenCVを使ったスポーツ画像解析2】フェデラー選手の移動軌跡をグラフ化してみました
・【OpenCVを使ったスポーツ画像解析3】選手やテニスボールの移動を自動で検出して移動軌跡をトラッキング
・【OpenCVを使ったスポーツ画像解析4】テニスコートのラインの自動検出
・【OpenCVを使ったスポーツ画像解析5】画像からテニス選手の位置を検出する
・【OpenCVを使ったスポーツ画像解析6】深層学習(ディープラーニング)を用いてテニス選手とボールをトラッキング

■環境
Windows10
Python3.5
OpenCV3.2+contrib

import cv2
import sys
import numpy as np

#トラッキングタイプでMILを選択
tracker = cv2.Tracker_create("MIL")

#videoファイルを読み込む
video = cv2.VideoCapture("aus-tennis.mp4")

# ファイルがオープンできない場合の処理.
if not video.isOpened():
    print ("Could not open video")
    sys.exit()
# 最初のフレームを読み込む
ok, frame = video.read()
if not ok:
    print ('Cannot read video file')
    sys.exit()

# バウンディングボックスの最初の位置とサイズを設定
c,r,w,h = 320,210,70,90
bbox = (c,r,w,h)

roi = frame[r:r+h, c:c+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 30.,32.)), np.array((180.,255.,255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 80, 1)

# 動画の読み込みと動画情報の取得
#movie = cv2.VideoCapture(target) 
fps    = video.get(cv2.CAP_PROP_FPS)
height = video.get(cv2.CAP_PROP_FRAME_HEIGHT)
width  = video.get(cv2.CAP_PROP_FRAME_WIDTH)
# 形式はMP4Vを指定
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
result = "result/test_output.m4v" 
# 出力先のファイルを開く
out = cv2.VideoWriter('output.avi',fourcc,20.0, (int(width), int(height)))
    

    
# バウンディングボックスをフレームに設定
ok = tracker.init(frame, bbox)


while True:
    # フレームを読み込む
    ok, frame = video.read()
    if not ok:
        break
        
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0,180], 1)
    

    # フレームを更新
    ok, bbox = tracker.update(frame)

    # バンディングボックスを描画
    if ok:
        p1 = (int(bbox[0]), int(bbox[1]))
        p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))
        cv2.rectangle(frame, p1, p2, (0,0,255))

    # フレームを画面表示
    cv2.imshow("Tracking", frame)
    
    #読み込んだフレームを書き込み
    out.write(frame)
    

    # ESCを押したら中止
    k = cv2.waitKey(1) & 0xff
    if k == 27 : break
        
video.release()
out.release()
cv2.destroyAllWindows()

 - blog, スポーツ画像解析, データ分析, テニス×テクノロジー