news 2026/9/2 13:49:57

基于Python与MediaPipe实现引体向上自动计数:从姿态估计到状态机逻辑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Python与MediaPipe实现引体向上自动计数:从姿态估计到状态机逻辑

简介:本资源是一套基于Python的引体向上动作自动计数算法实现方案,面向计算机科学、电子工程及应用数学等相关专业本科生与研究生,解决健身动作识别与运动次数量化中的姿态检测与轨迹分析问题,适用于课程实践、学期项目或毕业设计等中阶编程与CV结合场景。压缩包共8个文件,含2个核心Python脚本(姿态检测与计数逻辑)、2段MP4演示视频(原始动作与算法输出效果)、1个说明文档及辅助配置文件,整体大小为47.26MB,结构简洁、开箱即用。已有34人学习下载,资源突出算法可复现性与代码可扩展性——提供完整推理流程、关键参数注释及常见优化入口,便于读者理解人体关键点建模思路、调试阈值逻辑,并基于自身数据集进行迁移适配。

1. 项目概述:从健身痛点到一个Python程序员的解决方案

最近在健身房,我总能看到一些朋友在做引体向上时,要么自己数着数着就忘了,要么得依赖手机录像事后回放计数,既麻烦又打断了训练的连贯性。作为一个常年泡在代码里的程序员,我就在想,能不能用自己最熟悉的工具——Python,来解决这个小小的、但很实际的健身烦恼?于是,就有了这个“基于Python的引体向上计数算法实现”的项目。

这个项目的核心目标很简单:让电脑通过摄像头“看懂”你的引体向上动作,并自动、准确地为你计数。它不依赖任何昂贵的智能健身设备,只需要一台普通的电脑(甚至是一台树莓派)和一个摄像头(笔记本自带的或USB摄像头都行)。你只需要在单杠前开始训练,程序就会在后台默默工作,实时在视频画面上标注你的身体关键点,并在你完成一次标准动作后,自动增加计数。

听起来是不是有点像那些高端健身镜或智能健身App的功能?没错,原理是相通的。但我们的实现完全开源、透明,你可以清楚地知道每一行代码在做什么,如何调整算法以适应你自己的动作习惯,甚至把它改造成深蹲计数、俯卧撑计数。这对于健身爱好者、计算机视觉的初学者,或者任何想将编程应用于实际生活场景的朋友来说,都是一个绝佳的练手项目。它涉及了Python编程、OpenCV图像处理、以及轻量级的人体姿态估计等多个有趣的技术点。接下来,我就把自己从零搭建这个项目的完整思路、踩过的坑和最终可运行的源码,毫无保留地分享给你。

2. 核心思路与技术选型:为什么是“姿态估计”而不是“目标检测”

当你决定用计算机视觉来计数引体向上时,第一个面临的技术抉择就是:我们到底要识别什么?

最直观的想法可能是“识别人”或者“识别单杠”。这就是目标检测的思路,比如用YOLO或SSD模型在画面里框出人和单杠。但这个方法对于计数来说,精度远远不够。因为计数依赖的是动作的周期性变化,仅仅知道“那里有个人”是不够的,我们需要知道这个人身体各部位的具体位置和角度变化

举个例子:一个人挂在单杠上轻微晃动,和完成一次标准的引体向上(下巴过杠),在目标检测框里看起来可能差不多,但关节点的运动轨迹却有天壤之别。

因此,我选择了人体姿态估计作为本项目的技术基石。它的目标是识别出人体的一系列关键点,例如:鼻子、左右肩、左右肘、左右腕、左右髋、左右膝、左右踝等。通过追踪这些关键点(尤其是肩、肘、腕)在垂直方向上的运动轨迹,我们就可以清晰地定义出一个“引体向上”动作的周期。

