FRANCKYPRO's picture
Update app.py
85fd17b verified
import streamlit as st
import cv2
import mediapipe as mp
import numpy as np
from gtts import gTTS
from playsound import playsound
import os
import time
import threading
# Configuration
st.set_page_config(layout="wide")
st.title("🧠 Assistant de Rééducation - Analyse de Posture")
# Sélection de l'exercice
selected_exercise = st.selectbox("Choisissez un exercice :", ["Bras levés", "Squat", "Inclinaison latérale"])
# Initialisation
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
stframe = st.empty()
feedback_placeholder = st.empty()
previous_feedback = ""
last_speech_time = 0
MIN_DELAY = 3 # secondes
def speak_async(text):
def _speak():
tts = gTTS(text=text, lang='fr')
filename = f"feedback_{int(time.time())}.mp3"
tts.save(filename)
playsound(filename)
os.remove(filename)
threading.Thread(target=_speak).start()
with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose:
while cap.isOpened():
ret, frame = cap.read()
if not ret:
st.error("❌ Impossible d'accéder à la webcam.")
break
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image.flags.writeable = False
results = pose.process(image)
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if results.pose_landmarks:
mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
lm = results.pose_landmarks.landmark
feedback = ""
# Règles selon exercice choisi
if selected_exercise == "Bras levés":
wrist_l = lm[mp_pose.PoseLandmark.LEFT_WRIST.value]
wrist_r = lm[mp_pose.PoseLandmark.RIGHT_WRIST.value]
nose = lm[mp_pose.PoseLandmark.NOSE.value]
bras_gauche_ok = wrist_l.y < nose.y
bras_droit_ok = wrist_r.y < nose.y
if bras_gauche_ok and bras_droit_ok:
feedback = "✅ Les bras sont bien levés"
else:
if not bras_gauche_ok:
feedback += "💡 Bras gauche trop bas !\n"
if not bras_droit_ok:
feedback += "💡 Bras droit trop bas !"
elif selected_exercise == "Squat":
knee_l = lm[mp_pose.PoseLandmark.LEFT_KNEE.value]
ankle_l = lm[mp_pose.PoseLandmark.LEFT_ANKLE.value]
hip_l = lm[mp_pose.PoseLandmark.LEFT_HIP.value]
if hip_l.y > knee_l.y and knee_l.y < ankle_l.y + 0.05:
feedback = "✅ Bonne position de squat"
else:
feedback = "💡 Descendez vos hanches en gardant le dos droit"
elif selected_exercise == "Inclinaison latérale":
shoulder_l = lm[mp_pose.PoseLandmark.LEFT_SHOULDER.value]
shoulder_r = lm[mp_pose.PoseLandmark.RIGHT_SHOULDER.value]
delta_x = abs(shoulder_l.x - shoulder_r.x)
if delta_x > 0.2:
feedback = "✅ Bonne inclinaison latérale"
else:
feedback = "💡 Inclinez davantage le buste sur le côté"
# Affichage texte
feedback_placeholder.markdown(f"### 🎤 Feedback :\n{feedback}")
# Retour vocal asynchrone si message changé
current_time = time.time()
if feedback != previous_feedback and current_time - last_speech_time > MIN_DELAY:
speak_async(feedback.replace("\n", " "))
previous_feedback = feedback
last_speech_time = current_time
stframe.image(image, channels="BGR", use_column_width=True)
cap.release()