ジャストエイサー

https://github.com/jyogi-web/yanbaru-back-mediapipe

Flask

TypeScript

Azure

Python

JavaScript

エイサーでJust Dance!

Yanai

KOU050223

RiTa

推しアイデア

サブデバイスを使用した没入感!!

作った背景

サークル内でJust Danceが流行っていたので

推し技術

mediapie pose類似度判定

プロジェクト詳細

概要

エイサーの踊りでダンスゲーム!

画面左側に表示されるお手本動画に合わせて踊ろう! mediapipeの画像認識を用いてカメラからキャプチャしたダンスの類似度を算出&NintendoSwitchのJoyconで太鼓を叩く動作を検出し、スコア化! 極上の没入感を提供します

7曲のダンスゲームを収録!

  • 島人ぬ宝
  • ダイナミック琉球
  • 睡蓮花
  • マル・マル・モリ・モリ
  • ハレ晴れユカイ
  • オドループ

大まかな流れ

  1. 事前にお手本動画からフレーム毎に骨格ランドマークを抽出し、JSON形式で保存 ⇩
  2. ゲーム中、カメラでキャプチャしたプレイヤーの骨格ランドマークと該当するフレームのお手本の骨格ランドマークを比較し、類似度を判定 ⇩
  3. 類似度が閾値を超えたときに類似度を元にスコアを加算する

ダンスの類似度判定の流れ

  1. 比較するランドマーク座標(お手本とプレイヤーのもの)を相対座標に変換

画面のどの位置にいるかではなく、「頭に対して手がどこにあるか、足がどこにあるか」という各ランドマーク同士の相対的な位置が重要

相対座標に変換する関数

姿勢推定から得られたランドマークのデータを入力することで12の点(右肩)からの相対座標を出力する

function getRelativeLandmarks(landmarks) { if (!landmarks || landmarks.length === 0) { console.error("ランドマークが正しく取得されていません"); return []; // エラー回避のために空の配列を返す } const baseLandmark = landmarks[12]; // 基準座標 return landmarks.map(landmark => ({ x: landmark.x - baseLandmark.x, y: landmark.y - baseLandmark.y, })); }

⇩ 2. ダンスの類似度をcos類似度(角度を用いた類似度)で算出

ダンスのポーズ検出において、ランドマーク同士の距離ではなく、角度が重要。同じ距離でも角度が違えば全く違うポーズになってしまう。

cos類似度

コサイン類似度はベクトル同士の向きの類似度であり角度が近いほど1になり遠いほど-1になる。ここでは、各ランドマーク毎にコサイン類似度を算出し、平均をとり、コサイン平均類似度を出している。

function calculateCosineSimilarity(landmarks1, landmarks2) { let dotProduct = 0; let norm1 = 0; let norm2 = 0; for (let i = 0; i < landmarks1.length; i++) { const x1 = landmarks1[i].x; const y1 = landmarks1[i].y; const x2 = landmarks2[i].x; const y2 = landmarks2[i].y; dotProduct += (x1 * x2) + (y1 * y2); norm1 += (x1 * x1) + (y1 * y1); norm2 += (x2 * x2) + (y2 * y2); } return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2)); }

以上を毎フレーム繰り返してお手本との類似度をとります

使用技術

  • NAGO
    • NintendoSwitch Joycon
    • Azure
    • get_landmark_fps.py(自作)
    • OpenCV

get_landmark_fps

動画を読み込ませ、fpsを指定するだけで各フレームのランドマーク座標を保存したJSONファイルを作成する。これによりゲームで踊れるダンスを簡単に増やせる汎用的なプログラムになった。

import cv2 import mediapipe as mp import json import os import time # Mediapipeのポーズモジュールを初期化 mp_pose = mp.solutions.pose pose = mp_pose.Pose() # 見本動画から骨格ランドマークを抽出し、保存 def extract_and_save_landmarks(video_path, save_path, target_fps=60): cap = cv2.VideoCapture(video_path) landmarks_data = [] frame_interval = 1.0 / target_fps prev_time = time.time() while cap.isOpened(): ret, frame = cap.read() if not ret: break current_time = time.time() if current_time - prev_time >= frame_interval: # mediapipeで骨格検出 frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = pose.process(frame_rgb) if results.pose_landmarks: frame_landmarks = [] for landmark in results.pose_landmarks.landmark: frame_landmarks.append({ 'x': landmark.x, 'y': landmark.y, 'z': landmark.z, 'visibility': landmark.visibility }) landmarks_data.append(frame_landmarks) prev_time = current_time cap.release() # JSONファイルとして保存 with open(save_path, 'w') as f: json.dump(landmarks_data, f) # 見本動画の骨格ランドマークを抽出して保存 extract_and_save_landmarks('app/static/video/sample.mp4', 'app/static/landmarks/sample_landmarks.json')

リポジトリ

AzureのFunctions用 https://github.com/jyogi-web/yanabaru-Functions 使うのをやめた 将来的には使いそう

joyconの代わり用 https://github.com/jyogi-web/yanbaru-react-pwa

joycon https://github.com/jyogi-web/yanbaru-back-joycon

mediapipe https://github.com/jyogi-web/yanbaru-back-mediapipe

yanbaru-back-mediapipe

  • mediapipe
  • flask

yanbaru-back-joycon

  • pyjoycon
  • flask

yanbaru-react-pwa&yanabaru-Functions

  • DeviceMotionEvent
  • React
  • Static web app
  • SignalR Service←今回は諦めた

将来的発展

別の視点

  • ダンスではなく型にはめる
  • スポーツ(ダーツや武術など)
  • リハビリセンター
  • 歩き方や介護の医療の方面

お手本

  • youtubeなどのURLを指定することまたは自分で動画をUPすることで自分の踊りたいダンスで踊れる
  • 取得した骨格情報からオリジナルの3Dモデルに躍らせる

プレイの様子(開発中)

1. スタート・リセット・カメラ関係 2. 判定・スコア 3. プレイヤーランドマーク表示 4. お手本映像&ランドマーク表示

image

ゲーム内容

カメラ映像の上にランドマークが表示されたらスタートボタンを押してゲームスタート!

  • ランドマークが表示されない場合はカメラリセットボタンを押してください
  • 体全体が写っていないと測定不可
  • フレーム毎に類似度によって五段階評価
    • Excellent !!
    • Great !
    • Good
    • Safe
    • Bad

Joyconの代案

bluetooth接続して、楽しようとしたらデプロイしたら無理だと気づきました。 他のデバイス(ラズパイ)などを使ってAzure IoT HubやAzure IoT Centralなどのクラウドサービスと連携すれば、JoyconのBluetooth接続でも可能かなと....

使用技術

  • DeviceMotionEvent
  • React
  • Static web app

https://red-grass-08143c200.5.azurestaticapps.net/ ↑スマホで「リクエストを許可」をすると値が取れます。 スコアに関しては取れるのを確認したかっただけなのでめちゃくちゃな値が取れます 加速度は取れましたけど、連携が少し手間取ったので今後連携したいなと思います。

Xcodeと仲良くなれなかったのでWebで実装をしました...

インフラ構成図

今回の構成図 image

Azureの提供するリアルタイムプッシュ通信を提供するAzureSignalRを使ってみたかったですけど、時間がなくて断念... 今後挑戦してみてもおもしろいのかなと思ってます

アイディア

元ネタ https://www.youtube.com/watch?v=DxpzZ96LxjE

毎日部室で部員がこんな激しいダンスを踊っていますw

参考 https://qiita.com/Killinneko/items/58b4377ba03da7a9c037

Yanai

@Yanai1005