Распознавайте номера жестов с помощью программирования на Python
Google выпустил кроссплатформенный и настраиваемый набор инструментов для машинного обучения с открытым исходным кодом, который предоставляет решения для машинного обучения для потоковой передачи в Интернете (конечно, его также можно использовать для обычных видео, изображений и т. д.). Заинтересованные студенты могут открыть этот веб-сайт для получения подробной информации:mediapipe.dev/
Он предоставляет функции распознавания и отслеживания, такие как жесты, позы человека, лица, объекты и т. д., а также предоставляет наборы инструментов для таких языков программирования, как C++, Python и JavaScript, а также решения для платформ iOS и Android. взгляните на то, как использовать MediaPipe Обеспечивает распознавание жестов, чтобы написать код Python для распознавания чисел в жестах: 0-5.
Готов к работе
На компьютер необходимо установить 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 рук.
Программирование
- Напишите модуль 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
- Напишите еще один код fingercount.py. В этом коде вызовите метод, предоставляемый классом HandDetector файла handutil.py, чтобы получить данные жеста. Данные каждого жеста состоят из трех чисел: id, x, y, соответственно представляющих один из жестов Point и x\y координатное положение этой точки. На следующем рисунке представлено описание части руки, соответствующей каждому идентификатору при распознавании жестов.
Как видно из рисунка выше: 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()
Запустив код, мы видим, что цифра в жесте может быть распознана, и отображается соответствующая картинка и цифра.
Добро пожаловать в официальный аккаунт «Клуба программистов», чтобы узнать больше веселого и интересного программирования.