咱们曾经有了《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 cv2import mediapipe as mpimport mathclass 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# 导入numpyimport 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度之间,这个也是能够调整的。倡议拍摄视频或者应用摄像头时更多的放在人体的侧上局部,这样检测的会比拟精确。