Have you really done push ups? Dare you test it with Python

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!

Finally, the complete code has been packaged and sorted out. If you need a little partner, you can click this line of font or edit a private letter!

Small series tips: proper fitness is safer!

Keywords: Python OpenCV Programmer Computer Vision Deep Learning

Added by BuckeyeTheDog on Wed, 23 Feb 2022 02:04:02 +0200