Пошаговое руководство по созданию интерфейса в стиле фильма «Особое мнение» с использованием OpenCV и MediaPipe.
Делиться

Мы живем в эпоху беспилотных автомобилей и языковых моделей искусственного интеллекта, однако основной физический интерфейс, через который мы взаимодействуем с машинами, остается неизменным уже пятьдесят лет. Удивительно, но мы до сих пор используем компьютерную мышь, устройство, созданное Дугом Энгельбартом в начале 1960-х годов, для щелчков и перетаскивания. Несколько недель назад я решил подвергнуть сомнению эту норму, написав код на Python.
Для специалистов по анализу данных и инженеров машинного обучения этот проект — не просто трюк, а мастер-класс по прикладному компьютерному зрению. Мы создадим конвейер обработки данных в реальном времени, который будет принимать неструктурированный видеопоток (пиксели), последовательно применять модель машинного обучения для извлечения признаков (ориентиры рук) и, наконец, преобразовывать их в осязаемые команды (перемещение курсора). По сути, это пример «Hello World» следующего поколения взаимодействия человека с компьютером.
Цель? Управлять курсором мыши простым взмахом руки. После запуска программы в окне отобразится изображение с веб-камеры, на которое в реальном времени будет наложен скелет руки. Курсор на вашем компьютере будет отслеживать движение вашего указательного пальца. Это почти как телекинез — вы управляете цифровым объектом, не прикасаясь к физическому устройству.
Концепция: научить Python «видеть».
Чтобы соединить физический мир (мою руку) с цифровым миром (курсором мыши), мы решили разделить проблему на две части: глаза и мозг.
- «Глаза» – Веб-камера (OpenCV): Первый шаг – получение видео с камеры в реальном времени. Для этого мы будем использовать OpenCV. OpenCV – это обширная библиотека компьютерного зрения, которая позволяет Python получать доступ к кадрам с веб-камеры и обрабатывать их. Наш код открывает камеру по умолчанию с помощью cv2.VideoCapture(0), а затем продолжает считывать кадры один за другим.
- Обнаружение ориентиров на руке (MediaPipe): Для анализа каждого кадра, поиска руки и распознавания ключевых точек на ней мы обратились к решению Google MediaPipe Hands. Это предварительно обученная модель машинного обучения, способная взять снимок руки и предсказать местоположение 21 трехмерного ориентира (суставов и кончиков пальцев) на руке. Проще говоря, MediaPipe Hands не только «обнаруживает руку здесь», но и точно показывает, где находится каждый кончик пальца и сустав на изображении. Как только вы получите эти ориентиры, основная задача, по сути, решена: просто выберите нужный ориентир и используйте его координаты.

