Mediapipe三维实时人体关键点检测与追踪(二)

本文涉及的产品
视觉智能开放平台,视频资源包5000点
视觉智能开放平台,图像资源包5000点
视觉智能开放平台,分割抠图1万点
简介: Mediapipe三维实时人体关键点检测与追踪(二)

1.Mediapipe动作计数


前面上文,我们已经知道了,人体姿态的动作,是通过3个关节点加二个人体支干,组成的关节角度,来判断动作的。


所以识别某一个具体的动作,我们只需要找出人体做出指定动作的最明显的肢体部位,比如说,人体做下蹲的时候,最明显的特征可以识别出这个动作的肢体就是大腿和小腿。


等我们找到对面的肢体部位,将对应的部位,映射到mediapipe的具体关节点,比如说引体向上,对应的肢体就是我们的手臂。


image.png

手臂对应到Mediapipe中的索引号是16,14,12(左臂)11,13,15(右臂)。可以看下,做引体向上,角度(16-14-12)的夹角,角度(11-13-15)的夹角会在引体向上过程中发生变化。


44f8354fa9614928875db7e1d819c421.png


具体动作计数步骤:

  1. 先识别出人体的姿态
  2. 计算关键肢体位置的角度
  3. 我们通过记录肢体角度的变化,来对动作进计数


2.动作计数


2.1 俯卧撑


要想做好不同动作识别,最关键就是找到做动作,肢体变化最明显的部位。

比如说俯卧撑,可以看出人的手臂和躯干在变化

9e590b23f64e47e39c67e4fd3ac61ef7.png

对应到mediapipe的部位编号就是16,14,12(左臂),15,13,11(右臂),12,24,26(躯干)


有了动作计数,我们还需要有一个动作完成进度,因为每一个动作都是从初始动作一点点,变化到标准动作位置。对应的肢体角度也是一点点的变化的。


因此我们需要一个动作进度条。这里使用一种函数np.interp()线性插值。


函数解释:

np.interp(angle,(x1,y1),(x2,y2))


angle:就是对应我们通过mediapipe得到的肢体夹角,角度

(x1,y1):可以理解为angle的角度变化的范围

(x2,y2):可以理解为通过角度的数值,映射到进度条的数值的范围,类似于m=2n,n的取值范围就是角度的范围,m的取值范围就是进度条的取值范围。

最后返回一个进度条数值。


angle:就是对应我们通过mediapipe得到的肢体夹角,角度

(x1,y1):可以理解为angle的角度变化的范围(x2,y2):可以理解为通过角度的数值,映射到进度条的数值的范围,类似于m=2n,n的取值范围就是角度的范围,m的取值范围就是进度条取值范围。最后返回一个进度条数值。


