0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用MediaPipe Pose构建一个俯卧撑计数器

科技观察员 来源:circuitdigest 作者:Ashish Choudhary 2022-07-28 17:16 次阅读

由于最近虚拟现实和增强现实的增长和普及,人体姿态估计技术变得越来越流行。在我们之前的教程中,我们使用了 Media pipe Hand Tracking 模块来使用手势控制 Raspberry Pi 媒体播放器。在这个项目中,我们将使用MediaPipe Pose 估计包来构建一个俯卧撑。我们将使用姿势估计包来获取肩膀和肘部的坐标。肩部坐标将与肘部坐标进行比较。因此,如果肩膀与肘部处于同一水平或低于肘部,则将被视为俯卧撑。我们还将扬声器连接到 Raspberry Pi 以告知俯卧撑的计数。

俯卧撑计数所需的组件

树莓派 4

Pi 相机模块

扬声器

在这里,我们只需要安装了 OpenCV 和 MediaPipe 的 Raspberry Pi 4 和 Pi 摄像头模块。 OpenCV 用于 数字图像处理,而 MediaPipe 用于 Pose 估计。数字图像处理最常见的应用是 物体检测、 人脸识别和 人数统计。

什么是媒体管道?

MediaPipe是一个框架,用于构建跨平台(即 AndroidiOS、Web、边缘设备)多模式(即视频音频或任何时间序列数据)应用机器学习管道,包括快速 ML 推理、经典计算机视觉和媒体处理(例如视频解码)。MediaPipe 发布了各种预构建的 Python 和其他语言包,例如:

物体检测

人脸检测

手部追踪

姿势估计

多手追踪

头发分割

MediaPipePython 包可用于 Linux、macOS 和 Windows 的 PyPI。使用以下命令在 Raspberry Pi 4 上安装 MediaPipe:

须藤 pip3 安装 mediapipe-rpi4

如果您没有 Pi 4,则可以使用以下命令将其安装在 Raspberry Pi 3 上:

须藤 pip3 安装 mediapipe-rpi3

安装 OpenCV

在安装 OpenCV 和其他依赖项之前,Raspberry Pi 需要完全更新。使用以下命令将 Raspberry Pi 更新到其最新版本:

sudo apt-get 更新

然后使用以下命令安装在 Raspberry Pi 上安装 OpenCV 所需的依赖项。

sudo apt-get install libhdf5-dev -y 
sudo apt-get install libhdf5-serial-dev –y 
sudo apt-get install libatlas-base-dev –y 
sudo apt-get install libjasper-dev -y 
sudo apt-get install libqtgui4 –y 
sudo apt-get install libqt4-test –y

之后,使用以下命令在您的 Raspberry Pi 上安装 OpenCV。

pip3 安装 opencv-contrib-python==4.1.0.25

为上推计数器编程 Raspberry Pi

文档末尾给出了使用 OpenCV 上推计数器的完整代码。在这里,我们将解释代码的重要部分以便更好地解释。

通过导入 OpenCV 和 MediaPipe 包来启动代码。如前所述,MediaPipe 是 Pose 估计的核心包,而 OpenCV 用于图像处理。

导入简历2
将媒体管道导入为 mp

在接下来的几行中,我们创建了两个新变量。第一个是mp_drawing,它将用于从 MediaPipe Python 包中获取所有绘图实用程序,第二个是mp_pose,用于导入姿势估计模型。

mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose

之后,定义一个名为findPosition() 的函数。顾名思义,它用于查找所有身体标志的 X、Y 坐标,如肩膀、眼睛等。所有标志的坐标将存储在名为lmList[]的变量中。

def findPosition(图像,绘制=真):
  lmList = []
  如果结果.pose_landmarks:
      mp_drawing.draw_landmarks(
         图像,results.pose_landmarks,mp_pose.POSE_CONNECTIONS)
      对于 id, lm in enumerate(results.pose_landmarks.landmark):
          h, w, c = image.shape
          cx, cy = int(lm.x * w), int(lm.y * h)
          lmList.append([id, cx, cy])
  返回 lmList

