プロ野球選手のスイングをPythonで骨格解析する方法|MediaPipe入門【コード付き】

スイング解析

前回の記事「森下翔太の22号ホームランをAIで骨格解析してみた」を読んで、「自分でもやってみたい」と思った方向けの手順解説です。

使うのはGoogleが無料公開している姿勢推定ライブラリ「MediaPipe」。Pythonが少し書ければ、テレビ中継の映像から選手の関節33点の動きをデータ化できます。特別なカメラも有料ソフトも不要です。

必要なもの

  • Python(3.9〜3.12あたり)が動くPC
  • 解析したいスイングの動画クリップ(数秒でOK)
  • ライブラリ4つ(下記コマンドで一発)

pip install mediapipe==0.10.14 opencv-python scipy matplotlib

MediaPipeはバージョン指定がおすすめです。0.10.14までは学習済みモデルが同梱されていて、インストールするだけで動きます(最新版はAPIが変わりモデルの別途ダウンロードが必要)。

ステップ1: 映像を用意する

数秒のスイングクリップを用意します。ここで解析精度の8割が決まるので、ポイントを押さえてください。

  • アングルが命。 打者を真横〜斜めから捉えたカットがベスト。センターカメラ(投手側からの正面)でも解析できますが、腰が捕手と重なって精度が落ちます
  • 体全体が映っていること。 足元が切れているとステップや重心の解析ができません
  • スローリプレイは宝。 フレームあたりの動きが小さくなり、追跡が安定します

なお、放送映像そのものやスクリーンショットをブログ等に掲載するのは著作権的にNGです。映像はあくまで「解析の入力」として使い、公開するのは自分で描いたグラフや骨格図だけにしましょう。

ステップ2: 骨格を抽出する

基本の流れは「動画を1フレームずつ読む → MediaPipeに渡す → 関節座標を保存」です。骨組みはこれだけ。

import cv2

import mediapipe as mp

pose = mp.solutions.pose.Pose(

    static_image_mode=True,      # 1フレームずつ独立検出(小さい被写体に強い)

    model_complexity=1,

    min_detection_confidence=0.3,

)

cap = cv2.VideoCapture(“swing_clip.mov”)

while True:

    ok, frame = cap.read()

    if not ok:

        break

    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    result = pose.process(rgb)

    if result.pose_landmarks:

        # 33個の関節座標(x, y, 信頼度)が取れる

        landmarks = result.pose_landmarks.landmark

ここで実戦上の重要テクニックを3つ。私が実際にハマったポイントです。

① 打者の周辺だけ切り出して拡大する。 中継映像だと打者は画面の一部にしか映っておらず、そのままでは検出率が上がりません。frame[y:y+h, x:x+w]で打者周辺をクロップし、2倍程度に拡大してからMediaPipeに渡すと検出率が劇的に改善します。私の場合、全体のままだと検出3%だったのが、クロップ+拡大で65%まで上がりました。

② スマホの縦動画は回転に注意。 iPhoneの画面収録などは回転情報がメタデータに入っており、OpenCVはそれを無視して横向きで読み込みます。frame.shapeを確認して、幅と高さが逆ならcv2.rotate()で補正しましょう。

③ 信頼度(visibility)でゴミを弾く。 各関節には0〜1の信頼度が付いてきます。0.5未満の点は誤検出が多いので、集計から除外するのが基本です。

ステップ3: データをグラフにする

関節座標の時系列が取れたら、あとは料理次第です。私の記事で使っている指標は:

  • 肩幅・腰幅の変化 — 正面カメラでは体が開くほど見かけの幅が広がるので、「開き」の代理指標になります
  • 手首の移動速度 — 座標を時間微分するだけ。ピークがほぼインパクトのタイミングです
  • 連続骨格図(キノグラム) — 構え→始動→回転→インパクト→フォローの5局面の骨格を並べた図。matplotlibで関節を線で結ぶだけで作れて、完全な自作画像なので著作権もクリーンです

座標の生データはノイズが乗るので、scipyのsavgol_filter(サビツキー・ゴレイフィルタ)で平滑化してから微分するのがコツです。

正直な限界も知っておく

MediaPipeの出力は2D座標です。カメラに対して奥行き方向の回転は精度が出ません。また、テレビ中継の実効フレームレート(30〜60fps)では、腰と肩の回転開始の数十ミリ秒の差を測るのは分解能的に厳しい。

「測れること」と「測れないこと」を区別して発信するのが、データ解析ブログの信頼の根っこだと思っています。

まとめ

  1. pip install mediapipe==0.10.14 opencv-python scipy matplotlib
  2. 横〜斜めアングルのクリップを用意
  3. クロップ+拡大で検出率を上げて骨格抽出
  4. visibilityでフィルタして、平滑化してからグラフ化

環境構築からグラフ1枚目まで、慣れれば30分もかかりません。お気に入りの選手のスイングを数字で眺めると、野球観戦の解像度が一段上がりますよ。

解析しながら試合を見るなら、録画でコマ送り確認ができるスカパー!プロ野球セットが個人的にはおすすめです。スマホ中心ならDAZNでも十分楽しめます。


本記事のコードは自由に使ってください。解析結果を公開する際は、放送映像の転載にならないようご注意を。

「スコアの向こう側」は、データ解析で野球観戦がもっと面白くなるブログです。

コメント

タイトルとURLをコピーしました