Этот проект на ESP32 представляет собой увлекательный и интерактивный способ управления светодиодами с помощью жестов. Мы будем использовать плату ESP32, Python, MediaPipe и OpenCV для создания системы, которая может распознавать определённые жесты рук и преобразовывать их в действия, управляющие светодиодами. MediaPipe будет использоваться для распознавания жестов, а OpenCV будет захватывать видеосигнал с веб-камеры в режиме реального времени. На основе жестов (таких как открытая ладонь, кулак или движение пальцев) команды будут отправляться на ESP32, который будет управлять подключенными к нему светодиодами. Это позволит нам включать и выключать светодиоды, изменять их яркость и даже управлять различными светодиодами с помощью определённых жестов. Это практичный и увлекательный способ изучить распознавание жестов, аппаратное управление и взаимодействие между Python и микроконтроллерами.

Также на нашем сайте вы можете посмотреть другие проекты, связанные с распознванием жестов:
- управление компьютером с помощью жестов рук и Arduino;
- управляемая жестами роботизированная рука на Arduino Nano;
- распознавание жестов с помощью Raspberry Pi и OpenCV;
- управляемый жестами видеоплеер на Raspberry Pi и MediaPipe;
- умный дом на ESP12 с управлением жестами и компьютерном зрении;
- модуль распознавания жестов PAJ7620 и как его подключить к Arduino.
Обзор проекта
В этом проекте демонстрируется управление светодиодами с помощью жестов руки, реализованное с помощью Python, OpenCV и микроконтроллера ESP32. Жесты руки распознаются веб-камерой и обрабатываются с помощью MediaPipe — библиотеки, разработанной для отслеживания движений рук и распознавания жестов. Каждому распознанному жесту присваивается команда управления светодиодом, например, включение или выключение светодиодов. Это позволяет интерактивно управлять светодиодами простыми движениями руки.
Команды, генерируемые жестами, передаются по беспроводной сети на ESP32 через Wi-Fi с помощью HTTP-запросов. Выступая в роли сервера, ESP32 получает эти команды и управляет светодиодами, подключенными к его контактам GPIO. Этот проект объединяет компьютерное зрение, встраиваемые системы и сетевые технологии, предлагая отличную отправную точку для новичков, интересующихся системами управления на основе жестов, Интернетом вещей и интеграцией аппаратного и программного обеспечения.
Требуемые компоненты
1. Плата ESP32 - 1 (ESP32 используется в качестве контроллера для обработки команд, отправляемых на основе жестов руки, распознаваемых камерой) (купить на AliExpress).
2. Светодиоды (5 шт.) для каждого пальца (большой, указательный, средний, безымянный, мизинец) (купить на AliExpress).
3. Резисторы (пять по 220 Ом для каждого светодиода).
4. Соединительные провода (штекер-гнездо).
5. Макетная плата.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Схема проекта
Схема проекта распознавания жестов рук с помощью ESP32, Python и OpenCV представлена на следующем рисунке.
Для управления пятью светодиодами с помощью ESP32 светодиоды подключаются к определённым контактам GPIO на ESP32, при этом каждый светодиод соответствует определённому жесту руки. Положительный вывод (анод) каждого светодиода подключается к выделенному контакту GPIO, например, к контактам GPIO 14, 27, 26, 25 и 33, которые управляют светодиодами. Эти контакты GPIO обеспечивают необходимое напряжение для включения каждого светодиода. Чтобы предотвратить повреждение светодиодов или ESP32 избыточным током, последовательно с каждым светодиодом подключается резистор сопротивлением 220 Ом или 330 Ом. Резисторы имеют решающее значение, поскольку ограничивают ток, протекающий через светодиоды, обеспечивая их безопасную работу.

Отрицательный вывод (катод) каждого светодиода подключается к заземлению (GND) ESP32. Это обеспечивает замкнутую электрическую цепь для каждого светодиода. Когда вывод GPIO установлен в положение HIGH, он подаёт напряжение на анод светодиода, заставляя его загораться. И наоборот, когда вывод GPIO установлен в положение LOW, светодиод выключается. При правильном подключении система управления жестами может эффективно включать и выключать каждый светодиод в зависимости от распознанного жеста, что делает систему интерактивной и полезной для различных приложений.

