preface:
At the Winter Olympics, Gu ailing "soared to the sky", Su Yiming "A blockbuster", the dream team of short track speed skating "forge ahead"... The athletes' spirit of challenging the limit and climbing the peak has aroused the enthusiasm of countless audiences!
These athletes who ignite the Winter Olympic stadium are full of vigorous youth and write a bloody legend of life.
Daily question, do you insist on fitness exercise?
Do you exercise in the right way?
Text:
In the Singapore Army, there is a test called IPPT (personal physical fitness test). The difficulty of this test lies not in its high physical requirements, but in the electronic machine used to calculate the number of push ups and sit ups.
Like most people, my push ups are always below standard (according to the advice of the machine). In addition, due to the lack of practice referring to machine standards, many NSMen (who have completed two years of compulsory service) are difficult to achieve good results in the IPPT test.
Therefore, I decided to use mediapipe and OpenCV to create a program to track our push ups and ensure that every push up reached the standard.
Limb joints detected by mediapipe pose module
import cv2 import mediapipe as mp import math class poseDetector() : def __init__(self, mode=False, complexity=1, smooth_landmarks=True, enable_segmentation=False, smooth_segmentation=True, detectionCon=0.5, trackCon=0.5): self.mode = mode self.complexity = complexity self.smooth_landmarks = smooth_landmarks self.enable_segmentation = enable_segmentation self.smooth_segmentation = smooth_segmentation self.detectionCon = detectionCon self.trackCon = trackCon self.mpDraw = mp.solutions.drawing_utils self.mpPose = mp.solutions.pose self.pose = self.mpPose.Pose(self.mode, self.complexity, self.smooth_landmarks, self.enable_segmentation, self.smooth_segmentation, self.detectionCon, self.trackCon) def findPose (self, img, draw=True): imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) self.results = self.pose.process(imgRGB) if self.results.pose_landmarks: if draw: self.mpDraw.draw_landmarks(img,self.results.pose_landmarks, self.mpPose.POSE_CONNECTIONS) return img def findPosition(self, img, draw=True): self.lmList = [] if self.results.pose_landmarks: for id, lm in enumerate(self.results.pose_landmarks.landmark): #finding height, width of the image printed h, w, c = img.shape #Determining the pixels of the landmarks cx, cy = int(lm.x * w), int(lm.y * h) self.lmList.append([id, cx, cy]) if draw: cv2.circle(img, (cx, cy), 5, (255,0,0), cv2.FILLED) return self.lmList def findAngle(self, img, p1, p2, p3, draw=True): #Get the landmarks x1, y1 = self.lmList[p1][1:] x2, y2 = self.lmList[p2][1:] x3, y3 = self.lmList[p3][1:] #Calculate Angle angle = math.degrees(math.atan2(y3-y2, x3-x2) - math.atan2(y1-y2, x1-x2)) if angle < 0: angle += 360 if angle > 180: angle = 360 - angle elif angle > 180: angle = 360 - angle # print(angle) #Draw if draw: cv2.line(img, (x1, y1), (x2, y2), (255,255,255), 3) cv2.line(img, (x3, y3), (x2, y2), (255,255,255), 3) cv2.circle(img, (x1, y1), 5, (0,0,255), cv2.FILLED) cv2.circle(img, (x1, y1), 15, (0,0,255), 2) cv2.circle(img, (x2, y2), 5, (0,0,255), cv2.FILLED) cv2.circle(img, (x2, y2), 15, (0,0,255), 2) cv2.circle(img, (x3, y3), 5, (0,0,255), cv2.FILLED) cv2.circle(img, (x3, y3), 15, (0,0,255), 2) cv2.putText(img, str(int(angle)), (x2-50, y2+50), cv2.FONT_HERSHEY_PLAIN, 2, (0,0,255), 2) return angle def main(): detector = poseDetector() cap = cv2.VideoCapture(0) while cap.isOpened(): ret, img = cap.read() #ret is just the return variable, not much in there that we will use. if ret: img = detector.findPose(img) cv2.imshow('Pose Detection', img) if cv2.waitKey(10) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() if __name__ == "__main__": main()
The above is the code of this program.
The above code comes from posemodule Py has the following functions:
-
The pose detection module of ipape is activated.
-
Test the human body.
-
Find the position of different limb joints on the human body according to the model. (the limbs are shown in the picture above).
-
Find the angle between the joints (depending on the joint you select). For my push up program, I chose to find the angles of my elbows, shoulders and hips, because these are crucial to the standard of push ups.
Next is the actual push up count code. We use PoseModule and determine a criterion for whether push ups are qualified or not.
import cv2 import mediapipe as mp import numpy as np import PoseModule as pm cap = cv2.VideoCapture(0) detector = pm.poseDetector() count = 0 direction = 0 form = 0 feedback = "Fix Form" while cap.isOpened(): ret, img = cap.read() #640 x 480 #Determine dimensions of video - Help with creation of box in Line 43 width = cap.get(3) # float `width` height = cap.get(4) # float `height` # print(width, height) img = detector.findPose(img, False) lmList = detector.findPosition(img, False) # print(lmList) if len(lmList) != 0: elbow = detector.findAngle(img, 11, 13, 15) shoulder = detector.findAngle(img, 13, 11, 23) hip = detector.findAngle(img, 11, 23,25) #Percentage of success of pushup per = np.interp(elbow, (90, 160), (0, 100)) #Bar to show Pushup progress bar = np.interp(elbow, (90, 160), (380, 50)) #Check to ensure right form before starting the program if elbow > 160 and shoulder > 40 and hip > 160: form = 1 #Check for full range of motion for the pushup if form == 1: if per == 0: if elbow <= 90 and hip > 160: feedback = "Up" if direction == 0: count += 0.5 direction = 1 else: feedback = "Fix Form" if per == 100: if elbow > 160 and shoulder > 40 and hip > 160: feedback = "Down" if direction == 1: count += 0.5 direction = 0 else: feedback = "Fix Form" # form = 0 print(count) #Draw Bar if form == 1: cv2.rectangle(img, (580, 50), (600, 380), (0, 255, 0), 3) cv2.rectangle(img, (580, int(bar)), (600, 380), (0, 255, 0), cv2.FILLED) cv2.putText(img, f'{int(per)}%', (565, 430), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 0), 2) #Pushup counter cv2.rectangle(img, (0, 380), (100, 480), (0, 255, 0), cv2.FILLED) cv2.putText(img, str(int(count)), (25, 455), cv2.FONT_HERSHEY_PLAIN, 5, (255, 0, 0), 5) #Feedback cv2.rectangle(img, (500, 0), (640, 40), (255, 255, 255), cv2.FILLED) cv2.putText(img, feedback, (500, 40 ), cv2.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), 2) cv2.imshow('Pushup counter', img) if cv2.waitKey(10) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
Code result:
One thing to note is on lines 17-21. Determine the resolution of the image captured from the camera, adjust the pixel value when drawing the rectangle of push up count, and so on. (lines 68-82).
ending:
OK, now we're done - a push up counting software that can ensure the standard of action. Not completely down? It doesn't count! Knee on the ground? It doesn't count!
Small series tips: proper fitness is safer!