关于python:Python玩人工智能你的俯卧撑做对了吗

4次阅读

共计 4708 个字符,预计需要花费 12 分钟才能阅读完成。

咱们曾经有了《Python 玩人工智能:你能做几个引体向上?》和《Python 玩人工智能:你的仰卧起坐达标了吗?》,明天就来玩俯卧撑啦!

1. 筹备工作

1.1 装置 Python3.8.x

1.2 装置 PyCharm 社区版

1.3 创立我的项目

1.4 装置我的项目应用工具包

1.1 下载安装 Python3.8.x 版本

首先咱们的电脑上要装置 Python3.8.x。Python 3.8.x : https://www.python.org/downlo…

1.2 下载安装 PyCharm 社区版

PyCharm: https://www.jetbrains.com/pyc… 当然你也能够应用本人喜爱的 IDE。

1.3 创立一个 Python 我的项目

装置好 Python 和 PyCharm 之后,咱们能够启动 PyCharm,创立一个新的 Python 我的项目。抉择我的项目的存储地位,创立我的项目时,能够让 PyCharm 帮忙创立一个虚拟环境(virtualenv), 虚拟环境能够了解为这个我的项目专属的编程环境,不会影响其余的我的项目。

1.4 装置我的项目所用的工具包

我的项目创立好之后,咱们关上 PyCharm 的 Terminal 窗口,在这里咱们能够输出以下命令来装置这个我的项目所须要的工具包:opencv-python mediapipe numpy pyautogui。上面的命令会从网络上下载工具包并装置,如果你看到最初有“Successfully installed…”这样的英文,示意装置胜利了。

pip install opencv-python mediapipe numpy

也能够点开 PyCharm 的设置,看到我的项目的 Python 环境中,是否有以上的工具包,如果有就示意装置胜利了。

2. 编写程序

2.1 创立 poseutil.py 模块

2.2 编写 pushup.py

2.3 测试运行

2.1 创立 poseutil.py 模块

创立一个新的 Python 文件,取名为 poseutil.py,这是咱们创立的姿态辨认的模块,在这个模块中有一个 PoseDetector 的姿态识别器类,应用它能够辨认人体姿态、获取人体姿态数据以及计算人体姿态相干点的角度。

import cv2
import mediapipe as mp
import math

class PoseDetector():
    '''人体姿态检测类'''

    def __init__(self,
                 static_image_mode=False,
                 upper_body_only=False,
                 smooth_landmarks=True,
                 min_detection_confidence=0.5,
                 min_tracking_confidence=0.5):
        '''
        初始化
        :param static_image_mode: 是否是动态图片,默认为否
        :param upper_body_only: 是否是上半身,默认为否
        :param smooth_landmarks: 设置为 True 缩小抖动
        :param min_detection_confidence: 人员检测模型的最小置信度值,默认为 0.5
        :param min_tracking_confidence: 姿态可信标记的最小置信度值,默认为 0.5
        '''
        self.static_image_mode = static_image_mode
        self.upper_body_only = upper_body_only
        self.smooth_landmarks = smooth_landmarks
        self.min_detection_confidence = min_detection_confidence
        self.min_tracking_confidence = min_tracking_confidence
        # 创立一个 Pose 对象用于检测人体姿态
        self.pose = mp.solutions.pose.Pose(self.static_image_mode, self.upper_body_only, self.smooth_landmarks,
                                           self.min_detection_confidence, self.min_tracking_confidence)

    def find_pose(self, img, draw=True):
        '''
        检测姿态办法
        :param img: 一帧图像
        :param draw: 是否画出人体姿态节点和连贯图
        :return: 解决过的图像
        '''
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # pose.process(imgRGB) 会辨认这帧图片中的人体姿态数据,保留到 self.results 中
        self.results = self.pose.process(imgRGB)
        if self.results.pose_landmarks:
            if draw:
                mp.solutions.drawing_utils.draw_landmarks(img, self.results.pose_landmarks,
                                                          mp.solutions.pose.POSE_CONNECTIONS)
        return img

    def find_positions(self, img):
        '''
        获取人体姿态数据
        :param img: 一帧图像
        :param draw: 是否画出人体姿态节点和连贯图
        :return: 人体姿态数据列表
        '''
        # 人体姿态数据列表,每个成员由 3 个数字组成:id, x, y
        # id 代表人体的某个关节点,x 和 y 代表坐标地位数据
        self.lmslist = []
        if self.results.pose_landmarks:
            for id, lm in enumerate(self.results.pose_landmarks.landmark):
                h, w, c = img.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                self.lmslist.append([id, cx, cy])

        return self.lmslist

    def find_angle(self, img, p1, p2, p3, draw=True):
        '''
        获取人体姿态中 3 个点 p1-p2-p3 的角度
        :param img: 一帧图像
        :param p1: 第 1 个点
        :param p2: 第 2 个点
        :param p3: 第 3 个点
        :param draw: 是否画出 3 个点的连贯图
        :return: 角度
        '''
        x1, y1 = self.lmslist[p1][1], self.lmslist[p1][2]
        x2, y2 = self.lmslist[p2][1], self.lmslist[p2][2]
        x3, y3 = self.lmslist[p3][1], self.lmslist[p3][2]

        # 应用三角函数公式获取 3 个点 p1-p2-p3,以 p2 为角的角度值,0-180 度之间
        angle = int(math.degrees(math.atan2(y1 - y2, x1 - x2) - math.atan2(y3 - y2, x3 - x2)))
        if angle < 0:
            angle = angle + 360
        if angle > 180:
            angle = 360 - angle

        if draw:
            cv2.circle(img, (x1, y1), 20, (0, 255, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), 30, (255, 0, 255), cv2.FILLED)
            cv2.circle(img, (x3, y3), 20, (0, 255, 255), cv2.FILLED)
            cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255, 3))
            cv2.line(img, (x2, y2), (x3, y3), (255, 255, 255, 3))
            cv2.putText(img, str(angle), (x2 - 50, y2 + 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 255), 2)

        return angle
    

