プログラミング言語:Python
フレームワーク:pygame , OpenCV , media pipe , dilb, imutils , numpy , itertools , collections等
次の「ジェスチャーゲーム」の作成に向けてプログラムの組み方を学び、機械学習でできる範囲を知るため。
機械学習における画像認識と学習させたモデルの推論。
「最初はグー、じゃんけんポン」の合図で、ユーザーの手の形をコンピュータ側が(グー or チョキ or パーを)認識し、その結果(勝ち or 負け)かによって以下のようなあっち向いてほいの処理を行う。
1:勝ち → ユーザー:手、コンピュータ側:ランダム値を出して、ユーザーの手の上下左右を認識。
2:負け → ユーザー:顔、コンピュータ側:ランダム値を出して、ユーザーの手の上下左右を認識。
・未経験の状態から約1か月という短い製作期間の中で二人で製作したので、pythonやpygame、dlibの構造を知ることができたが手の認識におけるtensorflowの推論の部分は別プログラムに任せっきりで、理解することが厳しかった。
・じゃんけんのテストケース
MLP(多層パーセプトロン)を使って、手のランドマークデータを処理。
※以下、a.py(モデルの定義と推論)
このソースコードは、手のランドマークデータを用いた手のジェスチャー認識モデルをTensorFlowを使用して訓練し、保存、評価、推論、TensorFlow Lite形式への変換を行う一連の処理を行っています。具体的な処理内容を以下に説明します。
import csv
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split
csv
: CSVファイルの操作用ライブラリ。numpy
: 数値計算ライブラリ。tensorflow
: TensorFlowライブラリ。sklearn.model_selection.train_test_split
: データセットを訓練用とテスト用に分割するための関数。
RANDOM_SEED = 42
dataset = 'C:/Users/p-user/project/hand-gesture-recognition-using-mediapipe-main/hand-gesture-recognition-using-mediapipe-main/model/keypoint_classifier/keypoint.csv'
model_save_path = 'C:/Users/p-user/project/hand-gesture-recognition-using-mediapipe-main/hand-gesture-recognition-using-mediapipe-main/model/keypoint_classifier/keypoint_classifier.keras'
NUM_CLASSES = 4
RANDOM_SEED
: 乱数のシード値を設定し、再現性を確保。dataset
: ランドマークデータが保存されているCSVファイルのパス。model_save_path
: 訓練後のモデルを保存するパス。NUM_CLASSES
: クラス数を設定(ここでは4クラス)。
X_dataset = np.loadtxt(dataset, delimiter=',', dtype='float32', usecols=list(range(1, (21 * 2) + 1)))
y_dataset = np.loadtxt(dataset, delimiter=',', dtype='int32', usecols=(0))
X_train, X_test, y_train, y_test = train_test_split(X_dataset, y_dataset, train_size=0.75, random_state=RANDOM_SEED)
X_dataset
: ランドマークデータ(入力データ)を読み込み。y_dataset
: ラベルデータ(出力データ)を読み込み。train_test_split
: データを訓練用とテスト用に分割。
model = tf.keras.models.Sequential([
tf.keras.layers.Input((21 * 2, )),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(20, activation='relu'),
tf.keras.layers.Dropout(0.4),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(NUM_CLASSES, activation='softmax')
])
- シーケンシャルモデルを定義。
- 入力層は42次元(21個のランドマーク×2次元)。
- 隠れ層にはドロップアウト層と全結合層を配置。
model.summary() # tf.keras.utils.plot_model(model, show_shapes=True)
- モデルの構造を表示。
cp_callback = tf.keras.callbacks.ModelCheckpoint(
model_save_path, verbose=1, save_weights_only=False)
es_callback = tf.keras.callbacks.EarlyStopping(patience=20, verbose=1)
- モデルチェックポイント: 訓練中にモデルを保存。
- 早期停止: 訓練の早期停止を設定。
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
- モデルをコンパイル。
- 最適化関数はAdam、損失関数は
sparse_categorical_crossentropy
。
model.fit(
X_train,
y_train,
epochs=1000,
batch_size=128,
validation_data=(X_test, y_test),
callbacks=[cp_callback, es_callback]
)
- モデルを訓練。
- 訓練データと検証データを設定し、コールバックを使用。
val_loss, val_acc = model.evaluate(X_test, y_test, batch_size=128)
- テストデータを使用してモデルを評価。
model.save(model_save_path)
model = tf.keras.models.load_model(model_save_path)
- 訓練後のモデルを保存し、再度ロード。
predict_result = model.predict(np.array([X_test[0]]))
print(np.squeeze(predict_result))
print(np.argmax(np.squeeze(predict_result)))
- テストデータの一部を使って推論を行い、結果を表示。
tflite_save_path = 'C:/Users/p-user/project/hand-gesture-recognition-using-mediapipe-main/hand-gesture-recognition-using-mediapipe-main/model/keypoint_classifier/keypoint_classifier.tflite'
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quantized_model = converter.convert()
open(tflite_save_path, 'wb').write(tflite_quantized_model)
- モデルをTensorFlow Lite形式に変換し、量子化。
- 変換したモデルを保存。
interpreter = tf.lite.Interpreter(model_path=tflite_save_path)
interpreter.allocate_tensors()
# 入出力テンソルを取得
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
interpreter.set_tensor(input_details[0]['index'], np.array([X_test[0]]))
# 推論実施
interpreter.invoke()
tflite_results = interpreter.get_tensor(output_details[0]['index'])
print(np.squeeze(tflite_results))
print(np.argmax(np.squeeze(tflite_results)))
- TensorFlow Liteインタープリターを初期化し、テンソルを割り当て。
- 入力テンソルにデータをセットし、推論を実行。
- 結果を表示。
この一連の処理により、手のランドマークデータを使用して手のジェスチャーを分類するモデルを訓練し、TensorFlow Lite形式に変換して軽量化されたモデルを使って推論を行うことができます。
model/point_history_classifier
フィンガージェスチャー認識に関わるファイルを格納するディレクトリです。
また以下のファイルが格納されます。
学習用データ(point_history.csv)
学習済モデル(point_history_classifier.tflite)
ラベルデータ(point_history_classifier_label.csv)
推論用クラス(point_history_classifier.py)
dlibを使って顔の向き(yaw、pitch、roll)を推定。
・動画等
https://tpsxai.com/raspberrypi_tensorflow_lite/
https://github.com/Kazuhito00/hand-gesture-recognition-using-mediapipe?tab=readme-ov-file
{最適化関数 Adamについて}
https://qiita.com/Fumio-eisan/items/798351e4915e4ba396c2
{正規化と標準化について}
https://qiita.com/yShig/items/dbeb98598abcc98e1a57
{顔の向き、dlibについて}
https://qiita.com/oozzZZZZ/items/1e68a7572bc5736d474e
https://pyimagesearch.com/2017/04/03/facial-landmarks-dlib-opencv-python/