技术栈的确定:

  1. 编程语言:Python。这是计算机视觉和机器学习领域的事实标准,库生态极其丰富,从快速原型开发到性能优化都有成熟的工具链。
  2. 核心视觉库:OpenCV。用于视频流的读取、图像的基本处理(缩放、裁剪、颜色转换)、以及最终结果的绘制(画关键点、画计数文字)和输出。
  3. 姿态估计模型:MediaPipe Pose。这是本项目成功的关键。为什么选择它而不是OpenPose或HRNet?
    • 轻量级与高效率:MediaPipe是Google推出的一个跨平台框架,其Pose解决方案在CPU上就能达到实时推理的速度(30+FPS),完全不需要GPU。这对于我们希望在普通笔记本电脑上流畅运行的需求至关重要。
    • 开箱即用的精度:MediaPipe Pose提供了33个3D人体关键点,对于引体向上这种大肢体运动,其2D投影的精度已经绰绰有余,且模型鲁棒性很好,在部分遮挡(如侧面拍摄时一只手被身体挡住)下也能保持稳定输出。
    • 极简的API:几行代码就能完成模型的初始化和推理,让我们能把精力集中在动作逻辑的判断上,而不是复杂的模型部署上。

项目工作流程简述:

  1. 输入:摄像头实时视频流或本地视频文件。
  2. 处理:对每一帧图像,使用MediaPipe Pose模型检测出人体的33个关键点。
  3. 分析:提取关键点(如双肩中点、手腕)的Y轴(垂直方向)坐标,计算其相对位置和运动速度。
  4. 逻辑判断:根据关键点的运动轨迹,设计一个状态机来判断用户当前处于“悬挂起始”、“上升”、“顶峰锁定”、“下降”中的哪个阶段,从而在完成一个完整周期后计数。
  5. 输出:在原始视频帧上绘制出骨骼关键点和连线,并实时显示当前计数,最后输出处理后的视频。

这个流程清晰地将一个复杂的视觉任务分解为可逐个击破的模块,接下来我们就进入具体的实现环节。

3. 环境搭建与依赖安装:一步到位的配置指南

工欲善其事,必先利其器。为了避免大家在不同操作系统上遇到各种奇怪的依赖问题,我整理了一份经过验证的、清晰的环境配置清单。我们使用conda来创建独立的Python环境,这是管理项目依赖的最佳实践。

步骤1:创建并激活虚拟环境打开你的终端(Windows用Anaconda Prompt或CMD,Mac/Linux用Terminal),执行以下命令。环境名pullup_counter你可以随意替换。

# 创建名为 pullup_counter 的 Python 3.8 环境(3.7-3.10均可,推荐3.8) conda create -n pullup_counter python=3.8 -y # 激活环境 conda activate pullup_counter

激活后,你的命令行提示符前面应该会显示(pullup_counter),表示你已经在这个独立的环境中工作了。

步骤2:安装核心依赖库我们将使用pip来安装所需的包。请按顺序执行以下命令:

# 1. 安装OpenCV。这是处理图像和视频的基础。 pip install opencv-python # 2. 安装MediaPipe。这是实现姿态估计的核心。 pip install mediapipe # 3. (可选但推荐)安装NumPy。MediaPipe和OpenCV都会用到它,通常会自动安装,但明确安装可以避免版本问题。 pip install numpy

注意:关于MediaPipe安装的坑如果你在安装MediaPipe时遇到编译错误或版本冲突,大概率是因为Python版本或系统架构问题。最稳妥的解决方案是直接安装预编译的wheel包。访问 https://pypi.org/project/mediapipe/ 查看与你Python版本和系统匹配的版本号,然后用pip install mediapipe==[版本号]来安装。对于绝大多数用户,直接pip install mediapipe就能成功。

步骤3:验证安装创建一个简单的Python脚本test_env.py,输入以下内容:

import cv2 import mediapipe as mp import numpy as np print(f"OpenCV version: {cv2.__version__}") print(f"MediaPipe version: {mp.__version__}") print(f"NumPy version: {np.__version__}") print("环境测试成功!所有核心库均已就绪。")

