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
Example #3
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:
Example #7
0
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()