def evaluate_side_bicepcurl(self, frames: List[pose.PoseData]): side = detect_perspective(frames) # Angles to calculate upper_arm_lower_arm_angles = [] upper_arm_torso_angles = [] for frame in frames: if (side == pose.Side.right): upper_arm = pose.Part(frame.relbow, frame.rshoulder) lower_arm = pose.Part(frame.relbow, frame.rwrist) torso = pose.Part(frame.rhip, frame.neck) else: upper_arm = pose.Part(frame.lelbow, frame.lshoulder) lower_arm = pose.Part(frame.lelbow, frame.lwrist) torso = pose.Part(frame.lhip, frame.neck) upper_arm_lower_arm_angle = upper_arm.calculate_angle(lower_arm) upper_arm_torso_angle = upper_arm.calculate_angle(torso) upper_arm_lower_arm_angles.append(upper_arm_lower_arm_angle) upper_arm_torso_angles.append(upper_arm_torso_angle) # use thresholds learned from analysis upper_arm_torso_range = np.max(upper_arm_torso_angles) - np.min( upper_arm_torso_angles) upper_arm_lower_arm_min = np.min(upper_arm_lower_arm_angles) # print('Upper arm and torso angle range: {}'.format(upperarm_torso_range)) # print('Upper arm and forearm minimum angle: {}'.format(upperarm_forearm_min)) correct = True feedback = '' if upper_arm_torso_range > 35.0: correct = False feedback += 'Significant rotation in upper arm while curling\n' if upper_arm_lower_arm_min > 45.0: correct = False feedback += 'Curling not performed all the way to the top\n' if correct: feedback += 'Correctly performed\n' # print('-'*30) # print('Exercise correct: '+str(correct)) # print(feedback) return (correct, feedback)
def evaluate_frame(self, frame: pose.PoseData): self.frames.append(frame) # @TODO we need to calculate this only once side = detect_perspective([frame]) upper_arm_lower_arm_angle, upper_arm_torso_angle = self.evaluate_angle_per_frame( frame, side) ################# Reps counter and feedback logic ########################### # rep is still proceeding in downward direction if (not self.down_exited and upper_arm_lower_arm_angle < self.start_angle - self.threshold): self.frames_elapsed = 0 self.down_exited = True if (self.down_exited): self.frames_elapsed += 1 # for feedback purpose if (self.start_angle - self.threshold <= upper_arm_lower_arm_angle <= self.start_angle + self.threshold): # @TODO need to check it later, hardcoded value if (self.down_exited and self.frames_elapsed > 20): # 1 rep completed # print(upper_arm_lower_arm_angle) self.correct, feedback = self.evaluate_side_bicepcurl( self.frames) if (self.correct): self.reps += 1 else: self.reps_incorrect += 1 self.feedbacks.append(feedback) # Ahoy new reps begin self.frames = [] print(feedback) print(self.reps) print(self.reps_incorrect) self.initial_frame = self.frame_index self.down_exited = False self.frames_elapsed = 0
def on_file_change(*args): global video, side, active_file, cap, initial_frame, start_angle, end_angle, threshold, down, down_exited, frame_index global reps, reps_incorrect, frames_elapsed, feedback, frame_index active_file = variable.get() video = parser.parse_file(root_dir + '/' + active_file, False) cap.release() cap = cv2.VideoCapture(f'demo/video/{active_file.split(".")[0]}.mp4') if (cap.isOpened() == False): print("Error") initial_frame = 0 # start of each reps start_angle = 160 # intial position defined end_angle = 40 # final position of arm threshold = 10 down = False # to check whether the arm is in down region down_exited = False # to check whether arm exited down region reps = 0 # to count the number of reps in exercise reps_incorrect = 0 # to counf the incorrect reps frames_elapsed = 0 feedback = "" frame_index = 0 side = parser.detect_perspective(video) root.title(active_file) print(active_file)
def evaluate_side_shoulderpress(frames: List[pose.PoseData]): side = detect_perspective(frames) upperarm_forearm_angles = [] upperarm_torso_angles = [] back_vectors = [] elbow_neck_x = [] for frame in frames: # IGnore all the 0 confidence frames if (side == pose.Side.right): if (frame.relbow.confidence == 0 or frame.rshoulder.confidence == 0 or frame.rwrist.confidence == 0 or frame.rhip.confidence == 0 or frame.neck.confidence == 0): continue else: if (frame.lelbow.confidence == 0 or frame.lshoulder.confidence == 0 or frame.lwrist.confidence == 0 or frame.lhip.confidence == 0 or frame.neck.confidence == 0): continue if (side == pose.Side.right): upperarm = pose.Part(frame.relbow, frame.rshoulder) forearm = pose.Part(frame.relbow, frame.rwrist) torso = pose.Part(frame.rhip, frame.neck) # Or back # elbow_neck = pose.Part(frame.neck, frame.relbow) back_vectors.append( np.array( [frame.neck.x - frame.rhip.x, frame.neck.y - frame.rhip.y])) elbow_neck_x.append(frame.relbow.x - frame.neck.x) else: upperarm = pose.Part(frame.lelbow, frame.lshoulder) forearm = pose.Part(frame.lelbow, frame.lwrist) torso = pose.Part(frame.lhip, frame.neck) # elbow_neck = pose.Part(frame.lelbow, frame.neck) back_vectors.append( np.array( [frame.neck.x - frame.lhip.x, frame.neck.y - frame.lhip.y])) elbow_neck_x.append(frame.neck.x - frame.lelbow.x) angle1 = upperarm.calculate_angle(forearm) angle2 = upperarm.calculate_angle(torso) upperarm_forearm_angles.append(angle1) upperarm_torso_angles.append(angle2) ##### Angle cleanup ############ upperarm_forearm_angles = np.array(upperarm_forearm_angles) upperarm_forearm_angles = upperarm_forearm_angles[np.logical_not( np.isnan(upperarm_forearm_angles))] upperarm_torso_angles = np.array(upperarm_torso_angles) upperarm_torso_angles = upperarm_torso_angles[np.logical_not( np.isnan(upperarm_torso_angles))] back_vectors = np.array(back_vectors) ### Calculation of required parameters ################# max_upperarm_forearm_angle = np.max(upperarm_forearm_angles) back_vector_range = np.max(back_vectors, axis=0) - \ np.min(back_vectors, axis=0) elbow_x = np.min(elbow_neck_x) # Only x axis print(elbow_x) correct = True feedback = "" if (max_upperarm_forearm_angle < 175): correct = False feedback += "Not lifted upto the top. \n" if (back_vector_range[0] > 0.16): correct = False feedback += "Back shows significant movement. \n" if (elbow_x < -0.12): correct = False feedback += "Shoulders are not steady/parallel. \n" return (correct, feedback)
down = False # to check whether the arm is in down region down_exited = False # to check whether arm exited down region reps = 0 # to count the number of reps in exercise reps_incorrect = 0 # to counf the incorrect reps frames_elapsed = 0 feedback = "" frame_index = 0 cv_default_font = cv2.FONT_HERSHEY_PLAIN font_size = 1 video = [] while (True): keypoint, img = wrapper.calculate_frame() frame = parse_single_frame(keypoint[0]) video.append(frame) side = detect_perspective([frame]) output = evaluate_angle_per_frame(frame, side) angle1 = output["a1"] angle2 = output["a2"] ################# Reps counter and feedback logic ########################### if (not down_exited and angle1 < start_angle - threshold): frames_elapsed = 0 down_exited = True if (down_exited): frames_elapsed += 1 if (start_angle - threshold <= angle1 <= start_angle + threshold): if (down_exited and frames_elapsed > 20): # 1 rep completed print(angle1) # cv.imwrite("frame%d.jpg" % i, image)
break if k == ord('c'): is_video_good = not is_video_good index = 0 if k == ord('n'): video_index += 1 index = 0 if k == ord('p'): video_index -= 1 index = 0 # Main logic if is_video_good: video_index = abs(video_index % len(good_videos)) video = good_videos[video_index] side = detect_perspective(video) current_type = "Good" else: video_index = abs(video_index % len(bad_videos)) video = bad_videos[video_index] side = detect_perspective(video) current_type = "Bad" frame = video[index] # Angle if (side == pose.Side.right): upperarm = pose.Part(frame.relbow, frame.rshoulder) forearm = pose.Part(frame.relbow, frame.rwrist) torso = pose.Part(frame.rhip, frame.neck) else:
def visualize_vid(path): # Create a black image #img = np.zeros((600, 1200, 3), np.uint8) # Draw a diagonal blue line with thickness of 5 px # cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5) # cv.circle(img, (447, 63), 63, (0, 0, 255), -1) video = parse_file(path, False) side = detect_perspective(video) index = 0 cap = cv.VideoCapture('videos/bicep_6.mp4') if(cap.isOpened()==False): print("Error") i = 0 # to count the frame initial_frame = i #start of each reps start_angle = 160 #intial position defined end_angle = 40 # final position of arm threshold = 10 down = False #to check whether the arm is in down region up = False #to check whether the arm is in upward region down_exited = False # to check whether arm exited down region reps = 0 # to count the number of reps in exercise reps_incorrect = 0 # to counf the incorrect reps start = False angles = [] frames_elapsed = 0 while(cap.isOpened()): ret, image = cap.read() frame = video[i] # User input k = cv.waitKey(1) & 0xFF if k == 27: break if ret==False: break if(k == 'p'): cv.waitKey(0) # Angle if (side == pose.Side.right): upperarm = pose.Part(frame.relbow, frame.rshoulder) forearm = pose.Part(frame.relbow, frame.rwrist) torso = pose.Part(frame.rhip, frame.neck) else: upperarm = pose.Part(frame.lelbow, frame.lshoulder) forearm = pose.Part(frame.lelbow, frame.lwrist) torso = pose.Part(frame.lhip, frame.neck) angle1 = upperarm.calculate_angle(forearm) angle2 = upperarm.calculate_angle(torso) angles.append(angle1) #Reps counter if (not down_exited and angle1 < start_angle-threshold): print(i) frames_elapsed = 0 down_exited = True if (down_exited): frames_elapsed += 1 if (start_angle-threshold <= angle1 <= start_angle+threshold): if (down_exited and frames_elapsed > 20): print(angle1) # cv.imwrite("frame%d.jpg" % i, image) correct, feedback = evaluate_side_bicepcurl(video[initial_frame:i]) if (correct): reps += 1 else: reps_incorrect += 1 # print(initial_frame,i) # print(feedback) initial_frame = i down_exited = False frames_elapsed = 0 # #Lower region # if (start_angle-threshold <= angle1 <= start_angle+threshold): # down = True # if (down and down_exited): # # reps += 1 # down = False # down_exited = False # start = True # correct, feedback = evaluate_side_bicepcurl(video[initial_frame:i]) # if (correct): # reps += 1 # else: # reps_incorrect += 1 # # print(initial_frame,i) # initial_frame = i # # print(reps,feedback) # # if (down and up): # # reps += 1 # # final_frame = i # # down = False # # up = False # # feedback = evaluate_bicepcurl (video[initial_frame:final_frame]) # # print(feedback) # # initial_frame = i # # #Upper region # # if (end_angle-threshold <= angle1 <= end_angle+threshold): # # up = True # #Downward region exit # if (down and angle1<start_angle-threshold): # down_exited = True # if (start and down and angle1<start_angle-threshold): # # print(i) # print(initial_frame, i) # start = False # index_min = np.argmin(angles[initial_frame:i])+initial_frame # print(initial_frame, index_min) # initial_frame = index_min # Drawing cv.putText(image, f"{path} {index}", (250, 20), cv.FONT_HERSHEY_PLAIN, 2, (255, 255, 255), 1) cv.putText(image, f"Angle upperarm forearm: {angle1}", (10, 50), cv.FONT_HERSHEY_PLAIN, 2, (255, 255, 255), 1) cv.putText(image, f"Angle upperarm torso: {angle2}", (10, 80), cv.FONT_HERSHEY_PLAIN, 2, (255, 255, 255), 1) cv.putText(image, f"Reps: {reps}", (10, 110), cv.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), 1) cv.putText(image, f"Reps incorrect: {reps_incorrect}", (10, 140), cv.FONT_HERSHEY_PLAIN, 2, (0, 0, 255), 1) for name, joint in frame: x = int(joint.x) y = int(joint.y) cv.circle(image, (x, y), 5, (0, 0, 255), -1) # cv.putText(image, name, (x, y-10), cv.FONT_HERSHEY_SIMPLEX, # 0.6, (36, 255, 12), 2) # Update # time.sleep(0.04) i = i+1 cv.imshow('Testing', image) cv.destroyAllWindows()