## О проекте
Проект позволяет управлять роботом (в симуляторе) с помощью жестов рук, распознаваемых через камеру. Используется MediaPipe для детекции скелета.
## Структура проекта
```
gesture_robot/
├── main.py # Основной цикл
├── config.py # Конфигурация
├── skeleton/ # Детекция скелета (MediaPipe)
│ └── mediapipe_detector.py
├── gesture_control/ # Управление жестами
│ ├── arm_control.py # Скорости по рукам
│ ├── special_gestures.py # Специальные жесты по геометрии
│ └── state.py # Вкл/выкл режима (определение какой жест какую команду триггерит)
├── ml_gestures/ # ML для специальных жестов
│ ├── feature_extractor.py
│ ├── predict.py
│ └── train.py
├── ml_gestures_dynamic/ # ML для динамических жестов
│ ├── feature_extractor.py
│ ├── sequence_utils.py
│ ├── predict.py
│ ├── evaluate.py
│ └── train.py
├── robot/ # Робот (симулятор или заглушка)
│ ├── map_simulator.py
│ └── dummy.py
├── utils/ # Вспомогательные скрипты
│ ├── annotate.py # Разметка изображений
│ ├── capture_photo.py # Съёмка фото с камеры
│ └── record_dynamic.py # Разметка видеопоследовательности
└── requirements.txt
```
## Подготовка и запуск
### Установка зависимостей
pip install -r requirements.txt
### Настройка параметров
Все основные параметры вынесены в `config.py`. Основные:
- `CAMERA_ID` - индекс камеры (по умолчанию 0)
- `MIRROR_CAMERA` - зеркальное отображение (True для фронтальной камеры).
- `ARM_CONTROL` - настройки управления жестами (геометрией) управления
- `linear_arm` - рука, отвечающая за изменение линейной скорости
- `angular_arm` - рука, отвечающая за изменение угловой скорости
- `max_speed_linear` - максимальная линейная скорость (по умолчанию 1)
- `max_speed_angular` - максимальная угловая скорость (по умолчанию 1)
- `dead_zone` - мёртвая зона - доля от ширины плеч/высоты торса (по умолчанию 0.2) для предотвращения ложных срабатываний
- `debug` - Режим отладки, вкл/выкл логи (по умолчанию False)
- `SPECIAL_GESTURE_MODE` - способ детекции специальных статических жестов (ml или geometric)
- `ML_GESTURE_MODEL` - путь до весов ml модели статических жестов
- `ML_GESTURE_CLASSES` - список классов детектируемых жестов, + none
- `ROBOT_MODE` - simulator (мини игра проехать роботом мимо препятствий) или dummy (простой модуль, пишуший отправленную команду, для первичной отладки)
- `ROBOT_IMAGE_PATH` - путь до картинки робота, который будет ездить в симуляции (если не указать будет треугольник просто)
- параметры для симулятора карты:
- `MAP_WIDTH` - ширина карты
- `MAP_HEIGHT` - высота карты
- `MAP_OBSTACLES` - лист препятствий в формате (x, y, width, height)
- `START_POS` - стартовая позиция робота
- `FINISH_POS` - позиция финиша
- `ROBOT_RADIUS` - радиус робота
### Примеры запуска
#### Запуск с геометрическим распознаванием
1. Настройте `config.py`:
- `MIRROR_CAMERA = True` – для фронтальной камеры.
- `SPECIAL_GESTURE_MODE = 'geometric'`.
2. Запустите основной скрипт:
```
python3 main.py
```
3. Запустится симулятор и изображение с камеры
#### Запуск с ML-распознаванием статических жестов
1. Соберите датасет с нужными изображениями фото. Можете заснять собственные через `utils/capture_photo.py`:
```
python3 -m utils/capture_photo.py --dir data/raw
```
Нажмите `s`, подождите 3 секунды, фото сохранится в папку `data/raw`. Нажмите `q` чтобы закончить.
2. Разметьте фото с помощью аннотатора:
```
python3 -m utils/annotate.py --folder data/raw --classes dome,cross,none --output data.csv
```
Для каждого фото нажмите цифру, соответствующую жесту (1–dome, 2–cross, 3–none), или n для пропуска. При выходе данные сохранятся в `data.csv`.
3. Обучите модель
```
python3 -m ml_gestures/train.py --csv data.csv --model ml_gestures/models/special_model.pkl --type mlp --balance --target_classes dome,cross
```
Параметр `balance` уменьшит целевые классы (в параметре `target_classes`) до размера наименьшего из них, чтобы избежать перекоса. Класс none остаётся неизменным.
4. Оценка модели
После обучения модель сохраняется, и создаётся отчёт `special_model_report.json` с метриками (`accuracy`, `precision`, `recall`, `f1`, `confusion matrix`). Для повторной оценки используйте:
```
python3 -m ml_gestures/evaluate.py --csv data.csv --model ml_gestures/models/special_model.pkl --test_size 0.2
```
5. Подключите модель в `config.py`
```
SPECIAL_GESTURE_MODE = 'ml'
ML_GESTURE_MODEL = 'ml_gestures/models/special_model.pkl'
ML_GESTURE_CLASSES = ['dome', 'cross', 'none']
```
6. Запустите основной скрипт:
```
python3 main.py
```
7. Запустится симулятор и изображение с камеры
#### Запуск с ML-распознаванием динамических жестов
1. Соберите датасетс нужными последовательностями жестов.
```
python -m utils.record_dynamic --label wave_right --output dynamic_data.csv --duration 2.0
```
Нажмите `space`, подождите 3 секунды, последовательность точек с меткой сохранится в файл `dynamic_data.csv`. Нажмите `q` чтобы закончить.
2. Обучите модель
```
python -m ml_gestures_dynamic.train --data dynamic_data.csv --model dynamic_model.h5 --max_len 14 --epochs 50 --test_size 0.2
```
Укажите путь до вашего файла, укажите путь, куда сохранить модель, а также укажите длину последовательности кадров (зависит от вашей камеры и железа, будет выводится при сборе данных)
3. Оценка модели
После обучения модель сохраняется, и создаётся отчёт `dynamic_model_report.json` с метриками (`accuracy`, `precision`, `recall`, `f1`, `confusion matrix`). Для повторной оценки используйте:
```
python -m ml_gestures_dynamic.evaluate --data dynamic_data.csv --model dynamic_model.h5 --max_len 14 --test_size 0.2
```
5. Подключить модель в `config.py`
```
DYNAMIC_GESTURE = {
'enabled': True, # включить/выключить
'model_path': 'ml_gestures/models/dynamic_model.h5',
'classes_path': 'ml_gestures//odels/dynamic_model_classes.pkl',
'window_size': 14, # длина буфера
'threshold': 0.7, # порог уверенности
'actions': {
'wave_left': 'reset', # при жесте wave_left – перезапуск симулятора
'wave_right': 'restart', # при wave_right – рестарт
}
```
### Управление в симуляторе
Симулятор – поле с препятствиями, стартом и финишем. Робот движется согласно командам. При столкновении – игра заканчивается (перезапуск по `r`). Закрытие окна игры или нажатие `q` в окне камеры – выход.
1. Управление скоростями
- Линейная скорость (вперёд) – горизонтальное положение правой руки (рука вдоль тела – 0, вытянута в сторону – максимум).
- Угловая скорость – вертикальное положение левой руки (рука на уровне плеча – 0, вверх – поворот вправо, вниз – поворот влево).