运行它:

python test_env.py

如果成功输出版本号且没有报错,那么恭喜你,最磨人的环境配置环节已经顺利通过。接下来就是激动人心的编码部分了。

4. 代码实现深度解析:从关键点提取到状态机逻辑

让我们打开代码编辑器,新建一个名为pull_up_counter.py的文件。我将分模块、逐行解释核心代码,并穿插我在开发过程中总结的注意事项。

4.1 初始化与视频流读取

首先,导入必要的库并初始化MediaPipe Pose模型。

import cv2 import mediapipe as mp import numpy as np # 初始化MediaPipe Pose解决方案 mp_drawing = mp.solutions.drawing_utils # 用于绘制关键点和连线 mp_pose = mp.solutions.pose # 姿态估计模型 # 创建Pose模型实例 # static_image_mode: 对于视频流,设为False以提升速度 # model_complexity: 复杂度,0(快),1(中),2(慢且准)。引体向上用1或0足够。 # smooth_landmarks: 平滑关键点,减少抖动,必须设为True # min_detection_confidence: 检测置信度阈值,高于此值才认为检测到人体 # min_tracking_confidence: 跟踪置信度阈值,用于视频流中维持跟踪 pose = mp_pose.Pose(static_image_mode=False, model_complexity=1, smooth_landmarks=True, min_detection_confidence=0.5, min_tracking_confidence=0.5) # 初始化计数器与状态 counter = 0 stage = None # 动作阶段:'up', 'down'

实操心得:参数调优min_detection_confidencemin_tracking_confidence是影响体验的关键参数。设得太低(如0.3),容易产生误检测,画面里走过一个人都可能被计数;设得太高(如0.8),在动作快速或光线稍暗时容易丢失跟踪。0.5是一个在大多数场景下都比较稳健的折中值。如果在你自己的环境中计数不稳定,可以优先调整这两个参数。

接下来,设置视频源。你可以使用摄像头(cv2.VideoCapture(0))或者本地视频文件(cv2.VideoCapture(‘your_video.mp4’))。

# 使用默认摄像头(编号0)。如果是外接摄像头,可能需要尝试1或2。 cap = cv2.VideoCapture(0) # 设置摄像头分辨率,更高的分辨率有助于提升关键点检测精度,但会增加计算量。 cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) # 如果你有一个录制好的引体向上视频用于测试,可以注释掉上面两行,用下面这行 # cap = cv2.VideoCapture('pullup_demo.mp4')

4.2 关键点提取与核心逻辑:如何定义一次“引体向上”

这是整个项目的“大脑”。我们需要从MediaPipe返回的33个关键点中,选取合适的点来计算和判断。

MediaPipe Pose的关键点索引定义可以在其官方文档找到。对于我们计数引体向上,最有用的是:

  • 左肩:11
  • 右肩:12
  • 左腕:15
  • 右腕:16
  • 左肘:13
  • 右肘:14

一个稳健的策略是使用双肩中点和双腕中点来判定。因为有些人做引体向上时身体会扭转,单侧手腕可能被遮挡,取中点可以增加鲁棒性。

while cap.isOpened(): ret, frame = cap.read() if not ret: break # 如果视频流结束,退出循环 # 为了提升性能,可以将图像尺寸缩小。但注意,缩小会影响远处小目标的检测精度。 # frame = cv2.resize(frame, (640, 360)) # MediaPipe需要RGB格式的图像,但OpenCV默认是BGR image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) image.flags.writeable = False # 设置为False可以提升一点性能 # 核心:进行姿态估计检测! results = pose.process(image) # 改回BGR格式以便OpenCV显示 image.flags.writeable = True image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

现在,results.pose_landmarks里就包含了检测到的关键点坐标(归一化到[0,1]的坐标)。我们来提取并计算:

try: # 1. 提取关键点坐标 landmarks = results.pose_landmarks.landmark # 获取左右肩和左右腕的坐标 left_shoulder = [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x, landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y] right_shoulder = [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x, landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y] left_wrist = [landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].x, landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].y] right_wrist = [landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].x, landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].y] # 2. 计算双肩中点和双腕中点的Y坐标(图像坐标系,原点在左上角,Y向下增大) shoulder_center_y = (left_shoulder[1] + right_shoulder[1]) / 2 wrist_center_y = (left_wrist[1] + right_wrist[1]) / 2 # 3. 计算“手腕相对于肩膀的高度差”。这是判断上升下降的核心指标。 # 注意:Y坐标越大,位置越靠下。所以当手腕在肩膀下方时,这个差值为正。 vertical_diff = wrist_center_y - shoulder_center_y # 4. 状态机逻辑判断 # 阈值需要根据你的拍摄距离和身高进行调整!这是调参的重点。 DOWN_THRESHOLD = 0.05 # 手腕低于肩膀多少时,算作“下放到底”(悬挂状态) UP_THRESHOLD = -0.02 # 手腕高于肩膀多少时,算作“上升到顶”(下巴过杠) # 状态判断 if vertical_diff > DOWN_THRESHOLD: current_stage = "down" elif vertical_diff < UP_THRESHOLD: current_stage = "up" else: # 处于中间过渡状态,保持原阶段不变 current_stage = stage if stage is not None else None # 5. 计数逻辑:完成一个从“down” -> “up” -> “down”的循环,计数+1 if stage == "down" and current_stage == "up": # 检测到从下到上的转换,表示开始上升 pass elif stage == "up" and current_stage == "down": # 检测到从上到下的转换,表示完成了一次完整的引体向上! counter += 1 print(f"计数!当前总数:{counter}") # 在控制台也输出,便于调试 # 更新阶段状态 stage = current_stage except Exception as e: # 如果检测不到人体(landmarks为None),或者计算出错,就跳过这一帧 # print(f"Error: {e}") # 调试时可以打开 pass

核心难点与调参经验:阈值(THRESHOLD)的设定这是整个算法最需要根据实际场景调整的部分。DOWN_THRESHOLDUP_THRESHOLD不是固定值。

  • 它们代表什么?代表手腕Y坐标 - 肩膀Y坐标的归一化差值。因为坐标是归一化的,所以这个值与你的实际身高、距离摄像头的远近无关,只与动作幅度有关。
  • 如何确定?最好的方法是打印日志。在调试阶段,在while循环里加上:
    print(f"垂直差值: {vertical_diff:.3f}, 阶段: {stage}")
    然后你对着摄像头做几个引体向上,观察在“悬挂最低点”和“下巴过杠最高点”时,vertical_diff的典型值是多少。将“最低点”的值稍加一点余量作为DOWN_THRESHOLD,将“最高点”的值稍减一点余量作为UP_THRESHOLD
  • 一个常见的误区:不要设得过于苛刻。因为人体在运动时会有晃动,阈值设得太接近实际极值,可能导致状态在阈值附近来回跳动,造成误计数。适当放宽阈值,利用状态机的“记忆性”(只有完整的状态转换才计数),是保证计数稳定的关键。

4.3 结果可视化与输出

逻辑判断完成后,我们需要把结果直观地展示在视频画面上。