# 导入opencv工具包
import cv2
# 导入numpy
import numpy as np
# 导入姿势识别器
from poseutil import PoseDetector
# 打开视频文件
cap = cv2.VideoCapture('videos.mp4')
# 姿势识别器
detector = PoseDetector()
# 方向与个数
dir = 0  # 0为下,1为上
count = 0
# 视频宽度高度
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 录制视频设置
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('videos.mp4', fourcc, 30.0, (width, height))
while True:
    # 读取摄像头,img为每帧图片
    success, img = cap.read()
    if success:
        h, w, c = img.shape
        # 识别姿势
        img = detector.find_pose(img, draw=True)
        # 获取姿势数据
        positions = detector.find_positions(img)
        if positions:
            # 获取俯卧撑的角度
            angle1 = detector.find_angle(img, 12, 24, 26)
            angle2 = detector.find_angle(img, 12, 14, 16)
            # 进度条长度
            bar = np.interp(angle2, (45, 150), (w // 2 - 100, w // 2 + 100))
            cv2.rectangle(img, (w // 2 - 100, h - 150), (int(bar), h - 100), (0, 255, 0), cv2.FILLED)
            # 角度小于50度认为撑下
            if angle2 <= 50 and angle1 >= 165 and angle1 <= 175:
                if dir == 0:
                    count = count + 0.5
                    dir = 1
            # 角度大于125度认为撑起
            if angle2 >= 125 and angle1 >= 165 and angle1 <= 175:
                if dir == 1:
                    count = count + 0.5
                    dir = 0
            cv2.putText(img, str(int(count)), (w // 2, h // 2), cv2.FONT_HERSHEY_SIMPLEX, 10, (255, 255, 255), 20, cv2.LINE_AA)
        # 打开一个Image窗口显示视频图片
        cv2.imshow('Image', img)
        # 录制视频
        out.write(img)
    else:
        # 视频结束退出
        break
    # 如果按下q键,程序退出
    key = cv2.waitKey(1)
    if key == ord('q'):
        break
# 关闭视频保存器
out.release()
# 关闭摄像头
cap.release()
# 关闭程序窗口
cv2.destroyAllWindows()

2.2 引体向上


同样的引体向上也可以做

引体向上对应到mediapipe的部位编号就是16,14,12(左臂),15,13,11(右臂)

import cv2
import numpy as np
from poseutil import PoseDetector
# opencv打开一个视频
cap = cv2.VideoCapture('video.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.3 仰卧起坐


仰卧起坐对应到mediapipe的部位编号就是11,23,25(右侧躯干),12,24,26(左侧躯干)

# 导入opencv工具包
import cv2
# 导入numpy
import numpy as np
# 导入姿势识别器
from poseutil import PoseDetector
# 打开视频文件
cap = cv2.VideoCapture('videos.mp4')
# 姿势识别器
detector = PoseDetector()
# 方向与个数
dir = 0  # 0为躺下,1为坐起
count = 0
while True:
    # 读取摄像头,img为每帧图片
    success, img = cap.read()
    if success:
        h, w, c = img.shape
        # 识别姿势
        img = detector.find_pose(img, draw=True)
        # 获取姿势数据
        positions = detector.find_positions(img)
        if positions:
            # 获取仰卧起坐的角度
            angle = detector.find_angle(img, 11, 23, 25)
            # 进度条长度
            bar = np.interp(angle, (50, 130), (w // 2 - 100, w // 2 + 100))
            cv2.rectangle(img, (w // 2 - 100, h - 150), (int(bar), h - 100), (0, 255, 0), cv2.FILLED)
            # 角度小于55度认为坐起
            if angle <= 55:
                if dir == 0:
                    count = count + 0.5
                    dir = 1
            # 角度大于120度认为躺下
            if angle >= 120:
                if dir == 1:
                    count = count + 0.5
                    dir = 0
            cv2.putText(img, str(int(count)), (w // 2, h // 2), cv2.FONT_HERSHEY_SIMPLEX, 10, (255, 255, 255), 20, cv2.LINE_AA)
        # 打开一个Image窗口显示视频图片
        cv2.imshow('Image', img)
    else:
        # 视频结束退出
        break
    # 如果按下q键,程序退出
    key = cv2.waitKey(1)
    if key == ord('q'):
        break
# 关闭摄像头
cap.release()
# 关闭程序窗口
cv2.destroyAllWindows()


2.3 下蹲


下蹲对应mediapipe的部位编号就是24,26,28(左腿),23,25,27(右腿)


# 导入opencv工具包
import cv2
# 导入numpy
import numpy as np
# 导入姿势识别器
from poseutil import PoseDetector
# 打开视频文件
cap = cv2.VideoCapture('videos.mp4')
# 姿势识别器
detector = PoseDetector()
# 方向与个数
dir = 0  # 0为站立,1为蹲下
count = 0
while True:
    # 读取摄像头,img为每帧图片
    success, img = cap.read()
    if success:
        h, w, c = img.shape
        # 识别姿势
        img = detector.find_pose(img, draw=True)
        # 获取姿势数据
        positions = detector.find_positions(img)
        if positions:
            # 获取仰卧起坐的角度
            angle = detector.find_angle(img, 24, 26, 28)
            # 进度条长度
            bar = np.interp(angle, (50, 170), (w // 2 - 100, w // 2 + 100))
            cv2.rectangle(img, (w // 2 - 100, h - 150), (int(bar), h - 100), (0, 255, 0), cv2.FILLED)
            # 角度小于55度认为下蹲
            if angle <= 55:
                if dir == 0:
                    count = count + 0.5
                    dir = 1
            # 角度大于120度认为站立
            if angle >= 120:
                if dir == 1:
                    count = count + 0.5
                    dir = 0
            cv2.putText(img, str(int(count)), (w // 2, h // 2), cv2.FONT_HERSHEY_SIMPLEX, 10, (255, 255, 255), 20, cv2.LINE_AA)
        # 打开一个Image窗口显示视频图片
        cv2.imshow('Image', img)
    else:
        # 视频结束退出
        break
    # 如果按下q键,程序退出
    key = cv2.waitKey(1)
    if key == ord('q'):
        break
# 关闭摄像头
cap.release()
# 关闭程序窗口
cv2.destroyAllWindows()
相关文章
|
固态存储 计算机视觉 异构计算
一起来学MediaPipe(一)人脸及五官定位检测
一起来学MediaPipe(一)人脸及五官定位检测
3342 0
一起来学MediaPipe(一)人脸及五官定位检测
|
4月前
|
计算机视觉
在yolov5项目中如何使用自带摄像机不用网络摄像机进行实时检测?
这篇文章讨论了在yolov5项目中,如何避免使用网络摄像机而改用自带的本地摄像机进行实时目标检测,并提供了解决摄像头打开错误的具体步骤和代码示例。
在yolov5项目中如何使用自带摄像机不用网络摄像机进行实时检测?
|
5月前
人脸关键点检测
【7月更文挑战第31天】人脸关键点检测。
37 3
|
6月前
|
机器学习/深度学习 存储 算法
基于YOLOv8与ByteTrack的车辆行人多目标检测与追踪系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、运动物体追踪
基于YOLOv8与ByteTrack的车辆行人多目标检测与追踪系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、运动物体追踪
|
6月前
|
机器学习/深度学习 存储 编解码
基于YOLOv8与ByteTrack的车辆检测追踪与流量计数系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、车辆检测追踪、过线计数、流量统计(2)
基于YOLOv8与ByteTrack的车辆检测追踪与流量计数系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、车辆检测追踪、过线计数、流量统计
|
6月前
|
机器学习/深度学习 算法 计算机视觉
基于YOLOv8与ByteTrack的车辆检测追踪与流量计数系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、车辆检测追踪、过线计数、流量统计(3)
基于YOLOv8与ByteTrack的车辆检测追踪与流量计数系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、车辆检测追踪、过线计数、流量统计
|
6月前
|
机器人 人机交互 vr&ar
实战 | 实时手部关键点检测跟踪(附完整源码+代码详解)
实战 | 实时手部关键点检测跟踪(附完整源码+代码详解)
|
6月前
|
机器学习/深度学习 监控 算法
基于YOLOv8与ByteTrack的车辆检测追踪与流量计数系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、车辆检测追踪、过线计数、流量统计(1)
基于YOLOv8与ByteTrack的车辆检测追踪与流量计数系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标追踪、车辆检测追踪、过线计数、流量统计
|
7月前
|
机器学习/深度学习 传感器 算法
目标检测+车道线识别+追踪+测距(代码+部署运行)
目标检测+车道线识别+追踪+测距(代码+部署运行)
|
机器学习/深度学习 JavaScript 前端开发
Mediapipe三维实时人体关键点检测与追踪(一)
Mediapipe三维实时人体关键点检测与追踪(一)
1579 0

热门文章

最新文章