CoolFace
Apppublic

linsoning/Posture_Evaluation_App

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
app.py111 linesDownload Raw Back to root
1import os2os.environ["MPLCONFIGDIR"] = "/tmp/matplotlib-cache"3import cv24import mediapipe as mp5import gradio as gr6import math7import time8 9 10def find_angle(x1, y1, x2, y2):11    return abs(int(math.degrees(math.atan2(x2 - x1, y1 - y2))))12 13def detect_posture(frame, last_alert_time=0):14    # Initialize MediaPipe Pose with the same stuff15    # Oh and I "copied" this code from the Documentation16    # I moved this dumb stuff here, because it can't save to http://usr/local/17    mp_pose = mp.solutions.pose18    pose = mp_pose.Pose(model_complexity=0, min_detection_confidence=0.2, min_tracking_confidence=0.2, smooth_landmarks=False)19    #Also now I can't put the shortened shortcut outside the function anymore since I had to move MediaPipe in here :(20    LEFT_SHOULDER = mp_pose.PoseLandmark.LEFT_SHOULDER21    LEFT_EAR = mp_pose.PoseLandmark.LEFT_EAR22    LEFT_HIP = mp_pose.PoseLandmark.LEFT_HIP23    24    # This is the start time for my new FPS counter25    start_time = time.perf_counter()26 27    THEALERTPATH = None  # What's happening here, is that THEALERTPATH is NOT playing28 29    #Basically here, doing 3 conversions is slow, so by predefining the "results" using only 1 convertion...30    #It would be faster since a need to convert back to BGR is unnecessary31    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)32    results = pose.process(rgb_frame)33    #And since we aren't using image anymore...34    #This is what the computer will draw on35    output_frame = frame.copy()36 37    if results.pose_landmarks:38        # Get frame dimensions39        height, width = frame.shape[:2]40        allthelandmarks = results.pose_landmarks.landmark41 42        #This is why I defined it earlier43        shoulder = allthelandmarks[LEFT_SHOULDER]44        ear = allthelandmarks[LEFT_EAR]45        hip = allthelandmarks[LEFT_HIP]46 47        #Pixel coordinates48        shoulder_x, shoulder_y, ear_x, ear_y, hip_x, hip_y = int(shoulder.x * width), int(shoulder.y * height), int(ear.x * width), int(ear.y * height), int(hip.x * width), int(hip.y * height)49 50        # Calculate angles51        neck_angle = find_angle(shoulder_x, shoulder_y, ear_x, ear_y)52        torso_angle = find_angle(hip_x, hip_y, shoulder_x, shoulder_y)53 54        # Posture alert with cooldown55        current_time = time.time()56 57        if neck_angle > 40 or torso_angle > 10:58            if current_time - last_alert_time > 2:59                last_alert_time = current_time60                cv2.putText(output_frame, "BAD POSTURE!", (20, 40),61                            cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)62                THEALERTPATH = "Noise.mp3" #This plays the sound63 64        #same stuff as always, just with a different name65        cv2.line(output_frame, (shoulder_x, shoulder_y), (ear_x, ear_y), (0, 255, 0), 2)66        cv2.line(output_frame, (hip_x, hip_y), (shoulder_x, shoulder_y), (255, 0, 0), 2)67        cv2.line(output_frame, (shoulder_x, shoulder_y), (shoulder_x, shoulder_y - 100), (200, 200, 200), 1)68        cv2.line(output_frame, (hip_x, hip_y), (hip_x, hip_y - 100), (200, 200, 200), 1)69 70    # The fps counter code (I'll explain this in logbook)71    process_time = time.perf_counter() - start_time72    fps = 1 / process_time if process_time > 0 else 073    cv2.putText(output_frame, f"FPS: {fps:.1f}", (width-120, 40),74                cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)75 76    return cv2.cvtColor(output_frame, cv2.COLOR_BGR2RGB), last_alert_time, THEALERTPATH #This will now return the MP3 File on top of everything else77 78# It sends the incoming frame + the state (last_alert_time) to detect_posture(), and returns the updated frame + updated state.79# This acts like a bridge between Gradio's webcam stream and their posture detection function80def process_frame(input_frame, state=0):81    output_frame, new_state, alert_audio = detect_posture(input_frame, state)82    return output_frame, new_state, alert_audio83 84 85with gr.Blocks(title="V3 OF POSTURE DETECTION") as app: #This will create the Gradio Blocks interface86    gr.Markdown("If you don't straighten that back of yours, this program will shout at you!")87    with gr.Row(): # This will make the next 2 things side by side.88        #This is the webcam, obviously89        webcam = gr.Webcam(label="You")90        #The output with all the landmarks, and non-customization91        output = gr.Image(label="You but with landmarks", interactive=False)92 93        #Extra option for SOUND94        #This creates an audio player in Gradio that plays NOISE.mp395        alert_audio = gr.Audio(label="Audio Alert", autoplay=True)96 97    #This stores the last alert time98    state = gr.State(0)99 100    webcam.stream(101        # Sends webcam frames and last alert time (state) to process_frame102        # The updated image, state, and an MP3 path (if bad posture) are returned103        # Shows the image, state, and plays the sound automatically104        process_frame,105        inputs=[webcam, state],106        outputs=[output, state, alert_audio],  # Plays audio only if a file is returned107        show_progress="hidden",108    )109 110if __name__ == "__main__":111    app.launch()