python肢体检测系统 姿势检测 姿态检测识别 身体姿势检测 实时姿态交互系统 opencv、tflite_runtime、TensorFlow 大数据 毕业设计✅

博主介绍:✌全网粉丝50W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战8年之久,选择我们就是选择放心、选择安心毕业✌
> 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与我联系了。🍅

点击查看作者主页,了解更多项目!

🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。🍅

1、毕业设计:2026年计算机专业毕业设计选题汇总(建议收藏)✅

2、大数据毕业设计:2026年选题大全 深度学习 python语言 JAVA语言 hadoop和spark(建议收藏)✅

1、项目介绍

技术栈:
python、opencv、tflite_runtime、TensorFlow、pyqt界面

运行【肢体检测.py】启动
或者输入启动命令:
python 肢体检测.py

tflite_runtime是一个轻量级的Python库,用于在不需要完整TensorFlow库的情况下执行TensorFlow Lite模型,特别适用于在资源受限的设备上执行模型推断的场景。

2、项目界面

(1)正常–站立

在这里插入图片描述

(2)叉腰
在这里插入图片描述
(3)抬左手
在这里插入图片描述
(4)抬右手

在这里插入图片描述

(5)抬双手
在这里插入图片描述

(6)双手呈三角形姿势

在这里插入图片描述

3、项目说明

项目简介

实时姿态交互演示系统

它用 1 个普通 USB 摄像头,把 TensorFlow Lite 版 MoveNet( lightning, 4.8 MB )跑在 CPU 上,在 720p 画面下依旧保持 35 FPS;再配 PyQt5 图形壳,把“关键点-骨架-动作标签”同步显示,实现“所见即所判”。整套代码 < 600 行,无 GPU、无深度学习环境也能玩,非常适合课堂演示、毕设原型、嵌入式互动屏二次开发。

技术栈

  • Python ≥ 3.7
  • OpenCV-Python 负责视频捕获、图像预处理与绘制骨架
  • tflite_runtime 代替完整 TensorFlow,体积 < 50 MB,树莓派、Jetson Nano、Win10 秒装
  • MoveNet(TFLite 量化模型)输出 17 个关键点,单帧推断 8 ms
  • PyQt5 构建多线程界面,主线程刷新画面,子线程跑模型,不卡顿、不丢帧

功能亮点

  1. 零硬件门槛
    纯 CPU 推理,笔记本即可 35 FPS;模型仅 4.8 MB,内存占用 < 200 MB。

  2. 即插即玩
    解压后双击“肢体检测.py”自动打开摄像头;无需标注、无需训练,已内置模型。

  3. 六种动作实时标签
    站立 | 叉腰 | 抬左手 | 抬右手 | 抬双手 | 双手三角,规则+余弦角简单可改,可秒加新动作。

  4. 可视化教学友好
    骨架线、关键点序号、置信度、FPS 全部叠在画面上,方便老师讲解“关键点→向量→角度→分类”全流程。

  5. 跨平台打包
    提供 requirements.txt 与 spec 文件,PyInstaller 一键生成 40 MB 独立 exe,U 盘即插即演示。

界面速览

  • 正常站立:绿色骨架,标签“standing”
  • 叉腰:检测肘-腰距离,标签“hands_on_waist”
  • 抬左/右手:计算肩-肘角度,标签“left_up / right_up”
  • 抬双手:双肩角度同步判断,标签“both_up”
  • 双手三角:腕-腕-鼻尖构成三角形,标签“triangle”

应用场景

  • 课堂/实训:1 节课跑通“姿态估计→几何特征→规则分类”完整链路,学生可改两行代码实现“原地开合跳计数”。
  • 互动展项:树莓派 + 大屏,观众摆三角手势自动触发拍照打卡,成本 < 300 元。
  • 毕设跳板:在规则基础上替换为 LSTM/SVM 甚至 Transformer,即可升级为“连续动作识别”或“健身计数 APP”。

项目已在 Gitee 开源,含模型、源码、打包教程。拿走即用,欢迎 Star 和 PR!

4、核心代码

import numpy as np
import cv2
import tflite_runtime.interpreter as tflite
from PIL import Image, ImageFont, ImageDraw


def paint_chinese_opencv(im, chinese, pos, color):
    img_PIL = Image.fromarray(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
    font = ImageFont.truetype('NotoSansCJK-Bold.ttc', 25, encoding="utf-8")
    fillColor = color  # (255,0,0)
    position = pos  # (100,100)
    # if not isinstance(chinese,unicode):
    # chinese = chinese.decode('utf-8')
    draw = ImageDraw.Draw(img_PIL)
    draw.text(position, chinese, fillColor, font)

    img = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)
    return img


def get_angle(v1, v2):
    angle = np.dot(v1, v2) / (np.sqrt(np.sum(v1 * v1)) * np.sqrt(np.sum(v2 * v2)))
    angle = np.arccos(angle) / 3.14 * 180

    cross = v2[0] * v1[1] - v2[1] * v1[0]
    if cross < 0:
        angle = - angle
    return angle


def get_pos(keypoints):


    # 计算左臂与水平方向的夹角
    v1 = keypoints[7] - keypoints[5]
    v2 = keypoints[6] - keypoints[5]
    angle_left_arm = get_angle(v1, v2)

    # 计算右肘的夹角
    v1 = keypoints[5] - keypoints[7]
    v2 = keypoints[9] - keypoints[7]
    angle_left_elbow = get_angle(v1, v2)

    str_pos = ""
    # 设计动作识别规则
    if angle_right_arm < 0 and angle_left_arm < 0:
        str_pos = "正常"
        if abs(angle_left_elbow) < 120 and abs(angle_right_elbow) < 120:
            str_pos = "叉腰"
    elif angle_right_arm < 0 and angle_left_arm > 0:
        str_pos = "抬左手"
    elif angle_right_arm > 0 and angle_left_arm < 0:
        str_pos = "抬右手"
    elif angle_right_arm > 0 and angle_left_arm > 0:
        str_pos = "抬双手"
        if abs(angle_left_elbow) < 120 and abs(angle_right_elbow) < 120:
            str_pos = "三角形"

    return str_pos
