Mediapipe – отслеживание лиц, рук и позы

онлайн тренажер по питону
Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

MediaPipe Python: Полное руководство по библиотеке компьютерного зрения от Google

MediaPipe — это революционная open-source библиотека от Google, предназначенная для создания сложных мультимодальных ML-пайплайнов. Эта мощная платформа предоставляет готовые высокоточные решения для компьютерного зрения в реальном времени, включая отслеживание рук, распознавание лиц, детекцию поз, анализ жестов, обнаружение объектов и многие другие возможности.

Благодаря удобной Python-обёртке, разработчики могут легко интегрировать передовые технологии машинного обучения в свои проекты, создавая инновационные решения для игр, систем управления жестами, дополненной реальности, анализа поведения, фитнес-приложений и многого другого.

Установка и настройка MediaPipe

Базовая установка

pip install mediapipe opencv-python

Дополнительные зависимости для расширенного функционала

pip install mediapipe opencv-python numpy matplotlib

Проверка установки

import mediapipe as mp
import cv2
print(f"MediaPipe версия: {mp.__version__}")
print(f"OpenCV версия: {cv2.__version__}")

Архитектура и основные компоненты MediaPipe

MediaPipe построен на модульной архитектуре, где каждый модуль специализируется на конкретной задаче компьютерного зрения. Библиотека использует оптимизированные нейронные сети, обученные на огромных датасетах, что обеспечивает высокую точность и производительность.

Основные модули MediaPipe

Модуль Назначение Количество точек Применение
Hands Трекинг кистей рук 21 точка на руку Жестовое управление, виртуальные клавиатуры, игры
FaceMesh Детальное картирование лица 468 точек AR-фильтры, анализ эмоций, распознавание
Pose Отслеживание позы тела 33 ключевые точки Фитнес, спорт, реабилитация, анимация
Holistic Комплексный анализ Лицо + руки + тело Полноценный захват движений
FaceDetection Быстрое обнаружение лиц 6 ключевых точек Системы безопасности, подсчет людей
SelfieSegmentation Сегментация человека Маска сегментации Замена фона, эффекты
Objectron 3D-детекция объектов 3D bounding box AR, робототехника
MediaPipeHandLandmarker Улучшенный трекинг рук 21 точка + дополнительные метрики Точное распознавание жестов

Детальное описание модулей

Модуль Hands - Трекинг рук

Модуль Hands обеспечивает высокоточное отслеживание до двух рук одновременно, определяя 21 ключевую точку на каждой руке.

Основные параметры инициализации

import mediapipe as mp

mp_hands = mp.solutions.hands
hands = mp_hands.Hands(
    static_image_mode=False,      # Режим для видео (False) или статичных изображений (True)
    max_num_hands=2,              # Максимальное количество рук для обнаружения
    min_detection_confidence=0.5, # Минимальная уверенность детекции
    min_tracking_confidence=0.5   # Минимальная уверенность трекинга
)

Практический пример с обработкой координат

import cv2
import mediapipe as mp
import numpy as np

mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.5)
mp_draw = mp.solutions.drawing_utils

cap = cv2.VideoCapture(0)