2.2 编写 pushup.py

编写上面的代码,调用 poseutil 模块,获取人体姿态数据,并计算人体中肩膀、臀部、膝盖三个点以及肩膀、手肘、手段形成的角度,通过这 2 个角度来判断俯卧撑是否规范。

# 导入 opencv 工具包
import cv2
# 导入 numpy
import numpy as np
# 导入姿态识别器
from poseutil import PoseDetector

# 关上视频文件
cap = cv2.VideoCapture('videos/pushup.mp4')
# 姿态识别器
detector = PoseDetector()

# 方向与个数
dir = 0  # 0 为下,1 为上
count = 0

# 视频宽度高度
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# 录制视频设置
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('videos/pushupoutput.mp4', fourcc, 30.0, (width, height))

while True:
    # 读取摄像头,img 为每帧图片
    success, img = cap.read()
    if success:
        h, w, c = img.shape
        # 辨认姿态
        img = detector.find_pose(img, draw=True)
        # 获取姿态数据
        positions = detector.find_positions(img)

        if positions:
            # 获取俯卧撑的角度
            angle1 = detector.find_angle(img, 12, 24, 26)
            angle2 = detector.find_angle(img, 12, 14, 16)
            # 进度条长度
            bar = np.interp(angle2, (45, 150), (w // 2 - 100, w // 2 + 100))
            cv2.rectangle(img, (w // 2 - 100, h - 150), (int(bar), h - 100), (0, 255, 0), cv2.FILLED)
            # 角度小于 50 度认为撑下
            if angle2 <= 50 and angle1 >= 165 and angle1 <= 175:
                if dir == 0:
                    count = count + 0.5
                    dir = 1
            # 角度大于 125 度认为撑起
            if angle2 >= 125 and angle1 >= 165 and angle1 <= 175:
                if dir == 1:
                    count = count + 0.5
                    dir = 0
            cv2.putText(img, str(int(count)), (w // 2, h // 2), cv2.FONT_HERSHEY_SIMPLEX, 10, (255, 255, 255), 20, cv2.LINE_AA)

        # 关上一个 Image 窗口显示视频图片
        cv2.imshow('Image', img)

        # 录制视频
        out.write(img)
    else:
        # 视频完结退出
        break

    # 如果按下 q 键,程序退出
    key = cv2.waitKey(1)
    if key == ord('q'):
        break

# 敞开视频保留器
out.release()
# 敞开摄像头
cap.release()
# 关闭程序窗口
cv2.destroyAllWindows()

2.3 测试运行

在理论运行测试时,咱们设置的俯卧撑角度是 50 度到 125 度之间,能够依据拍摄角度来调整,另外咱们要求臀部角度在 165 度到 175 度之间,这个也是能够调整的。倡议拍摄视频或者应用摄像头时更多的放在人体的侧上局部,这样检测的会比拟精确。

正文完
 0