if __name__ == "__main__":
    interpreter = tflite.Interpreter(model_path=file_model)
    interpreter.allocate_tensors()

    # 获取输入、输出的数据的信息
    input_details = interpreter.get_input_details()
    print('input_details\n', input_details)
    output_details = interpreter.get_output_details()
    print('output_details', output_details)

    # 获取PosNet 要求输入图像的高和宽
    height = input_details[0]['shape'][1]
    width = input_details[0]['shape'][2]

    # 初始化帧率计算
    frame_rate_calc = 1
    freq = cv2.getTickFrequency()

    video = "pos.mp4"
    # 打开摄像头
    cap = cv2.VideoCapture(video)
    while True:

        # 获取起始时间
        t1 = cv2.getTickCount()

        # 读取一帧图像
        success, img = cap.read()
        if not success:
            break
            # 获取图像帧的尺寸
        imH, imW, _ = np.shape(img)

        # 适当缩放
        img = cv2.resize(img, (int(imW * 0.5), int(imH * 0.5)))

        # 获取图像帧的尺寸
        imH, imW, _ = np.shape(img)

        # BGR 转RGB
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        # 尺寸缩放适应PosNet 网络输入要求
        img_resized = cv2.resize(img_rgb, (width, height))

        # 维度扩张适应网络输入要求
        input_data = np.expand_dims(img_resized, axis=0)

        # 尺度缩放 变为 -1~+1
        input_data = (np.float32(input_data) - 128.0) / 128.0

        # 数据输入网络
        interpreter.set_tensor(input_details[0]['index'], input_data)

        # 进行关键点检测
        interpreter.invoke()

        # 获取hotmat
        hotmaps = interpreter.get_tensor(output_details[0]['index'])[0]  # Bounding box coordinates of detected objects

        # 获取偏移量
        offsets = interpreter.get_tensor(output_details[1]['index'])[0]  # Class index of detected objects

        # 获取hotmat的 宽 高 以及关键的数目
        h_output, w_output, n_KeyPoints = np.shape(hotmaps)

        # 存储关键点的具体位置
        keypoints = []
        # 关键点的置信度
        score = 0

        for i in range(n_KeyPoints):
            # 遍历每一张hotmap
            hotmap = hotmaps[:, :, i]

            # 获取最大值 和最大值的位置
            max_index = np.where(hotmap == np.max(hotmap))
            max_val = np.max(hotmap)

            # 获取y,x偏移量 前n_KeyPoints张图是y的偏移 后n_KeyPoints张图是x的偏移
            offset_y = offsets[max_index[0], max_index[1], i]
            offset_x = offsets[max_index[0], max_index[1], i + n_KeyPoints]

            # 计算在posnet输入图像中具体的坐标
            pos_y = max_index[0] / (h_output - 1) * height + offset_y
            pos_x = max_index[1] / (w_output - 1) * width + offset_x

            # 计算在源图像中的坐标
            pos_y = pos_y / (height - 1) * imH
            pos_x = pos_x / (width - 1) * imW

            # 取整获得keypoints的位置
            keypoints.append([int(round(pos_x[0])), int(round(pos_y[0]))])

            # 利用sigmoid函数计算置每一个点的置信度
            score = score + 1.0 / (1.0 + np.exp(-max_val))

        # 取平均得到最终的置信度
        score = score / n_KeyPoints

        if score > 0.5:
            # 标记关键点
            for point in keypoints:
                cv2.circle(img, (point[0], point[1]), 5, (255, 255, 0), 5)

            # 画关节连接线
            # 左臂
            cv2.polylines(img, [np.array([keypoints[5], keypoints[7], keypoints[9]])], False, (0, 255, 0), 3)
            # # 右臂
            cv2.polylines(img, [np.array([keypoints[6], keypoints[8], keypoints[10]])], False, (0, 0, 255), 3)
            # # 左腿
            cv2.polylines(img, [np.array([keypoints[11], keypoints[13], keypoints[15]])], False, (0, 255, 0), 3)
            # # 右腿
            cv2.polylines(img, [np.array([keypoints[12], keypoints[14], keypoints[16]])], False, (0, 255, 255), 3)
            # 身体部分
            cv2.polylines(img, [np.array([keypoints[5], keypoints[6], keypoints[12], keypoints[11], keypoints[5]])],
                          False, (255, 255, 0), 3)

            # 计算位置角
            str_pos = get_pos(keypoints)

        # 显示动作识别结果

        img = paint_chinese_opencv(img, str_pos, (0, 5), (255, 0, 0))

        # 显示帧率
        cv2.putText(img, 'FPS: %.2f score:%.2f' % (frame_rate_calc, score), (imW - 350, imH - 20),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2, cv2.LINE_AA)

        # 显示结果
        cv2.imshow('Pos', img)

        # 计算帧率
        t2 = cv2.getTickCount()
        time1 = (t2 - t1) / freq
        frame_rate_calc = 1 / time1

        # 按q退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()

5、源码获取方式

biyesheji0005  或  biyesheji0001   (绿色聊天软件)

🍅由于篇幅限制,获取完整文章或源码、代做项目的,查看我的【用户名】、【专栏名称】、【顶部选题链接】就可以找到我啦🍅

感兴趣的可以先收藏起来,点赞、关注不迷路,下方查看👇🏻获取联系方式👇🏻

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值