# 6. 使用MediaPipe提供的工具绘制姿态骨架和关键点 if results.pose_landmarks: mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS, mp_drawing.DrawingSpec(color=(245,117,66), thickness=2, circle_radius=2), # 关键点样式 mp_drawing.DrawingSpec(color=(245,66,230), thickness=2, circle_radius=2)) # 连线样式 # 7. 在画面上绘制计数和状态信息 # 绘制一个半透明的矩形作为文字背景 cv2.rectangle(image, (0,0), (300, 120), (245,117,16), -1) # -1表示填充矩形 # 显示计数 cv2.putText(image, 'REPS', (15,25), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,0), 2, cv2.LINE_AA) cv2.putText(image, str(counter), (15,80), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255,255,255), 3, cv2.LINE_AA) # 显示当前阶段 cv2.putText(image, 'STAGE', (130,25), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,0), 2, cv2.LINE_AA) cv2.putText(image, stage if stage else 'N/A', (130,80), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255,255,255), 3, cv2.LINE_AA) # 显示垂直差值(调试用,正式版可注释掉) cv2.putText(image, f'Diff: {vertical_diff:.3f}' if 'vertical_diff' in locals() else 'Diff: N/A', (10, image.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1, cv2.LINE_AA) # 8. 显示最终图像 cv2.imshow('Pull-up Counter', image) # 按‘q’键退出 if cv2.waitKey(10) & 0xFF == ord('q'): break # 释放资源 cap.release() cv2.destroyAllWindows()

至此,一个完整的、实时的引体向上计数器就完成了!运行python pull_up_counter.py,对着摄像头试试看吧。

5. 性能优化与高级功能扩展

基础版本已经能工作,但要做到“好用”,我们还需要考虑更多。这里分享几个优化和扩展的方向。

5.1 提升计数准确性的滤波技巧

原始的关键点坐标可能存在抖动,导致vertical_diff值波动,进而引发状态误判。一个简单有效的改进是加入滑动平均滤波

在初始化部分加入:

import collections # 创建一个队列来存储最近的垂直差值 diff_history = collections.deque(maxlen=5) # 保存最近5帧的值 filtered_diff = 0

在计算完vertical_diff后,进行滤波:

diff_history.append(vertical_diff) filtered_diff = sum(diff_history) / len(diff_history) # 计算简单移动平均 # 后续的状态判断使用 filtered_diff 代替 vertical_diff if filtered_diff > DOWN_THRESHOLD: current_stage = "down" elif filtered_diff < UP_THRESHOLD: current_stage = "up" else: current_stage = stage if stage is not None else None

这样,偶然的单帧跳动就会被平滑掉,状态转换会更加稳定。

5.2 支持离线视频分析与结果保存

很多时候,我们可能想分析一段已经录好的训练视频。修改视频源很简单,但更进一步,我们可以将处理后的视频保存下来,方便分享或复盘。

在初始化cv2.VideoCapture之后,定义视频写入器:

# 获取原视频的帧宽、帧高和帧率 frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = int(cap.get(cv2.CAP_PROP_FPS)) if fps == 0: # 有些摄像头获取不到FPS,给一个默认值 fps = 30 # 创建VideoWriter对象,用于保存处理后的视频 # ‘XVID’是编码器,输出文件为‘output_pullup_counted.avi’ fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output_pullup_counted.avi', fourcc, fps, (frame_width, frame_height))

在主循环中,将最终要显示的image帧写入文件:

# ... (所有处理逻辑之后,imshow之前) out.write(image) # 将绘制好的帧写入视频文件 cv2.imshow('Pull-up Counter', image)

程序结束后,记得释放写入器:

cap.release() out.release() # 释放视频写入器 cv2.destroyAllWindows()

5.3 动作标准度评估的初步思路

一个更有挑战性也更有价值的扩展是评估动作标准度。例如,检测是否“耸肩”、“摆动借力”或“下落未放直”。

这需要引入更多的关键点和几何计算:

  • 检测耸肩:计算肩膀(11,12)与耳朵(7,8)在垂直方向上的距离。在引体向上过程中,这个距离不应显著缩短。
  • 检测身体摆动:计算髋部中点(23,24)的横向(X轴)移动速度或幅度。如果幅度过大,可以给出“摆动借力”的提示。
  • 检测下落幅度:我们已经在用vertical_diffDOWN_THRESHOLD判断是否下放到底。可以增加一个“动作幅度不足”的警告,如果vertical_diff始终小于一个更小的阈值,则提示“未完全下放”。

