fixed some errors, dynamic fine

main
Eliza Moscovskaya 4 months ago
parent dcbb1b535b
commit b051f2a658

@ -163,6 +163,7 @@ DYNAMIC_GESTURE = {
| Название | Описание | Ссылка | Количество примеров | Классы | | Название | Описание | Ссылка | Количество примеров | Классы |
|----------|----------|--------|---------------------|--------| |----------|----------|--------|---------------------|--------|
| **special_gestures_v1** | Набор фотографий для распознавания специальных жестов (домик, крест, none). Собран с помощью `capture_photo.py` и стоковых изображений, размечен через `annotate.py`. | [Скачать](https://disk.yandex.ru/d/F25kMjrmZ8xwRA) | 77 (после балансировки, 13 на класс dome/cross, 51 none) | `dome`, `cross`, `none` | | **special_gestures_v1** | Набор фотографий для распознавания специальных жестов (домик, крест, none). Собран с помощью `capture_photo.py` и стоковых изображений, размечен через `annotate.py`. | [Скачать](https://disk.yandex.ru/d/F25kMjrmZ8xwRA) | 77 (после балансировки, 13 на класс dome/cross, 51 none) | `dome`, `cross`, `none` |
| **dynamic_data_v1** | csv файл с последовательностью точек скелета для 14 кадров | [Скачать](https://disk.yandex.ru/d/hnm6apfuxJsEyw) | 81 (по 20 на махи правой и левой рукой, 61 на none) | `none`, `wave_left`, `wave_right` |
## Модели ## Модели
| Название | Тип | Архитектура / параметры | Вход | Выход | Точность (test) | Precision / Recall (по классам) | Ссылка | Распознаваемые жесты | | Название | Тип | Архитектура / параметры | Вход | Выход | Точность (test) | Precision / Recall (по классам) | Ссылка | Распознаваемые жесты |
@ -170,3 +171,4 @@ DYNAMIC_GESTURE = {
| **special_gestures_mlp** | MLP (scikit-learn) | Скрытые слои: (64, 32), активация ReLU, Adam, early stopping, 500 эпох | 99 нормализованных координат скелета (33 точки × 3) | 3 класса (dome, cross, none) | **0.56** | **dome**: P=0.00, R=0.00<br>**cross**: P=0.00, R=0.00<br>**none**: P=0.60, R=0.90 | [Скачать](https://disk.yandex.ru/d/I1WyAfN3PJM9fw) | `dome` (руки над головой домиком)<br>`cross` (предплечья скрещены на груди)<br>`none` (остальные) | | **special_gestures_mlp** | MLP (scikit-learn) | Скрытые слои: (64, 32), активация ReLU, Adam, early stopping, 500 эпох | 99 нормализованных координат скелета (33 точки × 3) | 3 класса (dome, cross, none) | **0.56** | **dome**: P=0.00, R=0.00<br>**cross**: P=0.00, R=0.00<br>**none**: P=0.60, R=0.90 | [Скачать](https://disk.yandex.ru/d/I1WyAfN3PJM9fw) | `dome` (руки над головой домиком)<br>`cross` (предплечья скрещены на груди)<br>`none` (остальные) |
| **special_gestures_rf** | Random Forest | 50 деревьев, max_depth=10, random_state=42 | 99 нормализованных координат скелета (33 точки × 3) | 3 класса (dome, cross, none) | **0.87** | **dome**: P=0.67, R=1.00<br>**cross**: P=0.750, R=1.00<br>**none**: P=0.90, R=0.90 | [Скачать](https://disk.yandex.ru/d/fcXxQh4LGjqA1g) |`dome` (руки над головой домиком)<br>`cross` (предплечья скрещены на груди)<br>`none` (остальные) | | **special_gestures_rf** | Random Forest | 50 деревьев, max_depth=10, random_state=42 | 99 нормализованных координат скелета (33 точки × 3) | 3 класса (dome, cross, none) | **0.87** | **dome**: P=0.67, R=1.00<br>**cross**: P=0.750, R=1.00<br>**none**: P=0.90, R=0.90 | [Скачать](https://disk.yandex.ru/d/fcXxQh4LGjqA1g) |`dome` (руки над головой домиком)<br>`cross` (предплечья скрещены на груди)<br>`none` (остальные) |
| **special_gestures_lin** | Logistic Regression | max_iter=1000, random_state=42 | 99 нормализованных координат скелета (33 точки × 3) | 3 класса (dome, cross, none) | **0.94** | **dome**: P=1.00, R=1.00<br>**cross**: P=0.750, R=1.00<br>**none**: P=1.00, R=0.90 | [Скачать](https://disk.yandex.ru/d/4_XCPEeOGvNX6g) |`dome` (руки над головой домиком)<br>`cross` (предплечья скрещены на груди)<br>`none` (остальные) | | **special_gestures_lin** | Logistic Regression | max_iter=1000, random_state=42 | 99 нормализованных координат скелета (33 точки × 3) | 3 класса (dome, cross, none) | **0.94** | **dome**: P=1.00, R=1.00<br>**cross**: P=0.750, R=1.00<br>**none**: P=1.00, R=0.90 | [Скачать](https://disk.yandex.ru/d/4_XCPEeOGvNX6g) |`dome` (руки над головой домиком)<br>`cross` (предплечья скрещены на груди)<br>`none` (остальные) |
| **dynamic_model** | LSTM | 2 слоя LSTM по 64 нейрона, Dropout(0.3), Dense(3, softmax), optimizer=Adam, loss=sparse_categorical_crossentropy, epochs=50, batch_size=16 | Последовательность из 14 кадров, каждый кадр 99 признаков (нормализованные координаты скелета) | 3 класса (none, wave_left, wave_right) | 0.8235 | Precision / Recall (по классам) | [Скачать](https://disk.yandex.ru/d/yDol79iB2ZlS6Q) | `wave_left` (махание левой рукой) `wave_right` (махание правой рукой) `none` (отсутствие жеста) |

@ -16,18 +16,19 @@ class Config:
# ===== Специальные жесты ===== # ===== Специальные жесты =====
SPECIAL_GESTURE_MODE = 'ml' #ml #geometric SPECIAL_GESTURE_MODE = 'ml' #ml #geometric
ML_GESTURE_MODEL = '/home/ubuntu/sirius/models/rf/special_model.pkl' ML_GESTURE_MODEL = '/home/ubuntu/sirius/models/rf/special_gestures_rf.pkl'
ML_GESTURE_CLASSES = ['dome', 'cross', 'none'] ML_GESTURE_CLASSES = ['dome', 'cross', 'none']
DYNAMIC_GESTURE = { DYNAMIC_GESTURE = {
'enabled': True, # включить/выключить 'enabled': True, # включить/выключить
'model_path': 'dynamic_model.h5', 'model_path': '/home/ubuntu/sirius/models/lstm/dynamic_model.h5',
'classes_path': 'dynamic_model_classes.pkl', 'classes_path': '/home/ubuntu/sirius/models/lstm/dynamic_model_classes.pkl',
'window_size': 14, # длина буфера 'window_size': 14, # длина буфера
'threshold': 0.7, # порог уверенности 'threshold': 0.8, # порог уверенности
'actions': { 'actions': {
'wave_left': 'reset', # при жесте wave_left перезапуск симулятора 'wave_left': 'reset', # при жесте wave_left перезапуск симулятора
'wave_right': 'restart', # при wave_right рестарт 'wave_right': 'restart' # при wave_right рестарт
}
} }
# ===== Робот ===== # ===== Робот =====

@ -54,6 +54,9 @@ def main():
print("В симуляторе: R перезапуск после Game Over/победы") print("В симуляторе: R перезапуск после Game Over/победы")
print("q выход") print("q выход")
last_dynamic_gesture = None
dynamic_gesture_counter = 0
while True: while True:
ret, frame = cap.read() ret, frame = cap.read()
if not ret: if not ret:
@ -67,7 +70,6 @@ def main():
if result['success']: if result['success']:
landmarks = result['landmarks'] landmarks = result['landmarks']
if result['success']:
if cfg.DYNAMIC_GESTURE['enabled']: if cfg.DYNAMIC_GESTURE['enabled']:
dynamic_predictor.add_frame(landmarks) dynamic_predictor.add_frame(landmarks)
gesture = dynamic_predictor.predict() gesture = dynamic_predictor.predict()
@ -77,6 +79,8 @@ def main():
robot.reset() robot.reset()
elif action == 'restart': elif action == 'restart':
robot.reset() robot.reset()
last_dynamic_gesture = gesture
dynamic_gesture_counter = 30
vis_frame = detector.draw_landmarks(frame, result['pose_landmarks']) vis_frame = detector.draw_landmarks(frame, result['pose_landmarks'])
@ -99,6 +103,12 @@ def main():
if special != 'none': if special != 'none':
cv2.putText(vis_frame, f"Special: {special}", (10, 90), cv2.putText(vis_frame, f"Special: {special}", (10, 90),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,0), 2) cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,0), 2)
if dynamic_gesture_counter > 0 and last_dynamic_gesture:
cv2.putText(vis_frame, f"Dynamic: {last_dynamic_gesture}", (10, 120),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)
dynamic_gesture_counter -= 1
else: else:
vis_frame = frame vis_frame = frame
cv2.putText(vis_frame, "No pose detected", (10, 30), cv2.putText(vis_frame, "No pose detected", (10, 30),

@ -14,6 +14,8 @@ class DynamicGesturePredictor:
self.threshold = threshold self.threshold = threshold
def add_frame(self, landmarks): def add_frame(self, landmarks):
if landmarks is None or np.isnan(landmarks).any():
landmarks = np.zeros(99)
self.buffer.append(landmarks) self.buffer.append(landmarks)
def predict(self): def predict(self):

Loading…
Cancel
Save