俯卧撑计数 opencv-python + mediapipe

news2024/12/23 7:48:37

分享一个国外的趣味项目,可以计数,也可以完善进行动作是打分,确定标准程度
原文链接:https://aryanvij02.medium.com/push-ups-with-python-mediapipe-open-a544bd9b4351

程序原理介绍

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

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

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

2849653aec04089c034995408daca140.png

程序结构介绍

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

PoseModule.py 模块

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

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

  • 检测人体。

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

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

源码如下:

import cv2
import mediapipe as mp
import math


class 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 = mode
        self.complexity = complexity
        self.smooth_landmarks = smooth_landmarks
        self.enable_segmentation = enable_segmentation
        self.smooth_segmentation = smooth_segmentation
        self.detectionCon = detectionCon
        self.trackCon = trackCon

        self.mpDraw = mp.solutions.drawing_utils
        self.mpPose = mp.solutions.pose
        self.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 img

    def 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 printed
                h, w, c = img.shape
                # Determining the pixels of the landmarks
                cx, 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.lmList

    def findAngle(self, img, p1, p2, p3, draw=True):
        # Get the landmarks
        x1, y1 = self.lmList[p1][1:]
        x2, y2 = self.lmList[p2][1:]
        x3, y3 = self.lmList[p3][1:]

        # Calculate Angle
        angle = math.degrees(math.atan2(y3 - y2, x3 - x2) -
                             math.atan2(y1 - y2, x1 - x2))
        if angle < 0:
            angle += 360
            if angle > 180:
                angle = 360 - angle
        elif angle > 180:
            angle = 360 - angle
        # print(angle)

        # Draw
        if 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 angle


def 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'):
            break

    cap.release()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()


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

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

import cv2
import mediapipe as mp
import numpy as np
import PoseModule as pm

cap = 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 43
    width = 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 pushup
        per = np.interp(elbow, (90, 160), (0, 100))

        # Bar to show Pushup progress
        bar = np.interp(elbow, (90, 160), (380, 50))

        # Check to ensure right form before starting the program
        if elbow > 160 and shoulder > 40 and hip > 160:
            form = 1

        # Check for full range of motion for the pushup
        if form == 1:
            if per == 0:
                if elbow <= 90 and hip > 160:
                    feedback = "Up"
                    if direction == 0:
                        count += 0.5
                        direction = 1
                else:
                    feedback = "Fix Form"

            if per == 100:
                if elbow > 160 and shoulder > 40 and hip > 160:
                    feedback = "Down"
                    if direction == 1:
                        count += 0.5
                        direction = 0
                else:
                    feedback = "Fix Form"
                    # form = 0

        print(count)

        # Draw Bar
        if 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 counter
        cv2.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)

        # Feedback
        cv2.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'):
        break

cap.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.coloradmin.cn/o/196185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

程序股票交易接口怎么撤单?

在程序股票交易接口的开发基础上&#xff0c;还能增加一个撤单的委托模块&#xff0c;因为程序股票交易接口的开发不单单是委托下单&#xff0c;那照样也能撤单&#xff0c;这两种的开发原理上&#xff0c;都不冲突&#xff0c;有的股票接口需要计算多种算法&#xff0c;算起来…

CNCAP2021法规adas功能场景

CNCAP2021法规adas功能场景概述功能介绍试验场景概述 C-NCAP是中国汽车技术研究中心于2006年3月2日正式发布的首版中国新车评价规程。中国新车评价规程每三年进行一次规程改版&#xff0c;最新的是2021版本。本文只针对cncap2021主动安全场景进行梳理。 功能介绍 1、AEB(Aut…

vue2低代码平台搭建(三)组件间交互的实现

前言 大家好,我是L丶Y,我们在上一篇文章中主要介绍了低代码平台的页面设计器相关的一些功能原理,打通了页面设计器顶部操作栏、左侧组件列表,中间画布、右侧属性配置四个部分的关系。能够实现组件列表的展示、组件到画布的拖动,属性配置修改对组件渲染效果影响,并说明了…

Picgo配置Bilibili图床

Picgo 配置Bilibili 图床 picgo-plugin-bilibili 为 PicGo 开发的一款插件&#xff0c;新增了B站图床 图床。 使用用户动态的图片上传API。填写SESSDATA即可&#xff0c;获取方式在下面。 文章目录Picgo 配置Bilibili 图床在线安装获取B站SESSDATA图片样式解决B站防盗链&#…

隐函数及参数方程求导——“高等数学”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容是隐函数求导和参数方程求导&#xff0c;下面&#xff0c;就让我们进入求导数的世界吧 一、隐函数的导数 二、隐函数求导 三、由参数方程确定的函数的导数 四、相关变化率 一、隐函数的导数 要想知道隐函数…

官宣:计算中间件 Apache Linkis 正式毕业成为 Apache 顶级项目

Apache 软件基金会&#xff08;ASF&#xff09;孵化器于2022年12月03日&#xff0c;通过了 Apache Linkis 计算中间件项目的孵化毕业投票。2023年01月18日&#xff0c;Apache 软件基金会官方宣布 Apache Linkis 顺利毕业&#xff0c;成为 Apache 顶级项目&#xff08;TLP&#…

泊松分布的计算方式

如果都要计算泊松分布了&#xff0c;那么就默认你知道泊松分布的基本知识了&#xff0c;我这里只介绍如何计算&#xff0c;我是用的Excel直接套用公式计算的&#xff0c;如果想在代码里用&#xff0c;我的实现方式是&#xff0c;先用Excel把值全部求出来&#xff0c;然后做成ma…