实现这些功能,需要更复杂的状态管理和阈值设定,但核心方法论是一致的:提取关键点 -> 计算几何或运动特征 -> 设定逻辑规则进行判断。这为将本项目升级为一个初级的“AI健身教练”提供了可能。

6. 常见问题排查与实战调试技巧

在实际运行中,你几乎一定会遇到一些问题。下面是我在开发和测试中遇到的典型问题及解决方法。

问题现象可能原因排查与解决思路
程序报错,无法导入mediapipe1. 虚拟环境未激活或安装不正确。
2. Python版本不兼容。
1. 确认终端前有(pullup_counter)环境标识。
2. 执行pip list检查mediapipeopencv-python是否存在。
3. 尝试使用Python 3.8或3.9重新创建环境。
摄像头黑屏或打不开1. 摄像头被其他程序占用。
2. 摄像头索引号错误。
1. 关闭其他可能使用摄像头的软件(微信、Zoom等)。
2. 尝试将cv2.VideoCapture(0)中的0改为12
3. 在代码开头加入cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)(仅Windows)试试。
检测不到人体,没有骨架绘制1. 人物离摄像头太远或光线太暗。
2. 置信度阈值min_detection_confidence设得太高。
3. 背景杂乱,干扰模型。
1. 确保人物在画面中清晰可见,光线充足。
2. 尝试将min_detection_confidencemin_tracking_confidence暂时调低至0.4。
3. 尝试面对纯色墙壁进行测试。
计数不准(漏数或多计)1.UP_THRESHOLDDOWN_THRESHOLD设置不合理。
2. 关键点抖动导致状态跳变。
3. 动作不标准(如摆动太大)。
1.这是最可能的原因!务必使用“打印日志法”调试阈值。在循环中打印vertical_diffstage,观察动作极值点对应的数值,重新设定阈值。
2. 引入滑动平均滤波(见5.1节),平滑数据。
3. 调整摄像头角度,尽量保持人物正面或侧面,避免严重遮挡。
程序运行很卡,帧率很低1. 图像分辨率太高。
2.model_complexity参数设为2。
3. 电脑性能不足。
1. 将cv2.VideoCapture读取的分辨率降低(如640x480)。
2. 将model_complexity设为0(最快)或1。
3. 在主循环中,可以对图像进行缩放(如frame = cv2.resize(frame, (640, 360))),注意:缩放要在pose.process之前进行,且缩放后绘制骨架的坐标需要相应换算。
保存的视频无法播放或花屏1. 编解码器‘XVID’不支持。
2. 写入的帧尺寸与VideoWriter初始化尺寸不匹配。
1. 尝试更换编解码器,如‘MJPG’fourcc = cv2.VideoWriter_fourcc(*'MJPG'),文件后缀改为.avi
2. 确保out.write(image)中的image尺寸与创建VideoWriter时指定的(frame_width, frame_height)完全一致。一个稳妥的做法是使用image.shape[1]image.shape[0]来获取尺寸。

终极调试心法:可视化与日志当程序行为不符合预期时,最强大的工具就是print()cv2.putText()

  1. 把关键数据画在屏幕上:就像示例代码中显示vertical_diff一样,把stagecounter、甚至左右手腕的原始Y坐标都实时显示出来。这样你一眼就能看到程序“认为”的数值是什么。
  2. 在控制台打印详细日志:在状态改变、计数等关键节点打印信息,方便你复盘程序逻辑的执行流程。
  3. 录制一小段测试视频:用手机录制一段自己做引体向上的视频(10-15秒即可),然后用程序分析这个本地视频文件。这样可以让你反复、暂停地观察程序在每一帧的处理结果,是调整阈值和逻辑的黄金手段。