然后从 Raspberry Pi 摄像头开始视频流。您甚至可以使用预先录制的视频,而不是使用实时流。为此,将“0”替换为视频路径。

上限 = cv2.VideoCapture(0)
#cap = cv2.VideoCapture(“我的视频.mp4”)

然后在下一行,为 mediapipe feed 设置一个新实例,以访问我们之前导入的姿势估计模型。我们还传递了两个关键字参数,即最小检测置信度和最小跟踪置信度。接下来,我们将读取视频帧并将它们存储在 image 变量中。

以 mp_pose.Pose(min_detection_confidence=0.7, min_tracking_confidence=0.7) 作为姿势:

  而 cap.isOpened():
     成功,图像 = cap.read()
     图像 = cv2.resize(图像, (1280, 720))

我们从视频源获得的图像最初是 BGR 格式。S,在这一行中,我们将首先将图像水平翻转以供稍后的自拍视图显示,然后将BGR图像转换为RGB。

图像 = cv2.cvtColor(cv2.flip(图像, 1), cv2.COLOR_BGR2RGB)

之后,我们将通过姿势估计模型传递图像以进行检测并将结果存储在一个名为“结果”的变量中。然后我们将 BGR 图像转换为 RGB。

结果=姿势.过程(图像)
图像 = cv2.cvtColor(图像,cv2.COLOR_BGR2RGB)

现在我们得到了检测结果,我们将调用findPosition()函数在图像上绘制这些检测,并使用我们之前导入的绘图实用程序连接所有检测。

mp_drawing.draw_landmarks(图像,results.pose_landmarks,mp_pose.POSE_CONNECTIONS)

之后,我们会将所有检测的 id 和坐标存储在一个名为 lmList 的变量中。

lmList = findPosition(图像,绘制=真)

然后在接下来的几行中,我们将首先获取两个肩膀的坐标,然后在上面画圆。如下图所示,左右肩的 id 分别为 12 和 11。

pYYBAGLiU3aAPr2ZAALbCygmyCo696.png

