Contador de SENTADILLAS / SQUATS ?| Python – MediaPipe – OpenCV

Por Administrador

¡Súper contador de Sentadillas /Squats!. En este tutorial vamos a construir un contador de sentadillas con ayuda de MediaPipe Pose, OpenCV en Python. Ya sea si te gusta la programación, y/o los ejercicios, te animo a que…. ¡Te animes a probarlo ?!.

¡Vamos con la programación!

Para una explicación más detallada del programa que veremos a continuación, por favor dirígete al videotutorial de mi canal.

import cv2
import mediapipe as mp
import numpy as np
from math import acos, degrees

mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose

cap = cv2.VideoCapture("video_001.mp4")
up = False
down = False
count = 0
with mp_pose.Pose(
     static_image_mode=False) as pose:

     while True:
          ret, frame = cap.read()
          if ret == False:
               break
          #frame = cv2.flip(frame, 1)
          height, width, _ = frame.shape
          frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
          results = pose.process(frame_rgb)

          if results.pose_landmarks is not None:
               x1 = int(results.pose_landmarks.landmark[24].x * width)
               y1 = int(results.pose_landmarks.landmark[24].y * height)

               x2 = int(results.pose_landmarks.landmark[26].x * width)
               y2 = int(results.pose_landmarks.landmark[26].y * height)

               x3 = int(results.pose_landmarks.landmark[28].x * width)
               y3 = int(results.pose_landmarks.landmark[28].y * height)

               p1 = np.array([x1, y1])
               p2 = np.array([x2, y2])
               p3 = np.array([x3, y3])

               l1 = np.linalg.norm(p2 - p3)
               l2 = np.linalg.norm(p1 - p3)
               l3 = np.linalg.norm(p1 - p2)

               # Calcular el ángulo
               angle = degrees(acos((l1**2 + l3**2 - l2**2) / (2 * l1 * l3)))
               if angle >= 160:
                    up = True
               if up == True and down == False and angle <= 70:
                    down = True
               if up == True and down == True and angle >= 160:
                    count += 1
                    up = False
                    down = False

               #print("count: ", count)
               # Visualización
               aux_image = np.zeros(frame.shape, np.uint8)
               cv2.line(aux_image, (x1, y1), (x2, y2), (255, 255, 0), 20)
               cv2.line(aux_image, (x2, y2), (x3, y3), (255, 255, 0), 20)
               cv2.line(aux_image, (x1, y1), (x3, y3), (255, 255, 0), 5)
               contours = np.array([[x1, y1], [x2, y2], [x3, y3]])
               cv2.fillPoly(aux_image, pts=[contours], color=(128, 0, 250))

               output = cv2.addWeighted(frame, 1, aux_image, 0.8, 0)

               cv2.circle(output, (x1, y1), 6, (0, 255, 255), 4)
               cv2.circle(output, (x2, y2), 6, (128, 0, 250), 4)
               cv2.circle(output, (x3, y3), 6, (255, 191, 0), 4)
               cv2.rectangle(output, (0, 0), (60, 60), (255, 255, 0), -1)
               cv2.putText(output, str(int(angle)), (x2 + 30, y2), 1, 1.5, (128, 0, 250), 2)
               cv2.putText(output, str(count), (10, 50), 1, 3.5, (128, 0, 250), 2)
               cv2.imshow("output", output)
          cv2.imshow("Frame", frame)
          if cv2.waitKey(1) & 0xFF == 27:
               break

cap.release()
cv2.destroyAllWindows()

Videos usados como entrada:

? https://www.pexels.com/es-es/video/mujer-arboles-hierba-rubia-5025766/
? https://www.pexels.com/es-es/video/mujer-arboles-rubia-fitnes-5025965/