当前位置: 首页 > news >正文

AI健身体能测试之基于paddlehub实现引体向上计数个数统计

【引体向上计数】

本项目使用PaddleHub中的骨骼检测模型human_pose_estimation_resnet50_mpii,进行人体运动分析,实现对引体向上的自动计数。

1. 项目介绍

人体运动分析是近几年许多领域研究的热点问题。在学科的交叉研究上,人体运动分析涉及到计算机科学、运动人体科学、环境行为学和材料科学等。随着研究的深入以及计算机视觉、5G通信的飞速发展,人体运动分析技术已应用于自动驾驶、影视创作、安防异常事件监测和体育竞技分析、康复等实际场景人体运动分析已成为人工智能领域研究的前沿课题。

在体育课上,引体向上是一个常规的运动,体育老师有时需要对每位同学做引体向上项目时需要计数,那如何利用AI技术进行人体运动分析可以实现引体向上的自动计数,从而减轻老师的工作量呢?本项目我们就实现AI引体向上计数功能的实现,项目效果如下:

2.项目分析与解决方案设计

对于引体向上计数任务,首先使用录像设备将每个人的动作录制成视频,然后对视频进行拆帧拆解成多张图像,对每张图像进行人体关键骨骼点检测,然后获取每张图像的头部关键点的纵坐标,以七张图像为一个单位,判断第四张图像的头部关键骨骼关键点的纵坐标是否为七张图像中的最小值f(4)<=f(x),如果是记录为1,如果不是则记录为0,最后将记录的值进行累加,得到的值便是引体向上的数目,最后实现可视化计数,便于我们查看结果。这样我们就实现了引体向上计数!

本项目实现基本可以分为7步,分别是新建项目与数据导入、人体骨骼关键点模型的安装、模块导入、定义数据、人体骨骼点检测、将计数过程可视化、最后一步实现引体向上计数,引体向上计数就可以实现了,实现流程如下图所示:

了解了项目实现的基本流程,接下来我们就按顺序完成每一个模块功能的实现。

3.项目准备

我们要完成此项目,该做哪些准备呢? 首先是实验实施环境,本项目我们使用windows系统+nvidia RTX2070 super显卡安装环境:

