Python играет с искусственным интеллектом: распознавание чисел жестов

Python

Распознавайте номера жестов с помощью программирования на Python

Google выпустил кроссплатформенный и настраиваемый набор инструментов для машинного обучения с открытым исходным кодом, который предоставляет решения для машинного обучения для потоковой передачи в Интернете (конечно, его также можно использовать для обычных видео, изображений и т. д.). Заинтересованные студенты могут открыть этот веб-сайт для получения подробной информации:mediapipe.dev/

image-20210422112313073

Он предоставляет функции распознавания и отслеживания, такие как жесты, позы человека, лица, объекты и т. д., а также предоставляет наборы инструментов для таких языков программирования, как C++, Python и JavaScript, а также решения для платформ iOS и Android. взгляните на то, как использовать MediaPipe Обеспечивает распознавание жестов, чтобы написать код Python для распознавания чисел в жестах: 0-5.

hand_crops.png

Готов к работе

На компьютер необходимо установить Python3, и рекомендуется установить версию Python3.8.x. Кроме того, вам также необходимо установить Opencv-Python, MediaPipe и несколько наборов инструментов, которые можно установить с помощью pip:

pip install mediapipe numpy opencv-python

Мой компьютер - Python3.8.3, а версии инструментария:

mediapipe==0.8.3.1
numpy==1.20.2
opencv-python==4.5.1.48

Подготовьте 6 картинок, каждая из которых представляет собой изображение 6 рук.

image-20210424155201904.png

Программирование

  1. Напишите модуль handutil.py, этот модуль handutil имеет класс HandDetector, который предоставляет методы для обнаружения жестов и получения данных о жестах. Код выглядит следующим образом, подробное объяснение см. в комментариях к коду:
import cv2
import mediapipe as mp


class HandDetector():
    '''
    手势识别类
    '''
    def __init__(self, mode=False, max_hands=2, detection_con=0.5, track_con=0.5):
        '''
        初始化
        :param mode: 是否静态图片,默认为False
        :param max_hands: 最多几只手,默认为2只
        :param detection_con: 最小检测信度值,默认为0.5
        :param track_con: 最小跟踪信度值,默认为0.5
        '''
        self.mode = mode
        self.max_hands = max_hands
        self.detection_con = detection_con
        self.track_con = track_con

        self.hands = mp.solutions.hands.Hands(self.mode, self.max_hands, self.detection_con, self.track_con)

    def find_hands(self, img, draw=True):
        '''
        检测手势
        :param img: 视频帧图片
        :param draw: 是否画出手势中的节点和连接图
        :return: 处理过的视频帧图片
        '''
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 处理图片,检测是否有手势,将数据存进self.results中
        self.results = self.hands.process(imgRGB)
        if draw:
            if self.results.multi_hand_landmarks:
                for handlms in self.results.multi_hand_landmarks:
                    mp.solutions.drawing_utils.draw_landmarks(img, handlms, mp.solutions.hands.HAND_CONNECTIONS)
        return img

    def find_positions(self, img, hand_no=0):
        '''
        获取手势数据
        :param img: 视频帧图片
        :param hand_no: 手编号(默认第1只手)
        :return: 手势数据列表,每个数据成员由id, x, y组成,代码这个手势位置编号以及在屏幕中的位置
        '''
        self.lmslist = []
        if self.results.multi_hand_landmarks:
            hand = self.results.multi_hand_landmarks[hand_no]
            for id, lm in enumerate(hand.landmark):
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                self.lmslist.append([id, cx, cy])

        return self.lmslist
  1. Напишите еще один код fingercount.py. В этом коде вызовите метод, предоставляемый классом HandDetector файла handutil.py, чтобы получить данные жеста. Данные каждого жеста состоят из трех чисел: id, x, y, соответственно представляющих один из жестов Point и x\y координатное положение этой точки. На следующем рисунке представлено описание части руки, соответствующей каждому идентификатору при распознавании жестов.

hand_landmarks.png

Как видно из рисунка выше: 4, 8, 12, 16, 20 обозначают кончики большого, указательного, среднего, безымянного и мизинца соответственно. Полный код выглядит следующим образом:

import cv2
from handutil import HandDetector

# 打开摄像头
cap = cv2.VideoCapture(1)
# 创建一个手势识别对象
detector = HandDetector()

# 6张手的图片,分别代表0~5
finger_img_list = [
    'fingers/0.png',
    'fingers/1.png',
    'fingers/2.png',
    'fingers/3.png',
    'fingers/4.png',
    'fingers/5.png',
]
finger_list = []
for fi in finger_img_list:
    i = cv2.imread(fi)
    finger_list.append(i)

# 指尖列表,分别代表大拇指、食指、中指、无名指和小指的指尖
tip_ids = [4, 8, 12, 16, 20]

while True:
    success, img = cap.read()

    if success:
        # 检测手势
        img = detector.find_hands(img, draw=True)
        # 获取手势数据
        lmslist = detector.find_positions(img)
        if len(lmslist) > 0:
            fingers = []
            for tid in tip_ids:
                # 找到每个指尖的位置
                x, y = lmslist[tid][1], lmslist[tid][2]
                cv2.circle(img, (x, y), 10, (0, 255, 0), cv2.FILLED)
                # 如果是大拇指,如果大拇指指尖x位置大于大拇指第二关节的位置,则认为大拇指打开,否则认为大拇指关闭
                if tid == 4:
                    if lmslist[tid][1] > lmslist[tid - 1][1]:
                        fingers.append(1)
                    else:
                        fingers.append(0)
                # 如果是其他手指,如果这些手指的指尖的y位置大于第二关节的位置,则认为这个手指打开,否则认为这个手指关闭
                else:
                    if lmslist[tid][2] < lmslist[tid - 2][2]:
                        fingers.append(1)
                    else:
                        fingers.append(0)
            # fingers是这样一个列表,5个数据,0代表一个手指关闭,1代表一个手指打开
            # 判断有几个手指打开
            cnt = fingers.count(1)
            # 找到对应的手势图片并显示
            finger_img = finger_list[cnt]
            w, h, c = finger_img.shape
            img[0:w, 0:h] = finger_img
            cv2.rectangle(img, (200, 0), (300, 100), (0, 255, 0), cv2.FILLED)
            cv2.putText(img, str(cnt), (200, 100), cv2.FONT_HERSHEY_DUPLEX, 5, (0, 0, 255))

        cv2.imshow('Image', img)

    k = cv2.waitKey(1)
    if k == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

Запустив код, мы видим, что цифра в жесте может быть распознана, и отображается соответствующая картинка и цифра.

image-20210424155406430.png

image-20210424155433600.png

image-20210424155459651.png

image-20210424155517619.png

image-20210424155550759.png

image-20210424155607893.png

Добро пожаловать в официальный аккаунт «Клуба программистов», чтобы узнать больше веселого и интересного программирования.