如果 len(lmList) != 0:

      cv2.circle(图像, (lmList[12][1], lmList[12][2]), 20, (0, 0, 255), cv2.FILLED)
      cv2.circle(图像, (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED)
      cv2.circle(图像, (lmList[12][1], lmList[12][2]), 20, (0, 0, 255), cv2.FILLED)
      cv2.circle(图像, (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED)

现在,当我们找到肩膀的坐标时,我们将把这些坐标与两个肘部的坐标进行比较。所以,如果肩膀与肘部在同一水平或在肘部以下,我们将阶段设置为“向下”,当肩膀在肘部以上时,阶段将变为向上,这将被视为俯卧撑.

      如果(lmList[12][2] 和 lmList[11][2] >= lmList[14][2] 和 lmList[13][2]):
        cv2.circle(图像, (lmList[12][1], lmList[12][2]), 20, (0, 255, 0), cv2.FILLED)
        cv2.circle(图像, (lmList[11][1], lmList[11][2]), 20, (0, 255, 0), cv2.FILLED)
        阶段=“下降”
      if (lmList[12][2] and lmList[11][2] <= lmList[14][2] and lmList[13][2]) and stage == "down":
        阶段=“向上”
        计数器 += 1
        打印(计数器)

现在,随着俯卧撑的计数,我们将使用cv2.putText() 在视频流上打印俯卧撑计数。

text = "{}:{}".format("俯卧撑", counter)
    cv2.putText(图像, 文本, (10, 40), cv2.FONT_HERSHEY_SIMPLEX,
                1, (255, 0, 0), 2)
    cv2.imshow('MediaPipe 姿势', image)

最后,我们将视频流保存在我们的项目文件夹中。

    如果创建是无:
      fourcc = cv2.VideoWriter_fourcc(*'XVID')
      create = cv2.VideoWriter(opname,fourcc, 30, (image.shape[1], image.shape[0]), True)
    create.write(图像)

测试上推计数器脚本

现在 Push Up 计数器脚本已准备就绪,让我们继续测试它。有两种测试方法。您可以使用预先录制的视频,也可以使用 Pi 相机进行实时视频流。在这里,我们将使用 Pi 摄像头模块,因此,将 Raspberry Pi 摄像头模块与 Pi 连接,如下所示:

poYBAGLiU3GAGyLjAAWQK_s986M552.png

现在,检查 Pi 相机是否正常工作。查看相机后,启动 python 脚本,您会发现弹出一个窗口,其中包含您的视频源。最初做俯卧撑时,肩膀上的点将是红色:

pYYBAGLiU22AFxJFAAYLSWKkCgg804.png

当肩膀低于肘部时,点将从红色变为绿色,俯卧撑计数将增加一。

pYYBAGLiU2aAVasbAAWRmbXSh-E573.png

这就是您可以使用 MediaPipe 计算俯卧撑的方法。您还可以使用此库来计算仰卧起坐或任何其他锻炼。下面给出了完整的工作视频和代码。

代码

import cv2

import mediapipe as mp

import os

mp_drawing = mp.solutions.drawing_utils

mp_pose = mp.solutions.pose

counter = 0

stage = None

create = None

opname = “output.avi”

def findPosition(image, draw=True):

lmList = []

if results.pose_landmarks:

mp_drawing.draw_landmarks(

image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)

for id, lm in enumerate(results.pose_landmarks.landmark):

h, w, c = image.shape

cx, cy = int( lm.x * w), int(lm.y * h)

lmList.append([id, cx, cy])

#cv2.circle(image, (cx, cy), 5, (255, 0, 0), cv2.填充)

返回 lmList

cap = cv2.VideoCapture(0)

与 mp_pose.Pose(

min_detection_confidence=0.7,

min_tracking_confidence=0.7) 作为姿势:

而 cap.isOpened():

成功,image = cap.read()

image = cv2.resize(image, (640,480))

if not success:

print(“Ignoring empty camera frame.”)

# 如果加载视频,使用 ‘break’ 而不是 ‘continue’。

continue

# 水平翻转图像以供稍后的自拍视图显示,并将

# BGR 图像转换为 RGB。

image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)

# 为了提高性能,可选择将图像标记为不可写入

# 通过引用传递。

results = pose.process(image)

# 在图像上绘制姿态标注。

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

lmList = findPosition(image, draw=True)

if len(lmList) != 0:

cv2.circle(image, (lmList[12][1], lmList[12] [2]), 20, (0, 0, 255), cv2.FILLED)

cv2.circle(image, (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED)

cv2.circle(image, (lmList[12][1], lmList[12][2]), 20, (0, 0, 255), cv2.FILLED)

cv2.circle(image , (lmList[11][1], lmList[11][2]), 20, (0, 0, 255), cv2.FILLED)

if (lmList[12][2] 和 lmList[11][2] 》= lmList[14][2] 和 lmList[13][2]):

cv2.circle(image, (lmList[12][1], lmList[12][2]), 20, (0, 255, 0), cv2.FILLED)

cv2.circle(image, (lmList[11][ 1], lmList[11][2]), 20, (0, 255, 0), cv2.FILLED)

stage = “down”

if (lmList[12][2] and lmList[11][2] 《= lmList[14][2] 和 lmList[13][2]) 和 stage == “down”:

stage = “up”

counter += 1

counter2 = str(int(counter))

print(counter)

os.system( “echo ‘” + counter2 + “’ | festival --tts”)

text = “{}:{}”.format(“Push Ups”, counter)

cv2.putText(image, text, (10, 40), cv2 .FONT_HERSHEY_SIMPLEX,

1, (255, 0, 0), 2)

cv2.imshow(‘MediaPipe Pose’, image)

如果 create 为 None:

fourcc = cv2.VideoWriter_fourcc(*‘XVID’)

create = cv2.VideoWriter(opname,fourcc, 30, (image.shape[1], image.shape[0]), True)

create.write(image)

key = cv2 .waitKey(1) & 0xFF

# 如果 `q` 键被按下,则退出循环

if key == ord(“q”):

break

# 做一些清理

cv2.destroyAllWindows()

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 扬声器
    +关注

    关注

    29

    文章

    1214

    浏览量

    60189
  • 计数器
    +关注

    关注

    32

    文章

    2123

    浏览量

    92987
收藏 人收藏

    评论

    相关推荐

    构建一个4位二进制计数器

    构建一个4位二进制计数器计数范围从0到15(包括0和15),计数周期为16。同步复位输入时,将计数器重置为0。
    的头像 发表于 12-02 09:20 3405次阅读

    利用局部变量写计数器

    利用局部变量写计数器,每当VI运行计数器就加。当VI关闭后重新打开时,
    发表于 11-12 14:29

    伦敦街头的“俯卧撑”巴士

    ` 近日,捷克艺术家David Cerny设计并制造了辆会做俯卧撑的双层大巴。它是由伦敦街头的经典双层巴士改造而成,在伦敦奥运会期间它被摆放在捷克奥运代表团总部外,最后张图片您可以看到,
    发表于 08-07 12:01

    如何构建具有同步复位端的CMOS四进制计数器

    如何构建具有同步复位端的CMOS四进制计数器?输入端 复位控制信号RESET 时钟信号clk输出端 Q3 Q2 Q1 Q0 carry
    发表于 12-10 17:56

    如何设计实际可用的计数器

    我需要设计计数器,时钟变化几十计数次。我先用了
    发表于 03-14 16:49

    定时/计数器的原理是什么

    定时/计数器实质上是加1计数器计数值是存在THX,TLX(X取0或1)这28位的寄存
    发表于 07-19 07:20

    如何使用D触发和异或门构建从0开始计数的模16加1计数器

    如何使用D触发和异或门构建从0开始计数的模16加1计数器
    发表于 09-18 07:29

    环形计数器和扭环形计数器

    环形计数器和扭环形计数器 移位寄存器也可以构成计数器,称为移位型计数器。它有两种结构:环形计数器和扭环形
    发表于 01-12 14:07 9231次阅读

    如何构建一个使用IR光束的对象计数器

    一个电路,计算有多少人走过一扇门或一个对象通过一个点的次数可能非常重要。在这个Maker Pro项目中,我们将构建一个使用IR光束的对象计数器,当它被破坏时,会增加一个计数器
    的头像 发表于 07-30 11:15 1918次阅读

    使用计数器作为原型构建电路

    电子发烧友网站提供《使用计数器作为原型构建电路.zip》资料免费下载
    发表于 11-30 11:12 0次下载
    使用<b class='flag-5'>计数器</b>作为原型<b class='flag-5'>构建</b>电路

    同步计数器和异步计数器是什么 同步计数器和异步计数器的主要区别?

    在数字电子产品中,计数器是由一系列触发器组成的时序逻辑电路。顾名思义,计数器用于计算输入在负或正边沿转换中出现的次数。根据触发触发器的方式,计数器可以分为两类:同步计数器和异步
    的头像 发表于 03-25 17:31 2w次阅读
    同步<b class='flag-5'>计数器</b>和异步<b class='flag-5'>计数器</b>是什么 同步<b class='flag-5'>计数器</b>和异步<b class='flag-5'>计数器</b>的主要区别?

    构建LED二进制计数器

    电子发烧友网站提供《构建LED二进制计数器.zip》资料免费下载
    发表于 06-12 09:54 0次下载
    <b class='flag-5'>构建</b>LED二进制<b class='flag-5'>计数器</b>

    计数器构建

    电子发烧友网站提供《计数器构建.zip》资料免费下载
    发表于 07-05 09:11 0次下载
    <b class='flag-5'>计数器</b>的<b class='flag-5'>构建</b>

    使用移位寄存器构建环形计数器电路

    移位寄存器是一种重要的数字电路元件,可用于构建各种电路,包括环形计数器。在这篇文章中,我们将介绍如何使用移位寄存器来构建一个环形计数器电路。
    的头像 发表于 07-09 11:42 2293次阅读

    计数器怎么用 计数器的作用有哪些

    计数器是一种被广泛应用于各个领域的实用工具,在我们的日常生活中随处可见。无论是进行时间统计,协助工作任务的完成,还是用于科学研究和编程技术,在各个领域都起到了重要的作用。本文将详细介绍计数器
    的头像 发表于 02-03 10:04 1244次阅读