Google выпустил кроссплатформенный и настраиваемый набор инструментов для машинного обучения с открытым исходным кодом, который предоставляет решения для машинного обучения для потоковой передачи в Интернете (конечно, его также можно использовать для обычных видео, изображений и т. д.). Заинтересованные студенты могут открыть этот веб-сайт для получения подробной информации:mediapipe.dev/
Он предоставляет функции распознавания и отслеживания, такие как жесты, позы человека, лица, объекты и т. д., а также предоставляет наборы инструментов для таких языков программирования, как C++, Python и JavaScript, а также решения для платформ iOS и Android. взгляните на то, как использовать MediaPipe Предоставленная функция распознавания человеческих жестов использует программирование Python для завершения программы «обнаружения подтягивания».
На компьютер необходимо установить 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
Напишите модуль poseutil.py, этот модуль postutil имеет класс PoseDetector, который предоставляет методы для обнаружения человеческих поз, получения данных о человеческих позах и получения углов человеческих суставов. Код выглядит следующим образом, подробности смотрите в комментариях к коду:
import cv2
import mediapipe as mp
import math
class PoseDetector():
'''
人体姿势检测类
'''
def __init__(self,
static_image_mode=False,
upper_body_only=False,
smooth_landmarks=True,
min_detection_confidence=0.5,
min_tracking_confidence=0.5):
'''
初始化
:param static_image_mode: 是否是静态图片,默认为否
:param upper_body_only: 是否是上半身,默认为否
:param smooth_landmarks: 设置为True减少抖动
:param min_detection_confidence:人员检测模型的最小置信度值,默认为0.5
:param min_tracking_confidence:姿势可信标记的最小置信度值,默认为0.5
'''
self.static_image_mode = static_image_mode
self.upper_body_only = upper_body_only
self.smooth_landmarks = smooth_landmarks
self.min_detection_confidence = min_detection_confidence
self.min_tracking_confidence = min_tracking_confidence
# 创建一个Pose对象用于检测人体姿势
self.pose = mp.solutions.pose.Pose(self.static_image_mode, self.upper_body_only, self.smooth_landmarks,
self.min_detection_confidence, self.min_tracking_confidence)
def find_pose(self, img, draw=True):
'''
检测姿势方法
:param img: 一帧图像
:param draw: 是否画出人体姿势节点和连接图
:return: 处理过的图像
'''
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# pose.process(imgRGB) 会识别这帧图片中的人体姿势数据,保存到self.results中
self.results = self.pose.process(imgRGB)
if self.results.pose_landmarks:
if draw:
mp.solutions.drawing_utils.draw_landmarks(img, self.results.pose_landmarks,
mp.solutions.pose.POSE_CONNECTIONS)
return img
def find_positions(self, img):
'''
获取人体姿势数据
:param img: 一帧图像
:param draw: 是否画出人体姿势节点和连接图
:return: 人体姿势数据列表
'''
# 人体姿势数据列表,每个成员由3个数字组成:id, x, y
# id代表人体的某个关节点,x和y代表坐标位置数据
self.lmslist = []
if self.results.pose_landmarks:
for id, lm in enumerate(self.results.pose_landmarks.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
def find_angle(self, img, p1, p2, p3, draw=True):
'''
获取人体姿势中3个点p1-p2-p3的角度
:param img: 一帧图像
:param p1: 第1个点
:param p2: 第2个点
:param p3: 第3个点
:param draw: 是否画出3个点的连接图
:return: 角度
'''
x1, y1 = self.lmslist[p1][1], self.lmslist[p1][2]
x2, y2 = self.lmslist[p2][1], self.lmslist[p2][2]
x3, y3 = self.lmslist[p3][1], self.lmslist[p3][2]
# 使用三角函数公式获取3个点p1-p2-p3,以p2为角的角度值,0-180度之间
angle = int(math.degrees(math.atan2(y1-y2, x1-x2) - math.atan2(y3-y2, x3-x2)))
if angle < 0:
angle = angle + 360
if angle > 180:
angle = 360 - angle
if draw:
cv2.circle(img, (x1, y1), 8, (0, 255, 255), cv2.FILLED)
cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)
cv2.circle(img, (x3, y3), 8, (0, 255, 255), cv2.FILLED)
cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255, 3))
cv2.line(img, (x2, y2), (x3, y3), (255, 255, 255, 3))
#cv2.putText(img, str(angle), (x2-50, y2+50),cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 255), 2)
return angle
Напишите еще один код posetracking.py.В этом коде вызовите метод, предоставляемый классом PoseDetector файла poseutil.py, чтобы получить угол сгиба левого и правого локтя человеческого тела из видео подтягивания (или видео в реальном времени). видео с камеры). Предположим, мы используем Угол локтя от 170 градусов (при полном расслаблении) до 20 градусов (при подтягивании вверх) для определения стандартного подтягивания, чтобы мы могли определить количество стандартных подтягиваний завершено.
Из рисунка выше видно, что три точки 11, 13 и 15 — это узлы левого плеча, локтя и запястья, а 12, 14 и 16 — узлы правой руки. Полный код выглядит следующим образом:
import cv2
import numpy as np
from poseutil import PoseDetector
# opencv打开一个视频
cap = cv2.VideoCapture('mp4/1.mp4')
# 创建一个PoseDetector类的对象
detector = PoseDetector()
# 方向和完成次数的变量
dir = 0
count = 0
while True:
# 读取视频图片帧
success, img = cap.read()
if success:
# 检测视频图片帧中人体姿势
img = detector.find_pose(img, draw=True)
# 获取人体姿势列表数据
lmslist = detector.find_positions(img)
# 右手肘的角度
right_angle = detector.find_angle(img, 12, 14, 16)
# 以170到20度检测右手肘弯曲的程度
right_per = np.interp(right_angle, (20, 170), (100, 0))
# 进度条高度数据
right_bar = np.interp(right_angle, (20, 170), (200, 400))
# 使用opencv画进度条和写右手肘弯曲的程度
cv2.rectangle(img, (1200, 200), (1220, 400), (0, 255, 0), 3)
cv2.rectangle(img, (1200, int(right_bar)), (1220, 400), (0, 255, 0), cv2.FILLED)
cv2.putText(img, str(int(right_per)) + '%', (1190, 450), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)
# 左手肘的角度
left_angle = detector.find_angle(img, 11, 13, 15)
left_per = np.interp(left_angle, (20, 170), (100, 0))
left_bar = np.interp(left_angle, (20, 170), (200, 400))
cv2.rectangle(img, (500, 200), (520, 400), (0, 255, 0), 3)
cv2.rectangle(img, (500, int(left_bar)), (520, 400), (0, 255, 0), cv2.FILLED)
cv2.putText(img, str(int(left_per)) + '%', (490, 450), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)
# 检测个数,我这里设置的是从20%做到80%,就认为是一个
if (left_per >= 80 and right_per >= 80):
if dir == 0:
count = count + 0.5
dir = 1
if (left_per <= 20 and right_per <= 20):
if dir == 1:
count = count + 0.5
dir = 0
# 在视频上显示完成个数
cv2.putText(img, str(int(count)), (1000, 100), cv2.FONT_HERSHEY_SIMPLEX, 3, (0, 255, 255), 4)
cv2.imshow('Image', img)
else:
break
k = cv2.waitKey(1)
if k == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Запустив код, мы увидим изменение угла 2 локтей и 2 индикаторов выполнения, а также количество выполнений, которые можно использовать для определения количества выполнений стандартных подтягиваний.