俯卧撑计数 opencv-python + mediapipe

news/2024/10/17 18:24:33/

分享一个国外的趣味项目,俯卧撑计数自动计数项目,这个准确度还可以,考虑因素比较全,据说是新加坡军方使用的。
原文链接:https://aryanvij02.medium.com/push-ups-with-python-mediapipe-open-a544bd9b4351

github 地址: GitHub - aryanvij02/PushUpCounter: A simple program using Mediapipe and OpenCV to count the number of Push Ups done. The main goal is to ensure proper form while doing Push Ups so as to achieve maximum effect.

程序原理介绍

在新加坡军队中,有一种测试叫做IPPT(个人身体素质测试)。这个测试的困难不在于它对体力的要求有多高,而在于用来计算做俯卧撑和仰卧起坐次数的电子机器。

和大多数人一样,我的俯卧撑动作总是不达标(根据机器的意见)。此外,由于缺乏参照机器标准的练习,许多NSMen(已经完成两年强制性服役的人)在IPPT测试中都难以取得好成绩。

因此,我决定使用mediapipe和OpenCV创建一个程序,跟踪我们的俯卧撑动作,确保我们每一个俯卧撑动作都达标。

2849653aec04089c034995408daca140.png

程序结构介绍

该项目有两个文件即可运行:
文件一:PoseModule.py
文件二:main.pyPoseModule.py

模块一:PoseModule.py 模块

上面的代码来源于PoseModule.py,有以下几个功能:

  • 激活mediapipe的姿势检测模块。

  • 检测人体。

  • 根据模型找到人体上不同肢体关节的位置。(肢体显示在上面的图片中)。

  • 查找关节之间的角度(取决于你选择的关节)。对于我的俯卧撑程序,我选择找到肘部、肩部和臀部的角度,因为这些对俯卧撑动作的标准至关重要。

源码如下:

import cv2
import mediapipe as mp
import mathclass poseDetector():def __init__(self, mode=False, complexity=1, smooth_landmarks=True,enable_segmentation=False, smooth_segmentation=True,detectionCon=0.5, trackCon=0.5):self.mode = modeself.complexity = complexityself.smooth_landmarks = smooth_landmarksself.enable_segmentation = enable_segmentationself.smooth_segmentation = smooth_segmentationself.detectionCon = detectionConself.trackCon = trackConself.mpDraw = mp.solutions.drawing_utilsself.mpPose = mp.solutions.poseself.pose = self.mpPose.Pose(self.mode, self.complexity, self.smooth_landmarks,self.enable_segmentation, self.smooth_segmentation,self.detectionCon, self.trackCon)def findPose(self, img, draw=True):imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)self.results = self.pose.process(imgRGB)if self.results.pose_landmarks:if draw:self.mpDraw.draw_landmarks(img, self.results.pose_landmarks,self.mpPose.POSE_CONNECTIONS)return imgdef findPosition(self, img, draw=True):self.lmList = []if self.results.pose_landmarks:for id, lm in enumerate(self.results.pose_landmarks.landmark):# finding height, width of the image printedh, w, c = img.shape# Determining the pixels of the landmarkscx, cy = int(lm.x * w), int(lm.y * h)self.lmList.append([id, cx, cy])if draw:cv2.circle(img, (cx, cy), 5, (255, 0, 0), cv2.FILLED)return self.lmListdef findAngle(self, img, p1, p2, p3, draw=True):# Get the landmarksx1, y1 = self.lmList[p1][1:]x2, y2 = self.lmList[p2][1:]x3, y3 = self.lmList[p3][1:]# Calculate Angleangle = math.degrees(math.atan2(y3 - y2, x3 - x2) -math.atan2(y1 - y2, x1 - x2))if angle < 0:angle += 360if angle > 180:angle = 360 - angleelif angle > 180:angle = 360 - angle# print(angle)# Drawif draw:cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255), 3)cv2.line(img, (x3, y3), (x2, y2), (255, 255, 255), 3)cv2.circle(img, (x1, y1), 5, (0, 0, 255), cv2.FILLED)cv2.circle(img, (x1, y1), 15, (0, 0, 255), 2)cv2.circle(img, (x2, y2), 5, (0, 0, 255), cv2.FILLED)cv2.circle(img, (x2, y2), 15, (0, 0, 255), 2)cv2.circle(img, (x3, y3), 5, (0, 0, 255), cv2.FILLED)cv2.circle(img, (x3, y3), 15, (0, 0, 255), 2)cv2.putText(img, str(int(angle)), (x2 - 50, y2 + 50),cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 255), 2)return angledef main():detector = poseDetector()cap = cv2.VideoCapture(0)while cap.isOpened():ret, img = cap.read()  # ret is just the return variable, not much in there that we will use.if ret:img = detector.findPose(img)cv2.imshow('Pose Detection', img)if cv2.waitKey(10) & 0xFF == ord('q'):breakcap.release()cv2.destroyAllWindows()if __name__ == "__main__":main()


模块二:运行主程序模块PushUpCounter.py 

实际的俯卧撑计数的代码。我们使用PoseModule并确定一个俯卧撑合格与否的标准。

