[Japanese/English]
MediaPipe(Python版)を用いて手の姿勢推定を行い、検出したキーポイントを用いて、
簡易なMLPでハンドサインとフィンガージェスチャーを認識するサンプルプログラムです。

本リポジトリは以下の内容を含みます。
- サンプルプログラム
 - 全キーポイント版 サンプルプログラム
 - ハンドサイン認識モデル(TFLite)
 - フィンガージェスチャー認識モデル(TFLite)
 - 全キーポイント版 フィンガージェスチャー認識モデル(TFLite)
 - ハンドサイン認識用学習データ、および、学習用ノートブック
 - フィンガージェスチャー認識用学習データ、および、学習用ノートブック
 - 全キーポイント版 フィンガージェスチャー認識用学習データ、および、学習用ノートブック
 - フィンガージェスチャー認識用学習データの復元再生プログラム
 
- mediapipe 0.8.1
 - OpenCV 3.4.2 or Later
 - Tensorflow 2.3.0 or Later
tf-nightly 2.5.0.dev or later (LSTMモデルのTFLiteを作成する場合のみ) - scikit-learn 0.23.2 or Later (学習時に混同行列を表示したい場合のみ)
 - matplotlib 3.3.2 or Later (学習時に混同行列を表示したい場合のみ)
 
Webカメラを使ったデモの実行方法は以下です。
python app.pyデモ実行時には、以下のオプションが指定可能です。
- --device
カメラデバイス番号の指定 (デフォルト:0) - --width
カメラキャプチャ時の横幅 (デフォルト:960) - --height
カメラキャプチャ時の縦幅 (デフォルト:540) - --use_static_image_mode
MediaPipeの推論にstatic_image_modeを利用するか否か (デフォルト:未指定) - --min_detection_confidence
検出信頼値の閾値 (デフォルト:0.5) - --min_tracking_confidence
トラッキング信頼値の閾値 (デフォルト:0.5) 
全てのキーポイントを追跡するよう改変したデモの実行方法は以下です。
python app_allkeypoints.pyこちらも、app.pyと同じオプションが指定可能です。
│  app.py
│  app_allkeypoints.py
│  keypoint_classification.ipynb
│  point_history_classification.ipynb
│  point_history_classification_allkeypoints.ipynb
│  
│  history_log_show.py
│  
├─model
│  ├─keypoint_classifier
│  │  │  keypoint.csv
│  │  │  keypoint_classifier.hdf5
│  │  │  keypoint_classifier.py
│  │  │  keypoint_classifier.tflite
│  │  └─ keypoint_classifier_label.csv
│  │          
│  └─point_history_classifier
│      │  point_history.csv
│      │  point_history_allkeypoints.csv
│      │  point_history_classifier.hdf5
│      │  point_history_classifier_allkeypoints.hdf5
│      │  point_history_classifier.py
│      │  point_history_classifier_allkeypoints.py
│      │  point_history_classifier.tflite
│      │  point_history_classifier_allkeypoints.tflite
│      │  point_history_classifier_label.csv
│      └─ point_history_classifier_label_allkeypoints.csv
│          
└─utils
    └─cvfpscalc.py
推論用のサンプルプログラムです。
また、ハンドサイン認識用の学習データ(キーポイント)、
フィンガージェスチャー認識用の学習データ(人差指の座標履歴)を収集することもできます。
app.pyの拡張版です。app.pyはジェスチャー認識用データ収集の際に1点(人差し指先)のみの動きに追従、座標の履歴を保存していましたが、本拡張にとって全21点の動きを収集することができます。
この拡張プログラムに合わせて、※の付いた、以下の座標履歴を保存するcsvファイル、ラベルデータ、学習用ノートブック、サンプルモデルが追加、変更されます。
ハンドサイン認識用のモデル訓練用スクリプトです。
1点の座標履歴から、フィンガージェスチャーを認識用するモデルを訓練するスクリプトです。
全キーポイントの座標履歴から、フィンガージェスチャーを認識するモデルを訓練するスクリプトです。(上記の拡張版)
app_allkeypointsで収集したキーポイント座標データ群を読み込み、ウィンドウ上でリプレイ再生するスクリプトです。
ハンドサイン認識に関わるファイルを格納するディレクトリです。
以下のファイルが格納されます。
- 学習用データ(keypoint.csv)
 - 学習済モデル(keypoint_classifier.tflite)
 - ラベルデータ(keypoint_classifier_label.csv)
 - 推論用クラス(keypoint_classifier.py)
 
フィンガージェスチャー認識に関わるファイルを格納するディレクトリです。
以下のファイルが格納されます。
- 学習用データ(point_history.csv)
 - 学習済モデル(point_history_classifier.tflite)
 - ラベルデータ(point_history_classifier_label.csv)
 - 推論用クラス(point_history_classifier.py)
 
以下、全キーポイント版のファイルも格納されます
- 学習用データ(point_history_allkeypoints.csv)
 - 学習済モデル(point_history_classifier_allkeypoints.tflite)
 - ラベルデータ(point_history_classifier_label_allkeypoints.csv)
 - 推論用クラス(point_history_classifier_allkeypoints.py)
 
FPS計測用のモジュールです。
ハンドサイン認識、フィンガージェスチャー認識は、
学習データの追加、変更、モデルの再トレーニングが出来ます。
「k」を押すと、キーポイントの保存するモードになります(「MODE:Logging Key Point」と表示される)

「0」~「9」を押すと「model/keypoint_classifier/keypoint.csv」に以下のようにキーポイントが追記されます。
1列目:押下した数字(クラスIDとして使用)、2列目以降:キーポイント座標