2. Специальные жесты. Режим распознавания может быть геометрическим (по правилам) или обучаемым (ML-модель).
- Домик – обе руки над головой (включает управление).
- Крест – предплечья скрещены на груди (выключает управление).

## Возможные проблемы
1. Камера не работает - проверьте `CAMERA_ID` в `config.py` (обычно 0 или 1).
2. Скелет не определяется – убедитесь, что человек стоит на расстоянии 1–2 метра, плечи в кадре. Можете также повысить сложность модели определения скелета (`skeleton/mediapipe_detector.py`), но скажется на производительности.
3. Ложные срабатывания жестов – в геометрическом режиме увеличьте `min_conf` в `special_gestures.py` или переключитесь на ML-режим с большим количеством примеров
4. Робот не движется – проверьте, включено ли управление (жест "домик") и видимость рук.
## Датасеты
| Название | Описание | Ссылка | Количество примеров | Классы |
|----------|----------|--------|---------------------|--------|
| **special_gestures_v1** | Набор фотографий для распознавания специальных жестов (домик, крест, none). Собран с помощью `capture_photo.py` и стоковых изображений, размечен через `annotate.py`. | [Скачать](https://disk.yandex.ru/d/F25kMjrmZ8xwRA) | 77 (после балансировки, 13 на класс dome/cross, 51 none) | `dome`, `cross`, `none` |
## Модели
| Название | Тип | Архитектура / параметры | Вход | Выход | Точность (test) | Precision / Recall (по классам) | Ссылка | Распознаваемые жесты |
|----------|-----|-------------------------|------|-------|-----------------|--------------------------------|--------|----------------------|
| **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
**cross**: P=0.00, R=0.00
**none**: P=0.60, R=0.90 | [Скачать](https://disk.yandex.ru/d/I1WyAfN3PJM9fw) | `dome` (руки над головой домиком)
`cross` (предплечья скрещены на груди)
`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
**cross**: P=0.750, R=1.00
**none**: P=0.90, R=0.90 | [Скачать](https://disk.yandex.ru/d/fcXxQh4LGjqA1g) |`dome` (руки над головой домиком)
`cross` (предплечья скрещены на груди)
`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
**cross**: P=0.750, R=1.00
**none**: P=1.00, R=0.90 | [Скачать](https://disk.yandex.ru/d/4_XCPEeOGvNX6g) |`dome` (руки над головой домиком)
`cross` (предплечья скрещены на груди)
`none` (остальные) |