По сути, это означает, что мы передаем каждый кадр с камеры в MediaPipe, который выводит координаты (x,y,z) 21 точки на руке. Для управления курсором мы будем следовать за местоположением ориентира № 8 (кончик указательного пальца). (Если бы мы позже реализовали функцию щелчка, мы могли бы проверять расстояние между ориентиром № 8 и № 4 (кончик большого пальца), чтобы определить жест сжатия.) На данный момент нас интересует только движение: если мы найдем положение кончика указательного пальца, мы сможем довольно точно определить, куда должен переместиться указатель мыши.
Магия MediaPipe
MediaPipe Hands берет на себя сложные задачи обнаружения рук и оценки ключевых точек. Решение использует машинное обучение для прогнозирования 21 ключевой точки руки всего по одному кадру изображения.
Более того, модель предварительно обучена (на самом деле, на более чем 30 000 изображениях рук), а это значит, что нам не нужно обучать свою собственную модель. Мы просто получаем и используем «мозг» отслеживания рук MediaPipe на Python:
mp_hands = mp.solutions.hands hands = mp_hands.Hands(max_num_hands=1, min_detection_confidence=0.7)
Таким образом, после каждого кадра, отправляемого через hands.process(), возвращается список обнаруженных рук вместе с их 21 ориентиром. Мы отображаем их на изображении, чтобы визуально убедиться в работоспособности системы. Важно отметить, что для каждой руки мы можем получить hand_landmarks.landmark[i], где i изменяется от 0 до 20, причем каждое значение имеет нормализованные координаты (x, y, z). В частности, кончик указательного пальца — это landmark[8], а кончик большого пальца — landmark[4]. Используя MediaPipe, мы уже избавлены от сложной задачи определения геометрии положения руки.
Настройка
Для этого вам не понадобится суперкомпьютер — достаточно обычного ноутбука с веб-камерой. Просто установите следующие библиотеки Python:
pip install opencv-python mediapipe pyautogui numpy
- opencv-python: Обрабатывает видеопоток с веб-камеры. OpenCV позволяет захватывать кадры в реальном времени и отображать их в окне.
- mediapipe: Предоставляет модель отслеживания движений рук (MediaPipe Hands). Она обнаруживает руку и возвращает 21 опорную точку.
- pyautogui: кроссплатформенная библиотека для автоматизации графического интерфейса пользователя. Мы будем использовать её для перемещения фактического курсора мыши на экране. Например, pyautogui.moveTo(x, y) мгновенно перемещает курсор в позицию (x, y).
- numpy: Используется для численных операций, в основном для сопоставления координат камеры с координатами экрана. Мы используем numpy.interp для масштабирования значений от размера кадра веб-камеры до полного разрешения экрана.
Теперь наша среда готова, и мы можем написать всю логику в одном файле (например, ai_mouse.py).
Кодекс
Основная логика удивительно лаконична (менее 60 строк). Вот полный скрипт на Python:
import cv2 import mediapipe as mp import pyautogui import numpy as np # — КОНФИГУРАЦИЯ — SMOOTHING = 5 # Чем выше значение, тем плавнее движение, но и тем больше задержка. plocX, plocY = 0, 0 # Предыдущее положение пальца clocX, clocY = 0, 0 # Текущее положение пальца # — ИНИЦИАЛИЗАЦИЯ — cap = cv2.VideoCapture(0) # Открыть веб-камеру (0 = камера по умолчанию) mp_hands = mp.solutions.hands # Отслеживать максимум 1 руку, чтобы избежать путаницы, порог достоверности 0.7 hands = mp_hands.Hands(max_num_hands=1, min_detection_confidence=0.7) mp_draw = mp.solutions.drawing_utils screen_width, screen_height = pyautogui.size() # Получить фактический размер экрана print(«AI Mouse Active. Press 'q' to quit.») while True: # ШАГ 1: ПРОСМОТР — Захватить кадр с веб-камеры success, img = cap.read() if not success: break img = cv2.flip(img, 1) # Зеркальное отображение изображения кажется естественным frame_height, frame_width, _ = img.shape img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # ШАГ 2: ПОДУМАЙТЕ — Обработайте кадр с помощью MediaPipe results = hands.process(img_rgb) # Если рука найдена: if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: # Нарисуйте скелет на кадре, чтобы мы могли его видеть mp_draw.draw_landmarks(img, hand_landmarks, mp_hands.HAND_CONNECTIONS) # ШАГ 3: ДЕЙСТВУЙТЕ — Перемещайте мышь в соответствии с кончиком указательного пальца. index_finger = hand_landmarks.landmark[8] # ориентир #8 = кончик указательного пальца x = int(index_finger.x * frame_width) y = int(index_finger.y * frame_height) # Сопоставление координат веб-камеры с экранными координатами mouse_x = np.interp(x, (0, frame_width), (0, screen_width)) mouse_y = np.interp(y, (0, frame_height), (0, screen_height)) # Сглаживание значений для уменьшения дрожания («профессиональное ощущение») clocX = plocX + (mouse_x — plocX) / SMOOTHING clocY = plocY + (mouse_y — plocY) / SMOOTHING # Перемещение фактического курсора мыши pyautogui.moveTo(clocX, clocY) plocX, plocY = clocX, clocY # Обновление предыдущего местоположения # Отображение изображения с веб-камеры с наложением cv2.imshow(«AI Mouse Controller», img) если cv2.waitKey(1) & 0xFF == ord('q'): # Выход при нажатии клавиши 'q' break # Очистка cap.release() cv2.destroyAllWindows()
Эта программа непрерывно повторяет один и тот же трехэтапный процесс в каждом кадре: ВИДЕТЬ, ДУМАТЬ, ДЕЙСТВОВАТЬ. Сначала она захватывает кадр с веб-камеры. Затем она применяет MediaPipe для идентификации руки и отрисовки ориентиров. Наконец, код получает доступ к положению кончика указательного пальца (ориентир № 8) и использует его для перемещения курсора.
Поскольку кадр веб-камеры и ваш дисплей имеют разные системы координат, мы сначала преобразуем положение кончика пальца в разрешение всего экрана с помощью numpy.interp, а затем вызываем pyautogui.moveTo(x, y) для перемещения курсора. Для повышения стабильности движения мы дополнительно применяем небольшое сглаживание (усреднение положений во времени), чтобы уменьшить дрожание.
Результат
Запустите скрипт через Python ai_mouse.py. Откроется окно «AI Mouse Controller», отображающее активность камеры. Поднесите руку к камере, и вы увидите раскрашенный скелет (суставы и соединения кисти), нарисованный поверх него. Затем переместите указательный палец, и курсор мыши будет плавно перемещаться по экрану, следуя за движением пальца в реальном времени.
Поначалу это кажется странным — чем-то напоминает телекинез. Однако через несколько секунд к этому привыкаешь. Курсор движется именно так, как вы ожидаете увидеть движение пальца, благодаря интерполяции и сглаживанию, которые являются частью программы. Поэтому, если система на мгновение не сможет обнаружить вашу руку, курсор может оставаться неподвижным, пока обнаружение не восстановится, но в целом, это потрясающе хорошо работает. (Если вы хотите выйти, просто нажмите клавишу q в окне OpenCV.)
Заключение: Будущее интерфейсов
Для этого проекта было написано всего около 60 строк кода на Python, но он смог продемонстрировать нечто весьма важное.
Сначала мы ограничивались перфокартами, затем клавиатурами, а после этого — мышами. Теперь же достаточно просто взмахнуть рукой, и Python понимает это как команду. Поскольку индустрия сосредоточена на пространственных вычислениях, управление на основе жестов перестало быть фантастикой — оно становится реальностью нашего взаимодействия с машинами.