aiofiles==23.2.1
aiohttp==3.9.1
aiosignal==1.3.1
altair==5.2.0
annotated-types==0.6.0
anyio==4.2.0
astor==0.8.1
async-timeout==4.0.3
attrdict==2.0.1
attrs==23.2.0
Babel==2.14.0
bce-python-sdk==0.9.2
beautifulsoup4==4.12.2
blinker==1.7.0
cachetools==5.3.2
certifi==2023.11.17
charset-normalizer==3.3.2
click==8.1.7
colorama==0.4.6
colorlog==6.8.0
contourpy==1.1.1
cssselect==1.2.0
cssutils==2.9.0
cycler==0.12.1
Cython==3.0.8
datasets==2.16.1
decorator==5.1.1
dill==0.3.4
easydict==1.11
et-xmlfile==1.1.0
exceptiongroup==1.2.0
fastapi==0.109.0
ffmpy==0.3.1
filelock==3.13.1
fire==0.5.0
Flask==3.0.0
Flask-Babel==2.0.0
fonttools==4.47.2
frozenlist==1.4.1
fsspec==2023.10.0
future==0.18.3
gradio==4.14.0
gradio_client==0.8.0
h11==0.14.0
httpcore==1.0.2
httpx==0.26.0
huggingface-hub==0.20.2
idna==3.6
imageio==2.33.1
imgaug==0.4.0
importlib-metadata==7.0.1
importlib-resources==6.1.1
itsdangerous==2.1.2
jieba==0.42.1
Jinja2==3.1.3
joblib==1.3.2
jsonschema==4.20.0
jsonschema-specifications==2023.12.1
kiwisolver==1.4.5
lanms-neo==1.0.2
lap==0.4.0
lazy_loader==0.3
lmdb==1.4.1
lxml==5.1.0
markdown-it-py==3.0.0
MarkupSafe==2.1.3
matplotlib==3.7.4
mdurl==0.1.2
motmetrics==1.4.0
multidict==6.0.4
multiprocess==0.70.12.2
networkx==3.1
numpy==1.23.5
onnx==1.15.0
opencv-contrib-python==4.6.0.66
opencv-python==4.6.0.66
openpyxl==3.1.2
opt-einsum==3.3.0
orjson==3.9.10
packaging==23.2
paddle-bfloat==0.1.7
paddle2onnx==1.0.6
paddledet==2.6.0
paddlefsl==1.1.0
paddlehub==2.4.0
paddlenlp==2.5.2
paddlepaddle-gpu==2.4.2.post117
paddleseg==2.8.0
pafy==0.5.5
pandas==2.0.3
pdf2docx==0.5.7
pillow==10.3.0
pkgutil_resolve_name==1.3.10
Polygon3==3.0.9.1
PPOCRLabel==2.1.3
premailer==3.10.0
prettytable==3.9.0
protobuf==3.20.2
psutil==5.9.7
py-cpuinfo==9.0.0
pyarrow==14.0.2
pyarrow-hotfix==0.6
pyclipper==1.3.0.post5
pycocotools==2.0.7
pycryptodome==3.20.0
pydantic==2.5.3
pydantic_core==2.14.6
pydub==0.25.1
Pygments==2.17.2
PyMuPDF==1.20.2
pyparsing==3.1.1
PyQt5==5.15.10
PyQt5-Qt5==5.15.2
PyQt5-sip==12.13.0
python-dateutil==2.8.2
python-docx==1.1.0
python-multipart==0.0.6
pytz==2023.3.post1
PyWavelets==1.4.1
PyYAML==6.0.1
pyzmq==25.1.2
rapidfuzz==3.6.1
rarfile==4.1
referencing==0.32.1
requests==2.31.0
rich==13.7.0
rpds-py==0.17.1
safetensors==0.4.1
scikit-image==0.21.0
scikit-learn==1.3.2
scipy==1.10.1
seaborn==0.13.2
semantic-version==2.10.0
sentencepiece==0.1.99
seqeval==1.2.2
shapely==2.0.2
shellingham==1.5.4
six==1.16.0
sklearn==0.0
sniffio==1.3.0
soupsieve==2.5
starlette==0.35.1
termcolor==2.4.0
terminaltables==3.1.10
threadpoolctl==3.2.0
tifffile==2023.7.10
tomlkit==0.12.0
toolz==0.12.0
tqdm==4.66.1
typeguard==4.1.5
typer==0.9.0
typing_extensions==4.9.0
tzdata==2023.4
ultralytics==8.2.30
ultralytics-thop==0.2.8
urllib3==2.1.0
uvicorn==0.25.0
visualdl==2.4.2
wcwidth==0.2.13
websockets==11.0.3
Werkzeug==3.0.1
xlrd==1.2.0
xmltodict==0.13.0
xxhash==3.4.1
yarl==1.9.4
youtube-dl==2021.12.17
zipp==3.17.0

以上是对项目实现环境的要求,在此基础上还需要准备一个视频,我们将视频命名为引体向上.mp4

4.代码实现

In [2]

