Один из способов распознать жесты рук — это пометить руки ориентирами в каждом суставе.
Используя предварительно обученную модель Google MediaPipe Hand Landmarks, мы можем использовать эту функциональность в наших собственных приложениях. Для каждого изображения модель создает 20 ориентиров, соответствующих разным точкам на руке.
Для начала откройте новый блокнот или редактор кода!
Установить пакеты и модель вывода
!pip install -q mediapipe==0.10.0 !wget -q <https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task>
Первая строка устанавливает mediapipe в нашу среду, а другая устанавливает предварительно обученную модель Google под названием «hand_landmarker.task».
Установить зависимости
import os import numpy as np import cv2 import time import mediapipe as mp from mediapipe.tasks import python from mediapipe.tasks.python import vision from mediapipe import solutions from mediapipe.framework.formats import landmark_pb2
Функция отображения
Этот код точно такой же, как в примере кода Google.
Функция получает изображение и набор точек, идентифицированных на изображении. Затем он перебирает каждую точку и рисует как точки, так и соединительные линии между ними. Наконец, он пишет текст «левый» и/или «правый», чтобы указать, является ли ориентир левой или правой рукой.
MARGIN = 10 # pixels FONT_SIZE = 1 FONT_THICKNESS = 1 HANDEDNESS_TEXT_COLOR = (88, 205, 54) # vibrant green def draw_landmarks_on_image(rgb_image, detection_result): hand_landmarks_list = detection_result.hand_landmarks handedness_list = detection_result.handedness annotated_image = np.copy(rgb_image) # Loop through the detected hands to visualize. for idx in range(len(hand_landmarks_list)): hand_landmarks = hand_landmarks_list[idx] handedness = handedness_list[idx] # Draw the hand landmarks. hand_landmarks_proto = landmark_pb2.NormalizedLandmarkList() hand_landmarks_proto.landmark.extend([ landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in hand_landmarks ]) solutions.drawing_utils.draw_landmarks( annotated_image, hand_landmarks_proto, solutions.hands.HAND_CONNECTIONS, solutions.drawing_styles.get_default_hand_landmarks_style(), solutions.drawing_styles.get_default_hand_connections_style()) # Get the top left corner of the detected hand's bounding box. height, width, _ = annotated_image.shape x_coordinates = [landmark.x for landmark in hand_landmarks] y_coordinates = [landmark.y for landmark in hand_landmarks] text_x = int(min(x_coordinates) * width) text_y = int(min(y_coordinates) * height) - MARGIN # Draw handedness (left or right hand) on the image. cv2.putText(annotated_image, f"{handedness[0].category_name}", (text_x, text_y), cv2.FONT_HERSHEY_DUPLEX, FONT_SIZE, HANDEDNESS_TEXT_COLOR, FONT_THICKNESS, cv2.LINE_AA) return annotated_image
Обнаружение ориентира руки
Этот код адаптирован из примера кода Google.
Во-первых, мы указываем, какую модель использовать (наша загруженная и предварительно обученная модель). Затем мы указываем, чтобы использовать базовые параметры и что модель должна найти максимум две руки. Наконец, мы создаем детектор, чтобы делать выводы.
Я извлек часть предсказания в свою собственную функцию.
Одним из дополнений является первая строка в функции get_annotation_from
, которая преобразует кадр OpenCV в объект изображения MediaPipe.
# Setup options base_options = python.BaseOptions(model_asset_path='hand_landmarker.task') options = vision.HandLandmarkerOptions(base_options=base_options, num_hands=2) detector = vision.HandLandmarker.create_from_options(options) # Get inference def get_annotation_from(frame): image = mp.Image(image_format=mp.ImageFormat.SRGB, data=frame) detection_result = detector.detect(image) annotated_image = draw_landmarks_on_image(image.numpy_view(), detection_result) return detection_result, annotated_image
Захват видео
Используя OpenCV, мы можем захватывать кадры, анализировать их, а затем отображать окончательное аннотированное изображение.
Возможно, вам придется поэкспериментировать со значением внутри функции VideoCapture
, чтобы найти камеру. Мы запускаем цикл while True
для непрерывного получения кадров, пока не решим нажать клавишу «q» и выйти.
# define a video capture object cap = cv2.VideoCapture(0) while True: # capture image ret, frame = cap.read() if ret: detection_result, annotation = get_annotation_from(cv2.flip(frame, 1)) cv2.imshow('', annotation) else: print("! No frame") time.sleep(0.05) if cv2.waitKey(1) & 0xFF == ord('q'): break # After the loop release the cap object cap.release() # Destroy all the windows cv2.destroyAllWindows()
Вот и все!
Потрясающая работа! Теперь вы сможете запустить программу и получить вывод о наземных ориентирах в реальном времени! 😄