キーポイント座標は以下の前処理を④まで実施したものを保存します。

初期状態では、パー(クラスID:0)、グー(クラスID:1)、指差し(クラスID:2)の3種類の学習データが入っています。
必要に応じて3以降を追加したり、csvの既存データを削除して、学習データを用意してください。
 
 
「keypoint_classification.ipynb」をJupyter Notebookで開いて上から順に実行してください。
学習データのクラス数を変更する場合は「NUM_CLASSES = 3」の値を変更し、
「model/keypoint_classifier/keypoint_classifier_label.csv」のラベルを適宜修正してください。
「keypoint_classification.ipynb」で用意しているモデルのイメージは以下です。

「h」を押すと、指先座標の履歴を保存するモードになります(「MODE:Logging Point History」と表示される)

★ 全キーポイント版のapp_allkeypoints.pyの場合では、プログラム実行直後からジェスチャを認識する状態になり、全点が緑色に光りますが、「h」を押して、保存モードに切り替えてください。
「0」~「9」を押すと「model/point_history_classifier/point_history.csv」に以下のようにキーポイントが追記されます。
★ 全キーポイント版の場合は「model/point_history_classifier/point_history_allkeypoints.csv」に追記されます。
1列目:押下した数字(クラスIDとして使用)、2列目以降:座標履歴(2×16=32列)

(★allkeypointsの場合)
1列目:押下した数字(クラスIDとして使用)、2列目以降:座標履歴(2×21×16=672列)
キーポイント座標は以下の前処理を④まで実施したものを保存します。

★全キーポイント版ではTからT-15までの各時系列番号内にXY座標×21点分のデータが含まれています。
app.pyの初期状態では、静止(クラスID:0)、時計回り(クラスID:1)、反時計回り(クラスID:2)、移動(クラスID:4)の
4種類の学習データが入っています。
必要に応じて5以降を追加したり、csvの既存データを削除して、学習データを用意してください。
 
 
 
★全キーポイント版のプログラムの初期状態では、ポーズ(クラスID:0)、クレシェンド(クラスID:1)、フィニッシュ(クラスID:3)の
3種類の学習データが入っています。
app.py同様、適宜データを追加・削除してください。
(クレシェンド、フィニッシュは、指揮者をイメージした手の動きです)
 
 
「point_history_classification.ipynb」をJupyter Notebookで開いて上から順に実行してください。
学習データのクラス数を変更する場合は「NUM_CLASSES = 4」の値を変更し、
「model/point_history_classifier/point_history_classifier_label.csv」のラベルを適宜修正してください。
「point_history_classification.ipynb」で用意しているモデルのイメージは以下です。

「LSTM」を用いたモデルは以下です。
使用する際には「use_lstm = False」を「True」に変更してください(要tf-nightly(2020/12/16時点))

point_history_classification_allkeypoints.ipynbをJupyter Notebookで開いて上から順に実行してください。 学習データのクラス数を変更する場合は「NUM_CLASSES = 3」の値を変更し、「model/point_history_classifier/point_history_classifier_label_allkeypoints.csv」のラベルを適宜修正してください。
「point_history_classification_allkeypoints.ipynb」で用意しているモデルのイメージは以下です。

「LSTM」を用いたモデルは以下です。
使用する際には「use_lstm = False」を「True」に変更してください。
point_history_classification_allkeypoints.ipynbで学習した結果のモデルを、ONNXファイルで保存できます。
ONNXファイルにすると、Unity内でBarracuda、mediapipeを用いて、ジェスチャ認識モデルとして使うことができます。
詳しくはReferenceをご覧ください。
保存処理はノートブックの中に含まれているので、全てのセルを実行すれば生成されます。
ジェスチャー再現機能 (History_log_show.py)追加
これは、★、app_allkeypoints.pyで収集したデータをリプレイ再生するプログラムです。(app.pyで収集したデータ、ハンドサインには対応していません)
プログラムの実行方法は以下です。
python History_log_show.py実行時には、以下のオプションが指定可能です。
- --start
再生を始めるcsvデータの行番号を指定 (デフォルト:0 (int)) - --end
再生を終えるcsvデータの行番号を指定 (デフォルト:データ行列の最終行(int)) - --pause_time
一つのジェスチャ(16フレーム)を再生するごとに一瞬停止させるか(デフォルト:False (bool))
※視覚的にジェスチャを1回づつ区切れをつけ分かりやすくするため 
1行につきジェスチャの動き1回分のデータがあります
終了する際はEscキーを押して下さい。
- 
ジェスチャデータ(point_history_allkeypoints)と、ジェスチャ認識ラベル(point_history_classifier_label_allkeypoints)読み込み
 - 
ジェスチャデータを16フレーム(1ジェスチャ分)ごとに分割して成型
 - 
そのデータを1フレームづつ描画して表示
 
- row_ID
現在再生しているジェスチャの行番号 - GestureLabel
現在再生しているジェスチャのラベル番号(何のジェスチャをしているか)
=======================================
TODO: -  
"GestureLabel"の文字の横に"???"と表示される現象 
以下に応用事例を紹介します。
- Control DJI Tello drone with Hand gestures
 - Classifying American Sign Language Alphabets on the OAK-D
 
- 手の認識
HandPoseBarracuda - Unity内でのONNXファイルを使った分類
Unity Technologies製推論エンジン Barracudaがスゴイという話 
高橋かずひと(https://twitter.com/KzhtTkhs)
みみすけ名人 mimisukeMaster (https://twitter.com/mimisukeMaster)
hand-gesture-recognition-using-mediapipe is under Apache v2 license.