Конечно, этот прототип пока не готов заменить мышь в соревновательных играх. Но он позволил нам увидеть, как искусственный интеллект стирает разрыв между намерением и действием .
Ваше следующее испытание: щелчок щипком
Логичным следующим шагом будет превращение этого проекта из демонстрационной версии в полноценный инструмент. Функцию «клик» можно реализовать, отслеживая жест масштабирования:
- Измерьте евклидово расстояние между ориентиром № 8 (кончик указательного пальца) и ориентиром № 4 (кончик большого пальца).
- Если расстояние меньше заданного порогового значения (например, 30 пикселей), то следует вызвать метод pyautogui.click().
Давай, попробуй. Создай что-нибудь, что будет выглядеть как волшебство.
Давайте общаться
Если вам удастся это реализовать, я буду в восторге. Не стесняйтесь связаться со мной в LinkedIn и отправить мне личное сообщение с результатами. Я регулярно пишу статьи на темы, связанные с Python, ИИ и креативным программированием.
Ссылки
- MediaPipe Hands (Google): модель обнаружения ключевых точек на руке и документация.
- Документация OpenCV-Python: инструменты для захвата изображения с веб-камеры, обработки кадров и визуализации.
- Документация PyAutoGUI: API для программного управления курсором и автоматизации (moveTo, click и т. д.)
- Документация NumPy: numpy.interp() для сопоставления координат веб-камеры с координатами экрана.
- Дуг Энгельбарт и компьютерная мышь (исторический контекст): происхождение мыши как базового элемента современного интерфейса.
Источник: towardsdatascience.com



























