目次
0. 目的
授業計画 第1~5回 センシング技術とデータ収集(第1・2回 土田修平、第3~5回 宮澤仁)
センシング技術の発達により、人間の五感で感知できる情報、さらに五感では感知できない情報までを収集し、データ化することが可能になった。文化情報工学に活用できるデータ取得の方法としてセンシング技術の原理について学ぶとともに、簡単に使えるセンサを用いて実際に生体情報(第1・2回)や位置情報(第3~5回)を測定しデジタルのデータとして収集してみることを通じて、データ取得の技能を向上させる。(専門知)
→ 今回はPythonを使用しますが、実際にデータ収集にトライすることがメインの目的であるため、Pythonの細かな説明はしません。コードの簡易な説明を基に、骨格情報を抽出するまでの流れ・処理の全体像を掴んでいただければと考えています。尚、土田は全員ができていることを確認してから一つずつ授業を進めていくため、自分で実装進められる人はどんどん進めてもらって構いません。早く終わった人は、是非周りの友達を助けてあげてください!
1. 事前準備
1.1 注意事項の確認
1.1.1 ブラウザの確認
Safari非推奨。
ファイルのアップロード/ダウンロード回りでエラーが発生します。
ChromeやEdgeなどのブラウザの利用をお勧めします。
1.1.2 アカウントログイン
Google Colaboratoryを開いて、自分のアカウントでログインできているかを確認しておいてください。
https://colab.research.google.com/
1.1.3 zipフォルダの取り扱い
Windowsを利用している方は、zipフォルダの解凍の操作が必要なので注意してください(Macはzipフォルダをダブルクリックすれば解凍されます)。解凍せずに操作を進めるとエラーが発生します。
- ファイルまたはフォルダーを解凍 (展開) する zip フォルダーを探します。
- 次のいずれかの操作を行います。
- 1 つのファイルまたはフォルダーを解凍するには、zip フォルダーを開き、中のファイルまたはフォルダーを zip フォルダーから新しい場所にドラッグします。
- zip フォルダーのコンテンツをすべて解凍するには、フォルダーを長押し (または右クリック) して [すべて展開] を選択し、指示に従って操作します。
1.1.4 拡張子の表示
***.zipや***.pngなど、ファイルの種類を表すもので、拡張子は常に表示しておくことを強く推奨します。
- MacのFinder で、「Finder」>「設定」と選択してから、「詳細」をクリックします。
- 「すべてのファイル名拡張子を表示」を選択するか選択を解除します。
- タスク バーの検索ボックスに「エクスプローラー」と入力し、検索結果から [エクスプローラー] を選択します。
- エクスプローラーの [表示] タブの [表示/非表示] グループで、[ファイル名拡張子] チェック ボックスをオンにします。
1.2 ドライブにコピー
次のリンクにアクセスし、「ドライブにコピー」をクリック。
左上のタイトル「YOLOv8 – HumanPoseEstimation のコピー」と表示されたらOK!
1.3 セルの実行
再生ボタンをクリックするか、Shift+Enterを押せばセルを実行できる!
!nvidia-smi を実行。以下のように表示されればOK!(エラーが出た場合は、ランタイムからランタイムタイプをGPUに変更して下さい。よくわからない場合は土田を呼んでください)
1.4 Googleドライブにファイルをアップロード
STEP 0. Googleドライブとは
Googleドライブは、Google社が提供する「クラウドストレージサービス」のこと。
Googleアカウントごとにストレージ(データを永続的に記憶する装置)領域があり、インターネットを介してアクセスする。どのデバイスでも同じGoogleアカウントにログインすれば、ブラウザでファイルを編集したり、ローカルストレージからファイルをアップロードしたり、ローカルストレージにファイルをダウンロードしたりできる。
STEP 1. Dropboxから動画ファイルをフォルダごとダウンロード(AIST Dance Video Databaseの動画を活用)
※「 ダウンロード専用で続行」をクリックで問題ありません
ダウンロードしたzipファイルは解凍しておいてください。
STEP 2. Googleのページにアクセスして、Googleアカウントにログイン
STEP 3. Googleドライブに移動する
STEP 4. ダウンロードした「20240903_video」フォルダをGoogleドライブの「マイドライブ」にアップロード
1.5 Google ColaboratoryにGoogleドライブをマウント
GoogleドライブにアップロードされているファイルをGoogle Colaboratoryで使えるようにする
STEP 0. Google Colaboratoryの見方
STEP 1. 左側のメニューバーにある「ファイル」のアイコンをクリック
STEP 2. 左から3番目のアイコンをクリックしてGoogleドライブをマウント
STEP 3. もし「Googleドライブをマウントするには、このセルを実行してください」というメッセージが表示されて新たなセル(コードのブロック)ができた場合は、このセルを実行する
※ アクセス権は「すべて選択」を選んで続行
STEP 4. 実行結果で Mounted at /content/drive と表示されればOK
(Googleドライブをマウントできない場合)
ダウンロードしたフォルダ内の各ファイルを「ファイル」にドラッグ&ドロップ
1.6 ファイルのパスを取得する
パスとは
このイメージ図を木のような構造で表すと以下のようになる
contentからf0.mp4までのパス(経路)は /content/drive/MyDrive/20240903_video/f0.mp4 になる
STEP 1. ファイル名の右のアイコンをクリックして操作メニューを開き、「パスをコピー」する
2. コードの実行
Y01. YOLOv8をインストール
「Y01. YOLOv8をインストール」をひたすら実行してください。(もしエラーが出たらTAか土田まで)
※ 細かなコードの説明は飛ばします。
- # 1 YOLOv8をダウンロード
ultralytics
というライブラリをインストールして、YOLOv8という画像認識のツールを使えるようにします。
- # 2 必要なライブラリのインストール
- import
csv
とcv2
という便利なツールを使うための準備をします。YOLO
を使うためのインポートも行います。
- import
- # 3 学習モデルの読み込み。姿勢推論用のモデルデータを読み込む
- # 4 keypointの位置毎の名称定義
- 人体の各部位の名前をリストにして定義します(例:鼻、目、肩など)。
- # 5 ビデオライターの設定
- # 6 姿勢情報をCSVファイルに書き出す
- # 7 フレームにキーポイントと骨格を描画する
- # 8 動画をフレームごとに処理し、姿勢情報を取得してCSVと動画に保存する
def関数について
def
で始まる部分は関数と呼ばれます。プログラムの中で特定の作業をまとめて一つにしたものです。
例えば、算数の公式のようなものと考えてください。一度作ってしまえば、何度でも使うことができます。
例え話:クッキー作り
関数を使う便利さを、クッキー作りの例で説明します。
1. クッキーのレシピを一度覚える
クッキーを作るには、レシピがありますよね。材料を混ぜて、オーブンで焼くという一連の手順を一度覚えてしまえば、次からはその手順を思い出しながら何度でもクッキーを作れます。
2. レシピを関数にする
このレシピをプログラムにすると、「def
」という言葉を使って次のように書きます。
※ pint(“~~~”)で文字を実行結果の欄に表示することができます。
def make_cookies():
print("材料を混ぜる")
print("生地を形にする")
print("オーブンで焼く")
3. 簡単にクッキーを作る
一度この「make_cookies」という関数を作れば、クッキーを作りたいときに「make_cookies()」と書くだけで、全ての手順が実行されます。
make_cookies()
関数は、プログラムを簡単に、効率よく、そして理解しやすくするための非常に強力なツールです。
一度使い方を覚えれば、複雑な作業もシンプルにこなせるようになります。
今回、各関数は特定のタスク(ビデオの設定、データの保存、画像への描画)を行っています。
Y02. サンプル動画(sample.mp4)の読み込み
- GoogleDriveマウントの場合
- ファイルパス
/content/drive/MyDrive/20240903_video/sample.mp4
- ファイルパス
- ドラッグ&ドロップの場合
- ファイルパス
/content/sample.mp4
- ファイルパス
(余談)コピー&ペーストのショートカットキーを知らない方は必ずマスターしておいてください。Macなら 「command + C」して「command + V」。Windowsなら「Ctrl+C」して「Ctrl+V」です。その他のショートカットキー「command + X」や「command + F」なども合わせて覚えておくと良いでしょう。
Y03. サンプル動画(sample.mp4)の骨格情報推定
Y03.1 (今回は)fpsを30で統一する
GoogleDriveを無事マウントし、動画をDriveにアップロードした方は、「Y03.1 今回はfpsを30で統一する」を実行してください。
- GoogleDriveマウントの場合
- 実行コマンド
!ffmpeg -y -i "/content/drive/MyDrive/20240903_video/sample.mp4" -vf "fps=30" "sample_30fps.mp4"
- 実行コマンド
- ドラッグ&ドロップの場合
- 実行コマンド
!ffmpeg -y -i "sample.mp4" -vf "fps=30" "sample_30fps.mp4"
- 実行コマンド
ffmpeg
は、動画や音声の編集や変換を行うためのソフトウェアです。
Pythonでは先頭に!
マークをつけることで簡単に呼び出して使えます。
各部分の説明
!ffmpeg
:ffmpeg
コマンドを実行します。ここでの!
は、Jupyter Notebook などの環境でシェルコマンドを実行するためのものです。
-y
:- 上書き確認をせずに既存の出力ファイルを上書きします。
-i "sample.mp4"
:- 入力ファイルを指定します。この場合、
sample.mp4
という名前の動画ファイルを入力として使用する。
- 入力ファイルを指定します。この場合、
-vf "fps=30"
:- ビデオフィルター(
-vf
)を指定します。ここでは、フレームレートを30fps(1秒あたり30フレーム)に変更するフィルターを適用します。
- ビデオフィルター(
"sample_30fps.mp4"
:- 出力ファイルの名前を指定します。この場合、フレームレートを30fpsに変更した動画を
sample_30fps.mp4
という名前で保存します。
- 出力ファイルの名前を指定します。この場合、フレームレートを30fpsに変更した動画を
Y03.2 動画のwidth/height/fpsを取得
動画のFPS、Width、Heightについて
FPS (frames per second):
1秒間に表示される映像のフレーム数。fpsが高いほど動画がスムーズに見える。
例:30fpsは、1秒間に30枚の絵が映し出されることを意味する。
Width:
動画の横の長さ。ピクセルで表される。
例:1920wは、動画の横が1920ピクセルであることを示している。
Height:
動画の縦の長さ。ピクセルで表される。
例:1080hは、動画の縦が1080ピクセルであることを示している。
例えば”1920×1080の動画で30fps”は、
横1920ピクセル、縦1080ピクセルの大きさで、1秒間に30枚の絵が流れる動画ということがわかる。
Y03.3 入力動画のパスと出力ファイルのパスを指定
### Y03.3 入力動画のパスと出力ファイルのパスを指定
input_video_path = '/content/sample_30fps.mp4'
output_video_path = 'sample_30fps_with_pose.mp4'
csv_path = 'sample_30fps_pose_keypoints.csv'
Y03.4 動画を処理し、姿勢情報を取得してCSVと動画に保存
「### Y03.4 動画を処理し、姿勢情報を取得してCSVと動画に保存」のセルを実行!
以下のように表示されていればOKです。
Y03.5 結果確認用動画の作成
Colaboratory上で見れるように動画の形式を変更しています。
Y03.6 動画の再生
実行するとColaboratory上で関節位置の推定結果を確認できます!
Y04. 比較用動画(f0.mp4)の読み込み
マウントできていれば現状ままで大丈夫です。
- GoogleDriveマウントの場合
- ファイルパス
/content/drive/MyDrive/20240903_video/f0.mp4
- ファイルパス
- ドラッグ&ドロップの場合
- ファイルパス
/content/f0.mp4
- ファイルパス
Y05. 比較用動画(f0.mp4)の骨格情報の推定
ここからは「Y03」の繰り返し作業です。ファイル名が変わっただけです。
- Y05.1 (今回は)fpsを30で統一する
- Y05.2 動画のwidth/height/fpsを取得
- Y05.3 入力動画のパスと出力ファイルのパスを指定
- Y05.4 動画を処理し、姿勢情報を取得してCSVと動画に保存
- Y05.5 結果確認用動画の作成
- Y05.6 動画の再生
Y05.7 他の動画(f1.mp4)でも適用してみよう
- Y05.1 ~Y05.6 までの流れとほぼ同じ
- 一つのセルにまとめてみました
- また、ファイル名を自由に決めれるように変数名を自分で決められるようにしています。
- 今回は
f1.mp4
を読み込み込むため、以下のコードになります。 - このファイル名を適切に変更することで、どのような動画にも対応できるかと思います。
# Y05.7.2
# 簡単にするためにファイル名と拡張子を最初に定義
file_name = "f1"
extension = ".mp4"
### Y05.1 今回はfpsを30で統一する
# # ドラッグ&ドロップの場合
# !ffmpeg -y -i {file_name}{extension} -vf "fps=30" {file_name}"_30fps.mp4"
# # Google Driveの場合
!ffmpeg -y -i "/content/drive/MyDrive/20240903_video/"{file_name}{extension} -vf "fps=30" {file_name}"_30fps.mp4"
Y05.7.3では、Y05.7.2のセルを一つのdef関数def get_pose(file_name:str, extension:str):
としてまとめています。(def関数忘れた方はこちら)
これにより、get_pose("f2", ".mp4")
などと書くだけで、骨格推定が実行できるようになります。
Y06. 単位ベクトルに変換
Y06.1 骨格情報が入ったcsvファイルの中身を確認
エクセルの表をイメージしてみましょう!
1行目にデータの名前が入っていて、2行目から座標データが入っています。
各行が1つのフレームに対応しており、各列が人体の各部位の位置とその検出信頼度を示しています。
frame: フレーム番号。この列は、どのフレームの情報かを示しています。
nose_x, nose_y, nose_score: 鼻の位置(画像左上を(0,0)としたときのx座標とy座標)とその検出信頼度(score)。他の部位も同様。x座標とy座標についてはY06.2.0で可視化すれば理解できると思います。
以下の例は、最初のフレーム(frame 0)のデータです。
- frame 0:
- 鼻の位置は (x: 921, y: 107) で、信頼度は 0.989987。
- 左目の位置は (x: 942, y: 90) で、信頼度は 0.958196。
- 右目の位置は (x: 902, y: 89) で、信頼度は 0.972921。
- 左膝の位置は (x: 821, y: 745) で、信頼度は 0.996867。
- …
Y06.2 0フレーム目を可視化
Y06.3 0フレーム目を単位ベクトルに変換(可視化確認用)
なぜ単位ベクトルに変換するのか?
YOLOv8等を用いた2次元骨格推定で2つのダンス動作の差(DTWコスト値 or RMSE値)を計算する際に、単純に骨格座標のユークリッド距離を使用すると問題があります。
ユークリッド距離を使用する問題点
1. 平行移動の影響
画面内で異なる位置で同じ動きをしている場合でも、ユークリッド距離はその位置の違いを大きく反映します。例えば、2人のダンサーが同じ振り付けを画面内の異なる場所で踊っている場合、ユークリッド距離は大きな差があるとして計算してしまいます。
2. 奥行きの影響
2次元骨格推定では、カメラの視点からの深度情報が無視されるため、同じポーズでも撮影距離が異なるとスケールが異なるように見えます。これにより、実際には同じ動作でも、カメラに近い位置で行われた動作は大きく、遠い位置で行われた動作は小さく見えてしまいます。
3. 回転の影響
ダンサーの体の向きが異なる場合(例えば、一人は正面を向いていて、もう一人は斜めを向いている)、ユークリッド距離はその回転の違いを大きく反映してしまいます。残念ながら2次元骨格推定である限り、この影響は無視できません。そのため、2次元骨格推定に基づくダンス動作の差(DTWコスト値 or RMSE値)には、かなり誤差が含まれることを理解しておいてください。
使用画像:ヒップホップ Png vectors by Lovepik.com
Y06.4 全てのフレームを単位ベクトルに変換してcsvファイルに格納
実行するのみ!
# 指定されたディレクトリで関数を実行
transform_to_norm("sample")
transform_to_norm("f0")
transform_to_norm("f1")
transform_to_norm("f2")
Y06.5 変換結果のcsvファイルの中身を確認
単位ベクトルに変換された値がcsvに格納されていることがわかる
Y06.5 変換結果の可視化
0フレーム目の骨格を描き、各関節の動きをベクトルで可視化している。色は紫色から始まり、時間経過に合わせて青色、緑色、黄色、黄白色へと変化していきます。
3. 差(DTWコスト値 or RMSE値)の計算
Y07. 動的時間伸縮法 / DTW (Dynamic Time Warping) を計算
動的時間伸縮法(DTW:Dynamic Time Warping)は、時間とともに変わるデータ(例えばダンスの動き)を比較するための方法です。簡単に言うと、2つのデータのパターンがどれだけ似ているかを調べる方法です。
例えば、2人のダンサーが同じ振り付けを踊っているけれど、1人は少し速く踊り、もう1人は少し遅く踊っているとします。この場合、普通に動きの位置を比較しても、動きが全然違うように見えます。
ここでDTWを使うと、速さの違いを調整して、同じ振り付けかどうかを確認できます。つまり、ダンサーの動きを時間方向に伸ばしたり縮めたりして、同じタイミングの動きがどれだけ似ているかを調べます。ダンスでは、遅どり早どりというように楽曲に対して遅れて動いたり早く動いたりしてしまいがちです。そういった影響を無視して、単に動きの差(DTWコスト or RMSE値)を見たい場合には有効な評価手法です。
(注意)ダンスではリズムが非常に重要です。しかし、DTWは時間方向に伸縮させながら比較するので、リズムの違いを無視してしまっています。厳密にリズムに合わせて踊れているかも確認したい場合は他の手法を採用すべきです。
Y08. 二乗平均平方根誤差 / RMSE(Root Mean Squared Error)を計算する
単純にフレームごとの差分の平方根の総和平均をとっています。これはDTWよりも厳密にタイミングを見ています。ただ、少しでもリズムがずれた踊り方の場合、動き自体は似ていても、RMSEの値は大きくなってしまいます。
Y09. オリジナル動画を読み込んでみよう
【課題】ここまで習ってきた知識を活かしてmihon.mp4
のダンス動画を真似して踊り、自分の動きとの差をDTWで計算してみてください。
以下を提出してください。
- GoogleDrive
- 撮影した動画
- 見本動画(mihon.mp4)の~keypoints.csvファイル
- 見本動画(mihon.mp4)の~keypoints_norm.csvファイル
- アップロードした動画の~keypoints.csvファイル
- アップロードした動画の~keypoints_norm.csvファイル
- DTWコスト値のスクショ画像
- Google スプレッドシート
- DTWコスト値をスプレッドシートに記入してください。
- リアクションペーパー
- 以下の内容を含めてください
- データ収集時に感じた難しい点 or 工夫した点
- 本日の感想、わかりにくかった点、改善してほしい点など
- 以下の内容を含めてください
尚、撮影は2~3名程度でグループになって撮影してもらいます(こちらで当日勝手に決めます)。
(注意)時間が経つとdef関数がリセットされるようでした。その場合は再度セルを実行し、def関数を定義し直してください。
(注意)遅くとも11:30には教室に戻ってこないと提出に間に合わないと思っていた方が良いです。
撮影時の注意点
- 画角の中の人間は1人にすること
- 全身が映るようにすること
- 真正面から撮影すること
- 見本動画に対して左右反転しないように注意すること
おまけ
時間が余った人は「モーションデータをつかったダンス映像制作」のPART04からやってみよう!Processingについて学べます。
プログラミングを学びたい人は以下がオススメかも。
- アルゴ式(情報科学科の学生にオススメされた。Pythonメインです。)
- ドットインストール(自分が学生の頃はこれで基礎を学んでから作りたいもの作っていた。いつの間にか有料多くなってる。が、集中して学びたいなら1月分だけプレミアム枠払って学ぶのもありでは)
- 神戸大の西田先生の講義資料(ブラウザで動くp5.jsについて学べます。Gitについても学べる。)