import cv2
import mediapipe as mp
import numpy as np
import PoseModule as pmcap = cv2.VideoCapture(0)
detector = pm.poseDetector()
count = 0
direction = 0
form = 0
feedback = "Fix Form"while cap.isOpened():ret, img = cap.read()  # 640 x 480# Determine dimensions of video - Help with creation of box in Line 43width = cap.get(3)  # float `width`height = cap.get(4)  # float `height`# print(width, height)img = detector.findPose(img, False)lmList = detector.findPosition(img, False)# print(lmList)if len(lmList) != 0:elbow = detector.findAngle(img, 11, 13, 15)shoulder = detector.findAngle(img, 13, 11, 23)hip = detector.findAngle(img, 11, 23, 25)# Percentage of success of pushupper = np.interp(elbow, (90, 160), (0, 100))# Bar to show Pushup progressbar = np.interp(elbow, (90, 160), (380, 50))# Check to ensure right form before starting the programif elbow > 160 and shoulder > 40 and hip > 160:form = 1# Check for full range of motion for the pushupif form == 1:if per == 0:if elbow <= 90 and hip > 160:feedback = "Up"if direction == 0:count += 0.5direction = 1else:feedback = "Fix Form"if per == 100:if elbow > 160 and shoulder > 40 and hip > 160:feedback = "Down"if direction == 1:count += 0.5direction = 0else:feedback = "Fix Form"# form = 0print(count)# Draw Barif form == 1:cv2.rectangle(img, (580, 50), (600, 380), (0, 255, 0), 3)cv2.rectangle(img, (580, int(bar)), (600, 380), (0, 255, 0), cv2.FILLED)cv2.putText(img, f'{int(per)}%', (565, 430), cv2.FONT_HERSHEY_PLAIN, 2,(255, 0, 0), 2)# Pushup countercv2.rectangle(img, (0, 380), (100, 480), (0, 255, 0), cv2.FILLED)cv2.putText(img, str(int(count)), (25, 455), cv2.FONT_HERSHEY_PLAIN, 5,(255, 0, 0), 5)# Feedbackcv2.rectangle(img, (500, 0), (640, 40), (255, 255, 255), cv2.FILLED)cv2.putText(img, feedback, (500, 40), cv2.FONT_HERSHEY_PLAIN, 2,(0, 255, 0), 2)cv2.imshow('Pushup counter', img)if cv2.waitKey(10) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()

有个需要注意的地方在第17-21行。确定从相机捕捉到的图像的分辨率,并在绘制俯卧撑计数的矩形时调整像素值,等等。(第68-82行)。


环境部署说明:


新建虚拟环境,无需安装其他框架

pip install mediapipe -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple


http://www.ppmy.cn/news/703186.html

相关文章

【AI生成PPT】美图 vs Mindshow 谁更值得推荐?

概要 本文为大家安利两款人工智能生成PPT软件的不错办法&#xff0c;同时做一个简单的比较分析。 笔者写下这篇博文时是2023年的夏天&#xff0c;彼时国内直接可用的AI自动生成工具正在逐步完善。在呼声较高的国产PPT生成工具中&#xff0c;笔者着重比较了 美图 和 Mindshow 两…

瑞吉外卖-全网最全笔记-Day01

业务开发Day1-01-本章内容介绍 项目效果展示 登录界面 登录成功界面 管理界面展示 员工管理分类管理菜品管理套餐管理订单明细 前端开发使用HTML5技术&#xff08;自适应屏幕大小功能&#xff09; 目录 软件开发整体介绍瑞吉外卖项目介绍开发环境搭建 业务开发Day1-02…

苹果手机无法kx上网的问题

突然一下的不能小上网了&#xff0c;小火箭没有问题&#xff0c;网络没有问题&#xff0c;重启手机&#xff0c;重新下小火箭&#xff0c;重置网络设置&#xff0c;什么都试过了都不行。节点是没问题的pc端连的相同wifi都能上&#xff0c;实在是想不出来哪里出问题了。有大佬遇…

ios 10 部分App无法连接网络或网络错误

最近不少手机都升级了ios10.0系统&#xff0c;在调试的过程中发现&#xff0c;咱家的app无法连接到网络&#xff0c;然后去手动设置网络权限开启&#xff0c;但是根本找不到这个app。 据说这是ios10的bug&#xff0c;解决办法之一就是升级ios10.1beta系统 &#xff0c;貌似修复…

vue2如何使用codemirror

1.准备 现在如果你直接 npm install vue-codemirror codemirror --save 那么你大概率在引用 import codemirror/lib/codemirror.css 的时候会报错。因为在现在的版本是为vue3准备的。 那么你只要安装低版本的就行了 npm i codemirror5.65.12 npm i vue-codemirror4.0.6 …

关于苹果手机8P使用fiddler抓包连不上网的问题

在网上扒拉了一堆&#xff0c;感谢终于看到希望了 https://blog.csdn.net/m0_37554415/article/details/80434477?utm_mediumdistribute.pc_relevant.none-task-blog-baidujs-1 这篇文章算是一些基础的配置了&#xff0c;感谢大神。 但是我的8p手机经过这一堆操作之后还是连…

charles 代理手机连不上网_小白也能懂:电脑连不上网分析与解决!

电脑突然连不上网的情况时有发生&#xff0c;最近我发现即便是略有电脑基础的人&#xff0c;有些也不知道该如何检查处理&#xff0c;这方面的文章以前发过很多&#xff0c;今天再来梳理一下。 记住最重要的一点&#xff0c;是需要理解&#xff0c;下面的内容会教你如何理解的基…

ios15验证失败因为你不在连接互联网

每次苹果发布新的iOS版本&#xff0c;许多果粉都会迫不及待地更新他们的手机系统。但是&#xff0c;新的iOS版本很容易出现一些问题。 最近&#xff0c;一些用户在iPhone上尝试升级iOS 15时&#xff0c;手机提示“无法验证更新&#xff0c;iOS 15验证失败&#xff0c;因为您不再…