7. 项目总结与未来展望

通过这个项目,我们完成了一个从实际问题出发,利用现代计算机视觉库快速构建解决方案的完整流程。它麻雀虽小,五脏俱全:从环境配置、模型调用、数据提取、逻辑设计、到可视化交互。最重要的是,它提供了一个可运行的、能够解决真实需求的代码原型。

我个人在反复调试这个项目后,最深的体会是:在AI应用开发中,数据和逻辑的质量往往比模型本身更重要。MediaPipe Pose已经提供了一个非常强大的“眼睛”,但如何用好它提供的“关键点”数据,设计出鲁棒的业务逻辑(状态机),才是项目成败的关键。这其中的阈值设定、滤波处理、异常处理,都需要开发者对业务(引体向上动作)本身有深刻的理解,并通过大量的实验和观察来打磨。这个过程,是任何预训练模型都无法替代的。

这个项目完全可以作为一个起点,进行更多有趣的扩展:

  • 多动作识别:修改状态判断逻辑,可以同样实现俯卧撑、深蹲、仰卧起坐的计数。你只需要重新定义“完成一次动作”所对应的关键点运动模式。
  • 部署到移动端:MediaPipe本身就有Android和iOS的SDK。理论上,你可以将这套逻辑移植到手机App上,实现随身携带的健身计数器。
  • 云端分析与历史记录:将每次训练的次数、时间戳甚至关键点数据上传到服务器,可以生成长期的健身数据报表和分析图表。
  • 结合语音提示:在计数时或动作不标准时,用语音合成(TTS)库给出实时反馈,体验会更像健身教练。

希望这份超详细的指南和源码,不仅能帮你实现一个引体向上计数器,更能让你感受到用代码解决生活问题的乐趣和成就感。编程不只是冰冷的逻辑,也可以是充满活力的创造。如果你在实现过程中有任何新的发现或有趣的改进,也欢迎分享出来。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 13:49:29

喷码缺陷检测实战:轻量CNN+传统图像处理的产线级方案

简介&#xff1a;本资源是一套面向计算机、自动化及人工智能方向本科生的毕业设计级项目&#xff0c;聚焦工业质检场景中的喷码缺陷智能识别问题&#xff0c;适用于课程设计、期末大作业及毕业设计实践。项目基于Python实现&#xff0c;融合图像预处理、OCR字符提取与规则比对、…

作者头像 李华
网站建设 2026/9/2 13:49:11

gpt4free LMArena 报错修不好?按症状三步自助恢复

gpt4free LMArena 报错修不好&#xff1f;按症状三步自助恢复 【免费下载链接】gpt4free The official gpt4free repository | various collection of powerful language models | opus 4.6 gpt 5.3 kimi 2.5 deepseek v3.2 gemini 3 项目地址: https://gitcode.com/GitHub_T…

作者头像 李华
网站建设 2026/9/2 13:49:04

AionUi 入门指南:本地AI多模型协作的完整教程

AionUi 入门指南&#xff1a;本地AI多模型协作的完整教程 【免费下载链接】AionUi Open-source 24/7 Cowork app for OpenClaw, Hermes, Claude Code, Codex, OpenCode and 20 more CLI Agent | Customize your assistants | Team them up&#xff5c;Star if you like it! 项…

作者头像 李华
网站建设 2026/9/2 13:44:01

技术选型实战指南:新旧版本迭代中的理性决策与渐进迁移策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 13:40:45

Agent技术发展与应用场景解析:智能代理赋能各领域效率升级新路径

很多研究生写文献综述时&#xff0c;最大的问题不是找不到论文&#xff0c;而是找到了很多论文&#xff0c;却不知道怎么分类、比较和提炼研究空白。现在&#xff0c;AI 可以帮助完成检索、阅读、笔记整理和代码分析&#xff0c;但不同工具适合的任务并不一样。合理分工&#x…

作者头像 李华