We already have Python Playing AI: How many pull-ups can you Do? Playing AI with Python: Are Your sit-ups Up to scratch? Today to play push-ups!

1. Preparation

1.1 installation Python3.8. X

1.2 Installing PyCharm

1.3 Creating a Project

1.4 Installation Projects Use the tool package

1.1 Download and install python3.8. x

Python3.8.x will be installed on our computer first. Python 3.8 x: www.python.org/downloads/

1.2 Download and install PyCharm

PyCharm: www.jetbrains.com/pycharm/dow… Of course, you can use your favorite IDE.

1.3 Creating a Python project

After installing Python and PyCharm, we can start PyCharm and create a new Python project. When creating a project, PyCharm can help you create a VirtualEnv. The virtual environment can be understood as the programming environment of this project and will not affect other projects.

1.4 Installing the Project Tool package

After the project is created, we open the Terminal window of PyCharm, where we can type the following command to install the tool kit required for the project: Opencv-Python mediapipe numpy PyAutogui. The following command will download the toolkit from the network and install it. If you see “Successfully Installed… The installation is successful.

pip install opencv-python mediapipe numpy
Copy the code

You can also click on the PyCharm Settings to see if the above toolkits are present in the Python environment of your project. If so, the installation is successful.

2. Write programs

2.1 Create the Poseutil.py module

2.2 write a pushup. Py

2.3 Test Run

2.1 Create the Poseutil.py module

Create a new Python file called poseutil.py. This is the pose recognition module we created. In this module, we have a PoseDetector pose recognizer class that can be used to identify human poses, capture pose data, and calculate the Angle of points associated with human poses.

import cv2
import mediapipe as mp
import math

class PoseDetector() :
    Human posture detection

    def __init__(self,
                 static_image_mode=False,
                 upper_body_only=False,
                 smooth_landmarks=True,
                 min_detection_confidence=0.5,
                 min_tracking_confidence=0.5) :
        Initializing :param static_image_mode: static image (default: no) :param upper_body_only: upper body (default: no) :param smooth_landmarks: Set to True to reduce jitter :param min_detection_CONFIDENCE: minimum confidence value of the staff detection model, default is 0.5 :param min_tracking_confidence: minimum confidence value of the pose trust flag, default is 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
        Create a Pose object to detect human body posture
        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) :
        "" Detection posture method: Param IMG: a frame image: Param draw: whether to draw the human body posture node and connection diagram :return: processed image" "
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # pose. Process (imgRGB) will recognize the human pose data in this frame and save it to 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) :
        "Get human pose data :param img: a frame image: Param Draw: whether to draw human pose nodes and link diagrams :return: list of human pose data"
        # Body posture data list, each member consists of 3 numbers: ID, X, Y
        # ID represents a node of the human body, x and y represent coordinate position data
        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) :
        Param img: a frame image: Param P1: first point: Param P2: second point: Param P3: third point: Param draw: param img: a frame image: Param P1: first point: Param P2: second point: Param P3: third point: Param draw: Whether to draw a connection diagram of 3 points:
        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]

        # Use the trigonometric formula to obtain the Angle values of 3 points p1-P2-p3, with Angle P2 as the value, 0-180 degrees
        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
    
Copy the code

2.2 write a pushup. Py

Write the following code, call poseutil module, obtain the data of human body posture, and calculate the Angle of shoulder, hip and knee as well as shoulder, elbow and wrist, judge whether push-ups are standard by these two angles.

# Import opencV toolkit
import cv2
# import numpy
import numpy as np
# import pose recognizer
from poseutil import PoseDetector

# Open the video file
cap = cv2.VideoCapture('videos/pushup.mp4')
# Pose recognizer
detector = PoseDetector()

# Direction and number
dir = 0  # 0 is down, 1 is up
count = 0

# Video width height
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# Record video Settings
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('videos/pushupoutput.mp4', fourcc, 30.0, (width, height))

while True:
    Img for each frame
    success, img = cap.read()
    if success:
        h, w, c = img.shape
        # Recognize posture
        img = detector.find_pose(img, draw=True)
        Get posture data
        positions = detector.find_positions(img)

        if positions:
            Get the push up Angle
            angle1 = detector.find_angle(img, 12.24.26)
            angle2 = detector.find_angle(img, 12.14.16)
            Progress bar length
            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)
            # If the Angle is less than 50 degrees, it is considered to be under
            if angle2 <= 50 and angle1 >= 165 and angle1 <= 175:
                if dir= =0:
                    count = count + 0.5
                    dir = 1
            # If the Angle is greater than 125 degrees, it is considered to be supported
            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)

        Open an Image window to display the video Image
        cv2.imshow('Image', img)

        # Record video
        out.write(img)
    else:
        # Video end exit
        break

    If the q key is pressed, the program exits
    key = cv2.waitKey(1)
    if key == ord('q') :break

# Close the video saver
out.release()
# Turn off camera
cap.release()
Close the program window
cv2.destroyAllWindows()

Copy the code

2.3 Test Run

In the actual running test, we set the push up Angle between 50 degrees and 125 degrees, which can be adjusted according to the shooting Angle. In addition, we required the hip Angle between 165 degrees and 175 degrees, which can also be adjusted. It is recommended to place the camera more on the side of the human body when shooting video or using the camera, so that the detection will be more accurate.