while cap.isOpened():
    success, frame = cap.read()
    if not success:
        continue
    
    # Подготовка изображения
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    frame_rgb.flags.writeable = False
    results = hands.process(frame_rgb)
    frame_rgb.flags.writeable = True
    frame = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
    
    # Обработка результатов
    if results.multi_hand_landmarks:
        for hand_landmarks in results.multi_hand_landmarks:
            # Отрисовка соединений
            mp_draw.draw_landmarks(
                frame, hand_landmarks, mp_hands.HAND_CONNECTIONS,
                mp_draw.DrawingSpec(color=(0, 0, 255), thickness=2, circle_radius=2),
                mp_draw.DrawingSpec(color=(0, 255, 0), thickness=2)
            )
            
            # Получение координат конкретных точек
            landmarks = []
            for lm in hand_landmarks.landmark:
                h, w, c = frame.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                landmarks.append([cx, cy])
            
            # Пример: детекция поднятых пальцев
            fingers_up = count_fingers(landmarks)
            cv2.putText(frame, f'Fingers: {fingers_up}', (10, 30), 
                       cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
    
    cv2.imshow("Hand Tracking", frame)
    if cv2.waitKey(1) & 0xFF == 27:  # ESC для выхода
        break

cap.release()
cv2.destroyAllWindows()

def count_fingers(landmarks):
    """Функция подсчета поднятых пальцев"""
    tip_ids = [4, 8, 12, 16, 20]  # ID кончиков пальцев
    fingers = []
    
    # Большой палец
    if landmarks[tip_ids[0]][0] > landmarks[tip_ids[0] - 1][0]:
        fingers.append(1)
    else:
        fingers.append(0)
    
    # Остальные пальцы
    for id in range(1, 5):
        if landmarks[tip_ids[id]][1] < landmarks[tip_ids[id] - 2][1]:
            fingers.append(1)
        else:
            fingers.append(0)
    
    return sum(fingers)

Модуль FaceMesh - Детальное картирование лица

FaceMesh предоставляет исключительно точное отслеживание 468 трёхмерных точек лица в реальном времени.

Инициализация и параметры

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
    static_image_mode=False,
    max_num_faces=1,
    refine_landmarks=True,        # Улучшенная точность для губ и глаз
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

Работа с конкретными областями лица

import cv2
import mediapipe as mp

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(refine_landmarks=True)
mp_draw = mp.solutions.drawing_utils
draw_spec = mp_draw.DrawingSpec(thickness=1, circle_radius=1)

# Индексы для конкретных частей лица
LEFT_EYE = [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385, 384, 398]
RIGHT_EYE = [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161, 246]
LIPS = [61, 146, 91, 181, 84, 17, 314, 405, 320, 307, 375, 308, 324, 318]

cap = cv2.VideoCapture(0)

while cap.isOpened():
    success, frame = cap.read()
    if not success:
        continue
    
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = face_mesh.process(frame_rgb)
    
    if results.multi_face_landmarks:
        for face_landmarks in results.multi_face_landmarks:
            # Отрисовка всей сетки лица
            mp_draw.draw_landmarks(
                frame, face_landmarks, mp_face_mesh.FACEMESH_CONTOURS,
                None, draw_spec
            )
            
            # Выделение глаз
            h, w, c = frame.shape
            for eye_idx in LEFT_EYE + RIGHT_EYE:
                x = int(face_landmarks.landmark[eye_idx].x * w)
                y = int(face_landmarks.landmark[eye_idx].y * h)
                cv2.circle(frame, (x, y), 2, (0, 255, 0), -1)
    
    cv2.imshow("Face Mesh", frame)
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

Модуль Pose - Отслеживание позы тела

Модуль Pose определяет 33 ключевые точки человеческого тела, включая суставы, конечности и центральные точки.

Расширенный пример с анализом позы

import cv2
import mediapipe as mp
import numpy as np

mp_pose = mp.solutions.pose
pose = mp_pose.Pose(
    static_image_mode=False,
    model_complexity=2,           # 0, 1 или 2 (более высокая точность)
    smooth_landmarks=True,
    enable_segmentation=True,     # Включить сегментацию
    smooth_segmentation=True,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

mp_draw = mp.solutions.drawing_utils

def calculate_angle(a, b, c):
    """Вычисление угла между тремя точками"""
    a = np.array(a)
    b = np.array(b)
    c = np.array(c)
    
    radians = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
    angle = np.abs(radians * 180.0 / np.pi)
    
    if angle > 180.0:
        angle = 360 - angle
    
    return angle

cap = cv2.VideoCapture(0)

while cap.isOpened():
    success, frame = cap.read()
    if not success:
        continue
    
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = pose.process(frame_rgb)
    
    if results.pose_landmarks:
        # Отрисовка скелета
        mp_draw.draw_landmarks(
            frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS,
            mp_draw.DrawingSpec(color=(245, 117, 66), thickness=2, circle_radius=2),
            mp_draw.DrawingSpec(color=(245, 66, 230), thickness=2, circle_radius=2)
        )
        
        # Извлечение координат для анализа
        landmarks = results.pose_landmarks.landmark
        h, w, c = frame.shape
        
        # Координаты для анализа приседаний
        hip = [landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x * w,
               landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y * h]
        knee = [landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].x * w,
                landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].y * h]
        ankle = [landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].x * w,
                 landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].y * h]
        
        # Вычисление угла в колене
        angle = calculate_angle(hip, knee, ankle)
        
        # Визуализация угла
        cv2.putText(frame, f'Knee Angle: {int(angle)}', 
                   (int(knee[0]), int(knee[1]) - 20),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
        
        # Определение фазы приседания
        if angle > 160:
            stage = "UP"
        elif angle < 90:
            stage = "DOWN"
        
        cv2.putText(frame, f'Stage: {stage}', (10, 30),
                   cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    
    cv2.imshow("Pose Analysis", frame)
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

Модуль Holistic - Комплексный анализ

Holistic объединяет возможности всех основных модулей, обеспечивая одновременное отслеживание лица, рук и позы тела.

import cv2
import mediapipe as mp

mp_holistic = mp.solutions.holistic
holistic = mp_holistic.Holistic(
    static_image_mode=False,
    model_complexity=2,
    smooth_landmarks=True,
    enable_segmentation=True,
    smooth_segmentation=True,
    refine_face_landmarks=True,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

mp_draw = mp.solutions.drawing_utils

cap = cv2.VideoCapture(0)

while cap.isOpened():
    success, frame = cap.read()
    if not success:
        continue
    
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = holistic.process(frame_rgb)
    
    # Отрисовка всех компонентов
    if results.face_landmarks:
        mp_draw.draw_landmarks(frame, results.face_landmarks, mp_holistic.FACEMESH_CONTOURS)
    
    if results.pose_landmarks:
        mp_draw.draw_landmarks(frame, results.pose_landmarks, mp_holistic.POSE_CONNECTIONS)
    
    if results.left_hand_landmarks:
        mp_draw.draw_landmarks(frame, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
    
    if results.right_hand_landmarks:
        mp_draw.draw_landmarks(frame, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
    
    cv2.imshow("Holistic Analysis", frame)
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

Таблица методов и функций MediaPipe

Класс/Функция Модуль Описание Основные параметры
Hands() mp.solutions.hands Инициализация детектора рук static_image_mode, max_num_hands, min_detection_confidence
FaceMesh() mp.solutions.face_mesh Создание детектора лицевой сетки refine_landmarks, max_num_faces, min_detection_confidence
Pose() mp.solutions.pose Инициализация детектора позы model_complexity, smooth_landmarks, enable_segmentation
Holistic() mp.solutions.holistic Комплексный детектор model_complexity, refine_face_landmarks, enable_segmentation
SelfieSegmentation() mp.solutions.selfie_segmentation Сегментация селфи model_selection (0 или 1)
FaceDetection() mp.solutions.face_detection Быстрое обнаружение лиц model_selection, min_detection_confidence
.process(image) Все модули Обработка изображения RGB изображение в формате numpy array
draw_landmarks() mp.solutions.drawing_utils Отрисовка ключевых точек image, landmarks, connections, landmark_drawing_spec
DrawingSpec() mp.solutions.drawing_utils Настройка стиля отрисовки color, thickness, circle_radius
.landmark[i] Результаты обработки Доступ к конкретной точке Возвращает объект с координатами x, y, z
.multi_hand_landmarks Результат Hands Список обнаруженных рук Каждый элемент содержит 21 точку
.pose_landmarks Результат Pose Ключевые точки тела 33 точки скелета
.face_landmarks Результат FaceMesh Точки лица 468 точек лицевой сетки

Модуль SelfieSegmentation - Сегментация фона

import cv2
import mediapipe as mp
import numpy as np

mp_selfie = mp.solutions.selfie_segmentation
segmenter = mp_selfie.SelfieSegmentation(model_selection=1)  # 0 - общая модель, 1 - пейзажная

# Загрузка фонового изображения
background = cv2.imread('background.jpg')

cap = cv2.VideoCapture(0)

while cap.isOpened():
    success, frame = cap.read()
    if not success:
        continue
    
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = segmenter.process(frame_rgb)
    
    # Получение маски сегментации
    mask = results.segmentation_mask
    
    # Применение маски для замены фона
    condition = np.stack((mask,) * 3, axis=-1) > 0.1
    
    # Изменение размера фона под размер кадра
    h, w, c = frame.shape
    background_resized = cv2.resize(background, (w, h))
    
    # Замена фона
    output_image = np.where(condition, frame, background_resized)
    
    cv2.imshow("Selfie Segmentation", output_image)
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

Оптимизация производительности

Советы по повышению производительности

# Отключение записи для повышения производительности
frame_rgb.flags.writeable = False
results = hands.process(frame_rgb)
frame_rgb.flags.writeable = True

# Уменьшение разрешения для ускорения обработки
frame_small = cv2.resize(frame, (320, 240))

# Пропуск кадров для экономии ресурсов
frame_count = 0
if frame_count % 2 == 0:  # Обрабатывать каждый второй кадр
    results = hands.process(frame_rgb)
frame_count += 1

Практические применения MediaPipe

Управление презентацией жестами

import cv2
import mediapipe as mp
import pyautogui

class GesturePresentation:
    def __init__(self):
        self.mp_hands = mp.solutions.hands
        self.hands = self.mp_hands.Hands(min_detection_confidence=0.7)
        self.mp_draw = mp.solutions.drawing_utils
        
    def detect_gesture(self, landmarks):
        # Логика распознавания жестов
        fingers = self.count_fingers(landmarks)
        
        if fingers == [0, 1, 0, 0, 0]:  # Указательный палец
            return "NEXT"
        elif fingers == [1, 0, 0, 0, 0]:  # Большой палец
            return "PREVIOUS"
        elif fingers == [0, 1, 1, 0, 0]:  # Два пальца
            return "PAUSE"
        
        return "NONE"
    
    def control_presentation(self, gesture):
        if gesture == "NEXT":
            pyautogui.press('right')
        elif gesture == "PREVIOUS":
            pyautogui.press('left')
        elif gesture == "PAUSE":
            pyautogui.press('space')

Фитнес-трекер с анализом упражнений

class FitnessTracker:
    def __init__(self):
        self.mp_pose = mp.solutions.pose
        self.pose = self.mp_pose.Pose()
        self.exercise_count = 0
        self.stage = None
        
    def analyze_pushup(self, landmarks):
        # Анализ отжиманий по углу в локте
        shoulder = [landmarks[11].x, landmarks[11].y]
        elbow = [landmarks[13].x, landmarks[13].y]
        wrist = [landmarks[15].x, landmarks[15].y]
        
        angle = self.calculate_angle(shoulder, elbow, wrist)
        
        if angle > 160:
            self.stage = "UP"
        elif angle < 90 and self.stage == "UP":
            self.stage = "DOWN"
            self.exercise_count += 1
        
        return self.exercise_count, angle

Часто задаваемые вопросы

Почему results возвращает None?

Это происходит когда MediaPipe не может обнаружить объект (руку, лицо, позу) в кадре. Всегда проверяйте результат перед использованием:

if results.multi_hand_landmarks:
    # Обработка найденных рук
    pass

Как улучшить точность детекции?

Увеличьте значения min_detection_confidence и min_tracking_confidence, улучшите освещение, используйте качественную камеру и избегайте быстрых движений.

Почему координаты точек в диапазоне 0-1?

MediaPipe использует нормализованные координаты для независимости от разрешения. Для получения пиксельных координат умножьте на размеры изображения:

x_pixel = landmark.x * image_width
y_pixel = landmark.y * image_height

Как работать с несколькими объектами?

Используйте циклы для обработки всех обнаруженных объектов:

if results.multi_hand_landmarks:
    for hand_landmarks in results.multi_hand_landmarks:
        # Обработка каждой руки
        pass

Можно ли использовать MediaPipe без OpenCV?

Да, MediaPipe может работать с любыми изображениями в формате numpy array RGB, но OpenCV удобен для работы с камерой и отображением результатов.

Обработка ошибок и отладка

Типичные проблемы и решения

import cv2
import mediapipe as mp

def safe_mediapipe_processing():
    try:
        # Проверка доступности камеры
        cap = cv2.VideoCapture(0)
        if not cap.isOpened():
            raise Exception("Не удается открыть камеру")
        
        mp_hands = mp.solutions.hands
        hands = mp_hands.Hands()
        
        while True:
            success, frame = cap.read()
            if not success:
                print("Не удается получить кадр с камеры")
                continue
            
            # Проверка размера кадра
            if frame.shape[0] == 0 or frame.shape[1] == 0:
                continue
                
            frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            results = hands.process(frame_rgb)
            
            # Безопасная проверка результатов
            if results.multi_hand_landmarks is not None:
                for hand_landmarks in results.multi_hand_landmarks:
                    # Обработка точек
                    pass
            
            cv2.imshow("MediaPipe", frame)
            if cv2.waitKey(1) & 0xFF == 27:
                break
                
    except Exception as e:
        print(f"Ошибка: {e}")
    finally:
        cap.release()
        cv2.destroyAllWindows()

Интеграция с другими библиотеками

Использование с TensorFlow и машинным обучением

import tensorflow as tf
import numpy as np

class MediaPipeML:
    def __init__(self):
        self.mp_hands = mp.solutions.hands
        self.hands = self.mp_hands.Hands()
        self.model = tf.keras.models.load_model('gesture_model.h5')
    
    def extract_features(self, landmarks):
        # Извлечение признаков из координат точек
        features = []
        for landmark in landmarks.landmark:
            features.extend([landmark.x, landmark.y, landmark.z])
        return np.array(features).reshape(1, -1)
    
    def predict_gesture(self, frame):
        results = self.hands.process(frame)
        if results.multi_hand_landmarks:
            for hand_landmarks in results.multi_hand_landmarks:
                features = self.extract_features(hand_landmarks)
                prediction = self.model.predict(features)
                return np.argmax(prediction)
        return None

Развертывание и производство

Оптимизация для продакшена

class ProductionMediaPipe:
    def __init__(self):
        # Настройки для продакшена
        self.mp_hands = mp.solutions.hands
        self.hands = self.mp_hands.Hands(
            static_image_mode=False,
            max_num_hands=1,  # Ограничение для производительности
            min_detection_confidence=0.8,  # Высокая точность
            min_tracking_confidence=0.7
        )
        
        # Кэширование для оптимизации
        self.last_results = None
        self.frame_skip_counter = 0
        
    def process_frame(self, frame):
        # Пропуск кадров для экономии ресурсов
        self.frame_skip_counter += 1
        if self.frame_skip_counter % 2 == 0:
            frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            self.last_results = self.hands.process(frame_rgb)
        
        return self.last_results

Заключение

MediaPipe представляет собой одну из наиболее мощных и доступных библиотек для создания приложений компьютерного зрения. Благодаря высокой точности моделей, оптимизированной производительности и простоте использования, она позволяет разработчикам создавать инновационные решения уровня Google всего за несколько строк кода.

Библиотека идеально подходит для широкого спектра применений: от простых демонстраций до сложных коммерческих продуктов в области AR/VR, фитнеса, игр, систем безопасности и человеко-компьютерного взаимодействия. Кроссплатформенность и активная поддержка Google делают MediaPipe отличным выбором для современных проектов машинного обучения и компьютерного зрения.

С постоянным развитием и добавлением новых возможностей, MediaPipe продолжает устанавливать стандарты в области real-time компьютерного зрения, предоставляя разработчикам мощные инструменты для создания будущего интерактивных технологий.

Новости