Код ESP32 для управления светодиодами жестами руки
Этот код настраивает ESP32 как веб-сервер, управляющий пятью светодиодами, соответствующими большому, указательному, среднему, безымянному пальцам и мизинцу. Каждый светодиод подключен к определённому выводу GPIO и может включаться и выключаться с помощью HTTP-запросов. ESP32 подключается к Wi-Fi, используя предоставленные учётные данные, и после подключения служит конечными точками для управления каждым светодиодом. Когда пользователь переходит по URL-адресу, соответствующему светодиоду (например, "/led/thumb/on"), соответствующий светодиод включается и отправляет сообщение. Сервер работает на порту 80 и обрабатывает запросы на управление светодиодами.
Используемые библиотеки
ESPAsyncWebServer — доступен в диспетчере библиотек
Wire — библиотека по умолчанию
Полный код ESP32
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
#include <WiFi.h> #include <ESPAsyncWebServer.h> const char* ssid = "Wifi_name"; const char* password = "Wifi_password"; AsyncWebServer server(80); // Define GPIO pins for LEDs const int thumbLedPin = 27; const int indexLedPin = 26; const int middleLedPin = 25; const int ringLedPin = 33; const int pinkyLedPin = 32; void setup() { Serial.begin(115200); pinMode(thumbLedPin, OUTPUT); pinMode(indexLedPin, OUTPUT); pinMode(middleLedPin, OUTPUT); pinMode(ringLedPin, OUTPUT); pinMode(pinkyLedPin, OUTPUT); digitalWrite(thumbLedPin, LOW); digitalWrite(indexLedPin, LOW); digitalWrite(middleLedPin, LOW); digitalWrite(ringLedPin, LOW); digitalWrite(pinkyLedPin, LOW); Serial.println("Connecting to WiFi..."); WiFi.begin(ssid, password); int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < 20) { // Try for 20 seconds delay(1000); Serial.print("."); attempts++; } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nConnected to WiFi"); Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // Define HTTP request handlers for each LED server.on("/led/thumb/on", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(thumbLedPin, HIGH); request->send(200, "text/plain", "Price - 300"); }); server.on("/led/thumb/off", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(thumbLedPin, LOW); request->send(200, "text/plain", "Thumb LED is OFF"); }); server.on("/led/index/on", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(indexLedPin, HIGH); request->send(200, "text/plain", "Index finger LED is ON"); }); server.on("/led/index/off", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(indexLedPin, LOW); request->send(200, "text/plain", "Index finger LED is OFF"); }); server.on("/led/middle/on", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(middleLedPin, HIGH); request->send(200, "text/plain", "Middle finger LED is ON"); }); server.on("/led/middle/off", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(middleLedPin, LOW); request->send(200, "text/plain", "Middle finger LED is OFF"); }); server.on("/led/ring/on", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(ringLedPin, HIGH); request->send(200, "text/plain", "Ring finger LED is ON"); }); server.on("/led/ring/off", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(ringLedPin, LOW); request->send(200, "text/plain", "Ring finger LED is OFF"); }); server.on("/led/pinky/on", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(pinkyLedPin, HIGH); request->send(200, "text/plain", "Pinky finger LED is ON"); }); server.on("/led/pinky/off", HTTP_GET, [](AsyncWebServerRequest *request){ digitalWrite(pinkyLedPin, LOW); request->send(200, "text/plain", "Pinky finger LED is OFF"); }); server.begin(); Serial.println("Server started"); } else { Serial.println("\nFailed to connect to WiFi"); } } void loop() { // Additional code can be added here if needed, but typically not necessary for basic HTTP server operations. } |
Объяснение работы кода
Инициализация: ESP32 инициализирует последовательную связь со скоростью 115200 бод и настраивает контакты GPIO (27, 26, 25, 33, 32) для светодиодов.
Настройка светодиодов: все светодиоды изначально выключены путем установки их контактов GPIO в положение LOW.
Подключение к WiFi: ESP32 пытается подключиться к указанной сети WiFi, используя предоставленные SSID и пароль.
Проверка статуса WiFi: если соединение установлено успешно, выводится IP-адрес; если нет, то попытки продолжаются до 20 секунд.
Настройка сервера: после подключения к WiFi ESP32 запускает HTTP-сервер на порту 80.
Определения конечных точек: обработчики запросов HTTP GET определены для каждого светодиода с URL-адресами для включения или выключения каждого светодиода (например, «/led/thumb/on»).
Управление светодиодом: при получении запроса на определенной конечной точке (например, «/led/thumb/on») соответствующий светодиод включается или выключается.
Ответ: каждый HTTP-запрос отправляет ответ с подтверждающим сообщением, например «Светодиод большого пальца включен» или «Цена - 300».
Запуск сервера: сервер начинает прослушивать входящие запросы и обеспечивает управление светодиодами через конечные веб-точки.
Цикл: Функция loop() пуста, поскольку сервер работает асинхронно, обрабатывая запросы без необходимости постоянных проверок в цикле.
Код Python с использованием OpenCV и Media Pipe
Этот код использует OpenCV и MediaPipe для распознавания жестов руки через веб-камеру. Он определяет положение каждого пальца (поднят или опущен) и отправляет соответствующие команды управления на ESP32, например, для включения/выключения светодиодов. ESP32 задаётся IP-адрес, и он взаимодействует с сервером для отправки и получения команд с помощью HTTP-запросов. Код проверяет, все ли пальцы опущены, и в этом случае отправляет специальную команду. Распознанный жест руки отображается на экране, а команда ESP32 отображается в режиме реального времени.
Используемые библиотеки
pip install opencv-python
pip install mediapipe
pip install requests
Полный код Python
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
import cv2 import mediapipe as mp import requests # ESP32 Base URL ESP32_IP = "http://192.168.137.123" # Change this to your ESP32 IP address # Initialize MediaPipe Hands mp_hands = mp.solutions.hands hands = mp_hands.Hands() mp_drawing = mp.solutions.drawing_utils # Function to send hand gesture commands to ESP32 def control_led(endpoint): url = f"{ESP32_IP}/cart/{endpoint}" try: response = requests.get(url) print(f"Sent command: {endpoint}, ESP32 Response: {response.text}") except Exception as e: print(f"Failed to send command: {endpoint}, Error: {e}") # Function to fetch commands from ESP32 def fetch_esp32_command(): try: url = f"{ESP32_IP}/command" response = requests.get(url) return response.text.strip() except Exception as e: print(f"Error fetching command from ESP32: {e}") return None # Function to detect the state of each finger def count_fingers(hand_landmarks): # Detect finger states (up or down) thumb_up = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP].x < hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_IP].x index_up = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP].y < hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_PIP].y middle_up = hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP].y < hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_PIP].y ring_up = hand_landmarks.landmark[mp_hands.HandLandmark.RING_FINGER_TIP].y < hand_landmarks.landmark[mp_hands.HandLandmark.RING_FINGER_PIP].y pinky_up = hand_landmarks.landmark[mp_hands.HandLandmark.PINKY_TIP].y < hand_landmarks.landmark[mp_hands.HandLandmark.PINKY_PIP].y # Combine finger statuses into a list finger_status = [thumb_up, index_up, middle_up, ring_up, pinky_up] # Send control commands to ESP32 for each finger control_led("add" if thumb_up else "remove") control_led("index/on" if index_up else "index/off") control_led("middle/on" if middle_up else "middle/off") # Check if all fingers are down if not any(finger_status): print("All fingers are down") # Message when all fingers are down control_led("all/down") # Example action when all fingers are down return finger_status # Initialize VideoCapture cap = cv2.VideoCapture(1) while cap.isOpened(): ret, frame = cap.read() if not ret: break frame = cv2.flip(frame, 1) frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Detect hand landmarks results = hands.process(frame_rgb) if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS) fingers = count_fingers(hand_landmarks) # Fetch and display command from ESP32 esp32_command = fetch_esp32_command() if esp32_command: cv2.putText(frame, f"ESP32 Command: {esp32_command}", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) cv2.imshow('Hand Gesture Recognition', frame) if cv2.waitKey(5) & 0xFF == 27: # Exit on pressing 'Esc' break cap.release() cv2.destroyAllWindows() |
Объяснение кода Python
Инициализация библиотек: импортируются OpenCV и MediaPipe для обработки захвата видео и распознавания жестов рук.
Установить IP-адрес ESP32: Определяется IP-адрес ESP32, который будет использоваться для отправки и получения HTTP-запросов.
Инициализация MediaPipe: инициализируется модель отслеживания рук MediaPipe для обнаружения и обработки ориентиров рук на видеопотоке.
Определите функцию control_led: эта функция отправляет команду ESP32 для управления светодиодами на основе жеста руки (например, включение или выключение светодиодов).
Определите функцию fetch_esp32_command: эта функция извлекает команды из ESP32, отправляя HTTP-запрос GET на определенный URL.
Определите функцию count_fingers: эта функция анализирует ориентиры руки, чтобы определить, поднят или опущен каждый палец, и отправляет соответствующие команды управления светодиодом в ESP32.
Захват видео: код открывает видеопоток (камеру) и захватывает кадры для обработки.
Обработка ориентиров руки: MediaPipe обрабатывает каждый кадр для обнаружения ориентиров руки и определения состояния каждого пальца (поднят или опущен).
Отправка команд в ESP32: на основе обнаруженных состояний пальцев в ESP32 отправляются команды для управления светодиодами (например, включение или выключение определенных светодиодов).
Результаты отображения: жест руки и команда ESP32 отображаются в реальном времени на экране с помощью OpenCV, и программа продолжает обрабатывать видео до тех пор, пока пользователь не нажмет клавишу «Esc».
Основные моменты, которые следует запомнить:
обязательно замените « http://192.168.xx » на фактический IP-адрес из последовательного монитора Arduino IDE.
Тестирование работы проекта
Система обеспечивает интуитивно понятное управление светодиодами с помощью жестов. Определяя положение пальцев с помощью MediaPipe, проект определяет поднятые пальцы и отправляет соответствующие команды на ESP32. Каждому пальцу (большому, указательному, среднему, безымянному и мизинцу) соответствует определённый светодиод. При поднятии пальца соответствующий светодиод загорается, а при опускании — гаснет. Проект отправляет эти команды управления на ESP32 посредством HTTP-запросов, что упрощает управление несколькими светодиодами в режиме реального времени. Кроме того, если все пальцы опущены, система запускает предопределённое действие, например, выключает все светодиоды. Это решение интегрирует распознавание жестов с Интернетом вещей, обеспечивая бесперебойное взаимодействие между пользователем и модулем ESP32.


Полный код нашего проекта можно скачать с Github по следующей ссылке.




