Contador de SENTADILLAS / SQUATS ?| Python – MediaPipe – OpenCV
¡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/
Hola! Como estas?
Estaba probando tu código pero las dimensiones del video son muy grandes y no se completo cuando ejecuto el programa, tu me podrías ayudar para cambiarle la escala y que se pueda ver completo, te lo agradezco.
Hola.
Solo deberías aplicarle al frame, justo antes de obtener el tamaño (frame.shape) algún método para reducir la imagen.
O usas imutils
import imutils
frame = imutils.resize(frame, width = 600)
y obtendrías el frame a 600 de ancho con el alto proporcional a esa cantidad.
O directamente usas OpenCV
frame = cv2.resize(frame, (800, 600))
obteniendo un frame de 600×800 (ancho x alto)
a partir de ese momento, el script trabajará con el tamaño asignado.