|
|
|
|
|
from ultralytics.solutions.solutions import BaseSolution
|
|
from ultralytics.utils.plotting import Annotator
|
|
|
|
|
|
class AIGym(BaseSolution):
|
|
"""A class to manage the gym steps of people in a real-time video stream based on their poses."""
|
|
|
|
def __init__(self, **kwargs):
|
|
"""Initialization function for AiGYM class, a child class of BaseSolution class, can be used for workouts
|
|
monitoring.
|
|
"""
|
|
|
|
if "model" in kwargs and "-pose" not in kwargs["model"]:
|
|
kwargs["model"] = "yolo11n-pose.pt"
|
|
elif "model" not in kwargs:
|
|
kwargs["model"] = "yolo11n-pose.pt"
|
|
|
|
super().__init__(**kwargs)
|
|
self.count = []
|
|
self.angle = []
|
|
self.stage = []
|
|
|
|
|
|
self.initial_stage = None
|
|
self.up_angle = float(self.CFG["up_angle"])
|
|
self.down_angle = float(self.CFG["down_angle"])
|
|
self.kpts = self.CFG["kpts"]
|
|
self.lw = self.CFG["line_width"]
|
|
|
|
def monitor(self, im0):
|
|
"""
|
|
Monitor the workouts using Ultralytics YOLOv8 Pose Model: https://docs.ultralytics.com/tasks/pose/.
|
|
|
|
Args:
|
|
im0 (ndarray): The input image that will be used for processing
|
|
Returns
|
|
im0 (ndarray): The processed image for more usage
|
|
"""
|
|
|
|
tracks = self.model.track(source=im0, persist=True, classes=self.CFG["classes"])[0]
|
|
|
|
if tracks.boxes.id is not None:
|
|
|
|
if len(tracks) > len(self.count):
|
|
new_human = len(tracks) - len(self.count)
|
|
self.angle += [0] * new_human
|
|
self.count += [0] * new_human
|
|
self.stage += ["-"] * new_human
|
|
|
|
|
|
self.annotator = Annotator(im0, line_width=self.lw)
|
|
|
|
|
|
for ind, k in enumerate(reversed(tracks.keypoints.data)):
|
|
|
|
kpts = [k[int(self.kpts[i])].cpu() for i in range(3)]
|
|
self.angle[ind] = self.annotator.estimate_pose_angle(*kpts)
|
|
im0 = self.annotator.draw_specific_points(k, self.kpts, radius=self.lw * 3)
|
|
|
|
|
|
if self.angle[ind] < self.down_angle:
|
|
if self.stage[ind] == "up":
|
|
self.count[ind] += 1
|
|
self.stage[ind] = "down"
|
|
elif self.angle[ind] > self.up_angle:
|
|
self.stage[ind] = "up"
|
|
|
|
|
|
self.annotator.plot_angle_and_count_and_stage(
|
|
angle_text=self.angle[ind],
|
|
count_text=self.count[ind],
|
|
stage_text=self.stage[ind],
|
|
center_kpt=k[int(self.kpts[1])],
|
|
)
|
|
|
|
self.display_output(im0)
|
|
return im0
|
|
|