Upload programme5_Jalon4.py

#21
Files changed (1) hide show
  1. programme5_Jalon4.py +79 -0
programme5_Jalon4.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2 # utile pour la gestion de la vidéo
2
+ import mediapipe as mp # utile pour gérer la détection de visages
3
+ import json # utile pour l'exportation en json
4
+
5
+ face_mesh = mp.solutions.face_mesh.FaceMesh() # on initialise le modèle de détection du visage
6
+ cap = cv2.VideoCapture("video.mp4") # on ouvre la vidéo en mp4 via cv2
7
+ fps = cap.get(cv2.CAP_PROP_FPS) # récupère le nombre de fps
8
+ frame_index = 0 # compteur de frames, sert à calculer les timestamps
9
+ data = [] # contiendra tous les landmarks de toutes les frames, vide pour l'instant
10
+
11
+ while True:
12
+ ret, video = cap.read() # on lit la frame suivante de la vidéo
13
+ if ret is not True:
14
+ break # plus rien à lire, on sort
15
+
16
+ height, width, _ = video.shape # on récupère les dimensions de la frame
17
+ result = face_mesh.process(video) # cherche un visage sur la vidéo
18
+
19
+ for facial_landmarks in result.multi_face_landmarks: # on parcourt le visage
20
+ xb = [] # utile pour les coordonnées de la boîte englobante
21
+ yb = [] # utile pour les coordonnées de la boîte englobante
22
+
23
+ for pt in facial_landmarks.landmark: # on parcourt chaque point facial
24
+ x = int(pt.x * width) # calcul des coordonnées des pixels
25
+ y = int(pt.y * height) # calcul des coordonnées des pixels
26
+ xb.append(x) # on stocke les coordonnées pour calculer la boîte englobante
27
+ yb.append(y) # on stocke les coordonnées pour calculer la boîte englobante
28
+ cv2.circle(video, (x, y), 2, (100, 100, 0), -1) # on dessine un petit cercle sur chaque point du visage
29
+
30
+ cv2.rectangle(video, (min(xb), min(yb)), (max(xb), max(yb)), (0, 255, 0), 2) # boîte englobante verte autour du visage
31
+
32
+ if frame_index % round(fps / 4) == 0:
33
+ lm = facial_landmarks.landmark # raccourci pour accéder aux points
34
+ face_x = lm[1].x * width # position X du nez dans l'image
35
+ face_y = lm[1].y * height # position Y du nez dans l'image
36
+
37
+ centre_x = width / 2 # centre horizontal de l'image
38
+ centre_y = height / 2 # centre vertical de l'image
39
+
40
+ head_yaw = (face_x - centre_x) / centre_x * 90 # rotation gauche/droite
41
+ head_pitch = (face_y - centre_y) / centre_y * 90 # rotation haut/bas
42
+
43
+ mouth_open = abs(lm[14].y - lm[13].y) * height # ouverture de la bouche en pixels
44
+
45
+ mouth_width = abs(lm[61].x - lm[291].x) * width # largeur de la bouche en pixels (détection du sourire)
46
+
47
+ eye_open = abs(lm[159].y - lm[145].y) * height # ouverture de l'oeil gauche en pixels
48
+
49
+ face_width = max(xb) - min(xb) # largeur du visage en pixels
50
+ smile = mouth_width > 0.40 * face_width # sourire si bouche > 40% de la largeur du visage
51
+
52
+ eyes_wide = eye_open > 8 # yeux grands ouverts si ouverture > 8 pixels (surprise)
53
+
54
+ if mouth_open > 10: # bouche ouverte ==> antennes levées symétriquement
55
+ antenna_angle = 45
56
+ elif smile: # sourire ==> antennes en V
57
+ antenna_angle = 30
58
+ else:
59
+ antenna_angle = 0 # neutre ==> antennes baissées
60
+
61
+ data.append({
62
+ "timestamp": round(frame_index / fps, 1),
63
+ "mouth_open": round(mouth_open, 2),
64
+ "antennas": antenna_angle,
65
+ "smile": smile,
66
+ "eyes_wide": eyes_wide, # yeux grands ouverts ou non
67
+ "head_pitch": round(head_pitch, 2),
68
+ "head_yaw": round(head_yaw, 2)
69
+ })
70
+
71
+ cv2.imshow("Video", video) # on affiche la vidéo
72
+ cv2.waitKey(1) # on laisse 1ms à OpenCV pour afficher la frame
73
+ frame_index = frame_index + 1 # on passe à la frame suivante
74
+
75
+ with open("results.json", "w") as file: # on ouvre le fichier en écriture
76
+ json.dump(data, file, indent=2) # on écrit les données
77
+
78
+ cap.release() # on ferme la vidéo
79
+ cv2.destroyAllWindows() # ferme toutes les fenêtres