# 导入实验项目需要使用的库
import paddlehub as hub#调用paddlehub中预训练模型的库
import cv2# 能够快速的实现一些图像处理和识别的库
import os#含了很多操作文件和目录的函数的库
import numpy as np#一个由多维数组对象和用于处理数组的例程集合组成的库
from tqdm import tqdm#进度条库,可以帮助我们监测代码进度
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/scipy/sparse/sputils.py:16: DeprecationWarning: `np.typeDict` is a deprecated alias for `np.sctypeDict`.supported_dtypes = [np.typeDict[x] for x in supported_dtypes]
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/scipy/special/orthogonal.py:81: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecationsfrom numpy import (exp, inf, pi, sqrt, floor, sin, cos, around, int,
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/scipy/linalg/__init__.py:217: DeprecationWarning: The module numpy.dual is deprecated.  Instead of using dual, use the functions directly from numpy or scipy.from numpy.dual import register_func

第1步:定义数据

在这一部分需要定义实现引体向上项目需要的数据:

  1. 定义引体向上视频路径pull_up_path引体向上.mp4,用做引体向上计数视频;
  2. 定义一个bool值visualiztiontomp4,是否将计数结果保存到视频中;
  3. 定义一个窗口compare_window3,作为每次引体向上计数窗口大小;
  4. 定义一个视频名称video_namecount_引体向上.mp4,用于保存视频的名称。

实现方法如下:

In [3]

#定义数据
pull_up_path='引体向上.mp4'#定义引体向上视频路径
visualizationtomp4 = True#是否将结果保存为视频
compare_window=3#定义每次引体向上计数的帧数范围
video_name = "output_count_引体向上.mp4"#定义保存视频名称

第2步:人体骨骼点检测

人体关键骨骼点检测功能一共分为两步:

  • 第一步,加载模型human_pose_estimation_resnet50_mpii,此时model就变成具备人体关键骨骼点检测功能的“检测器”,第二步便是利用其keyponit_detection()函数检测输入图片列表中的所有骨骼点的位置。

  • 第二步,将骨骼点检测得到的位置坐标信息储存在result中,便于下一个环节使用,这里我们将这两步骤封装为point_detection(images)函数,参数images为存放图像的列表,并将检测结果返回,也就是在图片上标出骨骼关键点的位置,如下图所示:

实现代码如下所示:

In [4]

# 定义模型预测函数,实现人体关键骨骼点检测
# 图片数据,ndarray.shape 为 [H, W, C];
def point_detection(images): # 初始化module,调用人体关键点检测模型  model = hub.Module(name="human_pose_estimation_resnet50_mpii")    # 预测API,识别出人体骨骼关键点result = model.keypoint_detection(images,visualization=True)return result

第3步:计数过程可视化

经过以上操作我们完成了项目环境的准备,定义了本项目所用到的数据,和获取人体关键骨骼点的函数方法point_detection(images),接下来我们定义一个imagestovideo(images,is_up_list,video_name,fps)函数,该函数的作用是将预测的结果可视化,并且实现计数功能。

Imagestovideo( )函数中一共包含四个函数:

  • images(list):包含了视频中每一帧的图像;
  • is_up_list(list):用于记录每一帧的位置是否完成依次引体向上;
  • video_name(str):视频保存路径;
  • fps(int):视频的帧率。

具体的实现方法如下:

In [5]

# 将计数过程保存成视频
def imagestovideo(images, #(list): 每一帧视频图片is_up_list, #(list): 视频每一帧的位置是否为引体向上完成一次video_name, #(str): 保存视频路径fps):#(int)保存视频帧率size = images[0].shape[:2]  #获取图片格式大小#定义视频video,用于存放处理完的视频video = cv2.VideoWriter(video_name, cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), fps, size[::-1])count = 0#定义count,用于存放引体向上次数for i in tqdm(range(len(images))):count += is_up_list[i] #累加引体向上次数frame = images[i]#读取每一张图像#在图像上添加文字,用于记录引体向上次数cv2.putText(frame, f'pull up count: {count}', (5, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (55,255,155), 2)video.write(frame)#将图像写入视频中video.release()#释放视频对象

第4步:实现引体向上计数过程

经过上一步骤我们得到了人体关键骨骼点检测的方法point_detection()和将计数过程可视化的方法imagestovideo(),接下里我们具体的实现引体向上计数的过程,实现步骤如下:

In [6]

def countbyhead_with_mp4(mp4_path,#待处理视频路径;video_name,#视频保存名称compare_window=5,#计数窗口;visualizationtomp4=False):#是否可视化计数。'''第一步:我们定义一个列表images,用于存放视频中的每一帧图像,读取视频,并且获取视频的帧率fps,具体的实现代码如下:'''images = []#定义一个列表,用于存放视频中的每一帧图像cap = cv2.VideoCapture(mp4_path)#读取已有的视频fps = cap.get(cv2.CAP_PROP_FPS)#获取视频的帧率fps,fps=9.538461538461538'''第二步:通过while循环读取视频中的每一帧图像,并将图片信息保存到images列表当中,最后释放视频对象空间,具体的实现代码如下:'''while cap.isOpened():#判断视频对象是否成功读取,成功读取视频对象返回True#按帧读取视频,返回值ret是布尔型,正确读取则返回True,#读取失败或读取视频结尾则会返回False。#frame为每一帧的图像,这里图像是三维矩阵,即frame.shape = (640,480,3),#读取的图像为BGR格式。ret, frame = cap.read() if frame is None:#当读取到空图像时,循环终止breakimages.append(frame)#将读取到的每一张图像添加到images列表中cap.release()#释放视频对象'''第三步:对每一张图像进行人体关键骨骼点检测,并将结果保存到results中,通过for循环,获取每张图像的头部关键点的纵坐标信息,将每张图像的头部关键点的纵坐标信息存储到heads列表中,具体实现代码如下:'''results = point_detection(images)#进行人体关键骨骼点检测#获取每张图像的头顶关键点的纵坐标heads = [result['data']['head_top'][1] for result in results]'''第四步:定义is_up_list列表,用于记录视频中的每一帧的位置是否完成一次引体向上,通过for循环遍历视频中的图像,以每七张图像为一个单位进行,比较头部关键点的纵坐标大小,判断第四张图像的纵坐标是否为这七张图像中的最小值,并且保证前三张图像不是计数点,如果满足以上要求is_up_list添加1,如果不满足则添加0,直到循环结束,is_up_list中存储了每一帧图像是否完成一次引体向上,最后判断是否将计数过程可视化,如果实现可视化,则调用visualizationtomp4()函数,具体实现代码如下:'''is_up_list = [0] * compare_window #视频每一帧的位置是否为引体向上完成一次#从3到57依次循环遍历for idx in range(compare_window, len(heads) - compare_window - 1):front_idx = idx - compare_window #定义front_idx第一个图像的索引#heads中索引为0到3之间的数转化为数组,定义为frontfront = np.array(heads[front_idx:idx])#获取真正的索引3+3+1=7,定义为rear_idxrear_idx = idx + compare_window + 1#heads中索引为4到7之间的数转化为数组,定义为rearrear = np.array(heads[idx+1:rear_idx])#将前四张图像的头部关键点纵坐标减去第四张纵坐标,# 将大于1的数记为1,小于-1的记为-1,#将得到的四个数组求和定义为is_greater_than_the_frontis_greater_than_the_front = np.sum(np.clip(front - heads[idx], a_min=-1, a_max=1))#将第四张图像到第七张图像的头部关键点纵坐标减去第四张纵坐标,# 将大于1的数记为1,小于-1的记为-1,将得到的四个数组求和定义为is_greater_than_the_realis_greater_than_the_rear = np.sum(np.clip(rear - heads[idx], a_min=-1, a_max=1))#判断是否同时满足以下三个要求:以下条件为是否满足一次引体向上if is_greater_than_the_front > 0 and is_greater_than_the_rear > 0 and sum(is_up_list[-compare_window:]) == 0:is_up_list.append(1)#满足以上条件is_up_list列表末尾添加1else:is_up_list.append(0)#如果不满足以上条件is_up_list列表末尾添加0is_up_list.extend([0] * (compare_window + 1))#在is_up_list中添加4个0,用于补足视频的帧数if visualizationtomp4:#是否将计数过程保存成视频imagestovideo(images, is_up_list, video_name, fps)#将计数过程保存成视频return results, is_up_list

第5步:运行主函数

In [7]

results, is_up_list = countbyhead_with_mp4(pull_up_path,video_name, compare_window=3,visualizationtomp4=visualizationtomp4)
Download https://bj.bcebos.com/paddlehub/paddlehub_dev/human_pose_estimation_resnet50_mpii_1_2_0.zip
[##################################################] 100.00%
Decompress /home/aistudio/.paddlehub/tmp/tmphzw2nbgn/human_pose_estimation_resnet50_mpii_1_2_0.zip
[##################################################] 100.00%
[2023-07-21 17:32:55,564] [    INFO] - Successfully installed human_pose_estimation_resnet50_mpii-1.2.0
---    Fused 0 subgraphs into layer_norm op.
image saved in output_pose/ndarray_time=1689931976012325.jpg
image saved in output_pose/ndarray_time=1689931976012369.jpg
image saved in output_pose/ndarray_time=1689931976012375.jpg
image saved in output_pose/ndarray_time=1689931976012380.jpg
image saved in output_pose/ndarray_time=1689931976012384.jpg
image saved in output_pose/ndarray_time=1689931976012389.jpg
image saved in output_pose/ndarray_time=1689931976012394.jpg
image saved in output_pose/ndarray_time=1689931976012400.jpg
image saved in output_pose/ndarray_time=1689931976012405.jpg
image saved in output_pose/ndarray_time=1689931976012411.jpg
image saved in output_pose/ndarray_time=1689931976012416.jpg
image saved in output_pose/ndarray_time=1689931976012421.jpg
image saved in output_pose/ndarray_time=1689931976012436.jpg
image saved in output_pose/ndarray_time=1689931976012441.jpg
image saved in output_pose/ndarray_time=1689931976012446.jpg
image saved in output_pose/ndarray_time=1689931976012452.jpg
image saved in output_pose/ndarray_time=1689931976012456.jpg
image saved in output_pose/ndarray_time=1689931976012461.jpg
image saved in output_pose/ndarray_time=1689931976012466.jpg
image saved in output_pose/ndarray_time=1689931976012472.jpg
image saved in output_pose/ndarray_time=1689931976012476.jpg
image saved in output_pose/ndarray_time=1689931976012482.jpg
image saved in output_pose/ndarray_time=1689931976012487.jpg
image saved in output_pose/ndarray_time=1689931976012492.jpg
image saved in output_pose/ndarray_time=1689931976012498.jpg
image saved in output_pose/ndarray_time=1689931976012502.jpg
image saved in output_pose/ndarray_time=1689931976012507.jpg
image saved in output_pose/ndarray_time=1689931976012512.jpg
image saved in output_pose/ndarray_time=1689931976012517.jpg
image saved in output_pose/ndarray_time=1689931976012522.jpg
image saved in output_pose/ndarray_time=1689931976012527.jpg
image saved in output_pose/ndarray_time=1689931976012532.jpg
image saved in output_pose/ndarray_time=1689931976012536.jpg
image saved in output_pose/ndarray_time=1689931976012542.jpg
image saved in output_pose/ndarray_time=1689931976012546.jpg
image saved in output_pose/ndarray_time=1689931976012550.jpg
image saved in output_pose/ndarray_time=1689931976012556.jpg
image saved in output_pose/ndarray_time=1689931976012561.jpg
image saved in output_pose/ndarray_time=1689931976012565.jpg
image saved in output_pose/ndarray_time=1689931976012570.jpg
image saved in output_pose/ndarray_time=1689931976012575.jpg
image saved in output_pose/ndarray_time=1689931976012579.jpg
image saved in output_pose/ndarray_time=1689931976012584.jpg
image saved in output_pose/ndarray_time=1689931976012589.jpg
image saved in output_pose/ndarray_time=1689931976012594.jpg
image saved in output_pose/ndarray_time=1689931976012599.jpg
image saved in output_pose/ndarray_time=1689931976012604.jpg
image saved in output_pose/ndarray_time=1689931976012609.jpg
image saved in output_pose/ndarray_time=1689931976012614.jpg
image saved in output_pose/ndarray_time=1689931976012619.jpg
image saved in output_pose/ndarray_time=1689931976012624.jpg
image saved in output_pose/ndarray_time=1689931976012629.jpg
image saved in output_pose/ndarray_time=1689931976012634.jpg
image saved in output_pose/ndarray_time=1689931976012640.jpg
image saved in output_pose/ndarray_time=1689931976012644.jpg
image saved in output_pose/ndarray_time=1689931976012648.jpg
image saved in output_pose/ndarray_time=1689931976012654.jpg
image saved in output_pose/ndarray_time=1689931976012658.jpg
image saved in output_pose/ndarray_time=1689931976012662.jpg
image saved in output_pose/ndarray_time=1689931976012667.jpg
image saved in output_pose/ndarray_time=1689931976012673.jpg
image saved in output_pose/ndarray_time=1689931976012678.jpg
100%|██████████| 62/62 [00:00<00:00, 975.11it/s]

完整代码+模型+视频例子+运行结果视频下载地址:

https://download.csdn.net/download/FL1623863129/89760682

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++——内存管理
  • 828华为云征文|部署知识库问答系统 MaxKB
  • Sqlserver常用sql
  • list从0到1的突破
  • Guava中Preconditions校验
  • Android中的冷启动,热启动和温启动
  • 一款自动对杂乱文件进行整理和分类的AI工具--FileNeatAI
  • python之排列组合1
  • RecyclerView的子项长按选择功能
  • Node.js运行环境搭建
  • 苹果CMS海洋CMS那个更容易被百度收录?苹果CMS站群
  • 记录小数点
  • 001 RabbitMQ入门及安装
  • 浏览器插件利器--allWebPluginV2.0.0.20-beta版发布
  • 2024 批量下载知乎回答/文章/想法/专栏/视频/收藏夹,导出 excel 和 pdf
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • HTML-表单
  • java 多线程基础, 我觉得还是有必要看看的
  • Java-详解HashMap
  • MySQL的数据类型
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • node.js
  • Object.assign方法不能实现深复制
  • React-flux杂记
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • Spring Cloud Feign的两种使用姿势
  • spring security oauth2 password授权模式
  • 码农张的Bug人生 - 见面之礼
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • #Java第九次作业--输入输出流和文件操作
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (ISPRS,2021)具有遥感知识图谱的鲁棒深度对齐网络用于零样本和广义零样本遥感图像场景分类
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (Qt) 默认QtWidget应用包含什么?
  • (zt)最盛行的警世狂言(爆笑)
  • (二)PySpark3:SparkSQL编程
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (一)80c52学习之旅-起始篇
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转载)利用webkit抓取动态网页和链接
  • (自用)gtest单元测试
  • ../depcomp: line 571: exec: g++: not found
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET MVC第三章、三种传值方式
  • .net Stream篇(六)
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 使用反射调用含 ref 或 out 参数的方法
  • .Net接口调试与案例
  • .NET连接MongoDB数据库实例教程
  • .NET中使用Redis (二)
  • [20170713] 无法访问SQL Server