开组会写论文必备工具清单

来源&#xff1a;投稿 作者&#xff1a;卷舒 编辑&#xff1a;学姐 公式工具 https://www.latexlive.com/ snip这个工具也与之类似&#xff0c;但是需要安装&#xff0c;且有50个的限制。 这是一个LaTeX公式在线编辑器。提供了各类快捷符号及公式模板。在输入区域尝试LaTeX公…

创建SpringBoot工程

目录 一、官网创建 1、进入spring官网&#xff1a;Spring | Home 2、点击Spring Boot&#xff0c;滑倒最下面&#xff0c;点击Spring initializr 3&#xff0c;创建Spring Boot工程&#xff0c;版本选2.多的&#xff0c;高版本配置可能会出现问题&#xff0c;jdk选你电脑上装…

训练营day15

层序遍历 10 226.翻转二叉树 101.对称二叉树 2 102.二叉树的层序遍历 力扣题目链接 给你一个二叉树&#xff0c;请你返回其按 层序遍历 得到的节点值。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 接下来我们再来介绍二叉树的另一种遍历方式&#x…

Java面试题二-并发编程、IO、设计模式、通信/网络、JVM

本文目录如下&#xff1a;Java面试题(二)四、并发编程线程和进程的区别&#xff1f;守护线程是什么&#xff1f;创建线程有哪几种方式&#xff1f;线程有哪些状态&#xff1f;sleep() 和 wait() 有什么区别&#xff1f;线程的sleep()方法和yield()方法有什么区别&#xff1f;线…

KVM虚拟机安装Virtio驱动

KVM虚拟机安装Virtio驱动KVM服务器上配置Virtio驱动ISO文件Windows实例安装Virtio驱动Linux实例安装kvm驱动(一般不需要)KVM服务器上配置Virtio驱动ISO文件 参考&#xff1a;https://www.ibm.com/docs/zh/cloud-orchestrator/2.5.0.1?topicimages-installing-virtio-driver-k…

成功解决:尚硅谷中的谷粒商城前端项目运行依赖问题。【详细图解+问题说明+解决思路】

一个混迹于Github、Stack Overflow、开源中国、CSDN、博客园、稀土掘金、51CTO等 的野生程序员。 目标&#xff1a;分享更多的知识&#xff0c;充实自己&#xff0c;帮助他人 GitHub公共仓库&#xff1a;https://github.com/zhengyuzh 以github为主&#xff1a; 1、分享前端后端…

程序员超级书单:技术人必看

写在前面 电影一部两小时打底&#xff0c;却很少有人可以静下心看30分钟书。今天刷沸点摸鱼, 无意中摸到一条让我有写作冲动的鱼&#xff0c;开工几天了&#xff0c;大家应该都暗暗立下不少flag&#xff0c;比如坚持锻炼&#xff0c;再比如自己今年要看多少本书籍。 行业内卷…

舆情监控工具app推荐,舆情监控工具包括哪些?

舆情监控工具的目的是帮助组织了解公众对各种话题、问题或品牌的意见和情绪。它们可以从多种来源收集数据&#xff0c;包括社交媒体、新闻媒体、博客、论坛和评论区。舆情监控工具app推荐&#xff0c;舆情监控工具包括哪些? 一、舆情监控工具app推荐 TOOM舆情监控工具&…

算法基础集训(第31天)------>BFS之经典【走迷宫】

一&#xff1a;概念定义给定一个 nm 的二维整数数组&#xff0c;用来表示一个迷宫&#xff0c;数组中只包含 0 或 1&#xff0c;其中 0 表示可以走的路&#xff0c;1 表示不可通过的墙壁。最初&#xff0c;有一个人位于左上角 (1,1) 处&#xff0c;已知该人每次可以向上、下、左…

扎克伯格15年邮件曝光:AR/VR平台全盘细节,谈收购Unity的优势

近期一份2015年时扎克伯格的一封邮件曝光&#xff0c;文中解释了Facebook在VR领域的战略策略和VR对未来的影响等&#xff0c;揭露了但是Facebook在VR/AR方向上的全盘计划&#xff0c;同时曝光当时Facebook就有收购Unity的计划&#xff0c;值得一看。以下是摘要&#xff1a;1&am…

DarkNet框架实现分类任务避坑指南(附安装包)

声明&#xff1a;本文仅分享技术&#xff0c;无其他 文章目录***声明&#xff1a;本文仅分享技术&#xff0c;无其他***这个框架真的非常非常非常小众&#xff0c;入坑需谨慎DarkNet对编译环境有要求配置前的准备环节1、 DarkNet源码封装&#xff08;安装包如果失效了&#xff…

看这个就够了——ubuntu系统中的cuda cudnn cudatookit及pytorch使用

一.基本概念1.1 nvidia独立显卡独立显卡是指以独立板卡形式存在&#xff0c;可在具备显卡接口的主板上自由插拔的显卡。独立显卡具备单独的显存&#xff0c;不占用系统内存&#xff0c;而且技术上领先于集成显卡&#xff0c;能够提供更好的显示效果和运行性能。显卡作为电脑主机…

GooFuzz:一款基于OSINT方法的模糊测试工具

关于GooFuzz GooFuzz是一款基于OSINT方法的模糊测试工具&#xff0c;该工具基于Google Dork实现其功能。本质上来说&#xff0c;GooFuzz是一个Bash脚本&#xff0c;该脚本使用了Google Search技术来获取文件或目录中的敏感信息&#xff0c;而无需向目标Web服务器发送请求。 工…