|
a |
|
b/start.py |
|
|
1 |
import os |
|
|
2 |
import threading |
|
|
3 |
#os.environ["KIVY_NO_CONSOLELOG"] = "1" |
|
|
4 |
from kivy.lang import Builder |
|
|
5 |
from kivymd.app import MDApp |
|
|
6 |
from kivymd.uix.boxlayout import MDBoxLayout |
|
|
7 |
from kivymd.uix.button import MDRaisedButton |
|
|
8 |
from kivymd.uix.label import MDLabel |
|
|
9 |
from kivy.uix.image import Image |
|
|
10 |
from kivy.graphics.texture import Texture |
|
|
11 |
from kivy.clock import Clock |
|
|
12 |
from kivy.uix.progressbar import ProgressBar |
|
|
13 |
from kivy.uix.popup import Popup |
|
|
14 |
from internal.frame_process import model_initialization, on_update |
|
|
15 |
from internal.tts.tttest import generate_audios, play_audio |
|
|
16 |
from kivy.core.text import Label |
|
|
17 |
from kivy.graphics import Line, Rectangle, Color |
|
|
18 |
from kivy.uix.widget import Widget |
|
|
19 |
from kivy.clock import Clock |
|
|
20 |
from vendor.kvconfigs import KV |
|
|
21 |
import cv2 |
|
|
22 |
from notifypy import Notify |
|
|
23 |
|
|
|
24 |
# Set the application icon |
|
|
25 |
|
|
|
26 |
notification = Notify() |
|
|
27 |
|
|
|
28 |
class AutopostureApp(MDApp): |
|
|
29 |
def build(self): |
|
|
30 |
generate_audios('bad', 'Sit correctly!') |
|
|
31 |
self.recently_alerted = False |
|
|
32 |
self.theme_cls.theme_style_switch_animation = True |
|
|
33 |
self.theme_cls.theme_style = "Light" |
|
|
34 |
self.theme_cls.primary_palette = "Blue" |
|
|
35 |
self.icon = 'assets/ergonomic.png' |
|
|
36 |
|
|
|
37 |
self.prediction_scores = [] # List to store prediction scores |
|
|
38 |
return Builder.load_string(KV) |
|
|
39 |
|
|
|
40 |
def on_start(self): |
|
|
41 |
self.video_running = False |
|
|
42 |
self.capture = cv2.VideoCapture(0, cv2.CAP_V4L2) |
|
|
43 |
model_initialization('0', 'src_models/yolov7-w6-pose.pt') |
|
|
44 |
|
|
|
45 |
def load_video_button(self): |
|
|
46 |
if not self.video_running: |
|
|
47 |
self.root.ids.start_autoposture.text = "PAUSE AUTOPOSTURE" |
|
|
48 |
self.video_running = True |
|
|
49 |
Clock.schedule_interval(self.load_video, 1.0 / 30.0) |
|
|
50 |
else: |
|
|
51 |
self.root.ids.start_autoposture.text = "RESTART AUTOPOSTURE" |
|
|
52 |
self.video_running = False |
|
|
53 |
Clock.unschedule(self.load_video) |
|
|
54 |
|
|
|
55 |
def switch_theme_style(self): |
|
|
56 |
self.theme_cls.primary_palette = ( |
|
|
57 |
"Blue" if self.theme_cls.primary_palette == "Blue" else "Blue" |
|
|
58 |
) |
|
|
59 |
self.theme_cls.theme_style = ( |
|
|
60 |
"Dark" if self.theme_cls.theme_style == "Light" else "Light" |
|
|
61 |
) |
|
|
62 |
|
|
|
63 |
def alert_user(self): |
|
|
64 |
notification.title = "Bad Posture" |
|
|
65 |
notification.message = "You are in a bad posture. Please correct your sitting." |
|
|
66 |
notification.icon = "assets/ergonomic.png" |
|
|
67 |
notification.send() |
|
|
68 |
play_audio('bad') |
|
|
69 |
|
|
|
70 |
def run_alert(self): |
|
|
71 |
if not self.recently_alerted: |
|
|
72 |
self.recently_alerted = False |
|
|
73 |
threading.Thread(target=self.alert_user).start() |
|
|
74 |
|
|
|
75 |
def trigger_alert(self, dt): |
|
|
76 |
self.alert_user() |
|
|
77 |
self.recently_alerted = False |
|
|
78 |
|
|
|
79 |
|
|
|
80 |
def load_video(self, *args): |
|
|
81 |
if not self.video_running: |
|
|
82 |
return |
|
|
83 |
|
|
|
84 |
ret, frame = self.capture.read() |
|
|
85 |
frame, posture, prediction_score, should_update = on_update(frame, self.recently_alerted, 0.7) |
|
|
86 |
if should_update: |
|
|
87 |
self.run_alert() |
|
|
88 |
self.recently_alerted = True |
|
|
89 |
else: |
|
|
90 |
self.recently_alerted = False |
|
|
91 |
|
|
|
92 |
buffer = cv2.flip(frame, 0).tobytes() |
|
|
93 |
texture = Texture.create( |
|
|
94 |
size=(frame.shape[1], frame.shape[0]), |
|
|
95 |
colorfmt='bgr') |
|
|
96 |
texture.blit_buffer(buffer, colorfmt='bgr', bufferfmt='ubyte') |
|
|
97 |
|
|
|
98 |
video_image = self.root.ids.video_image |
|
|
99 |
video_image.texture = texture |
|
|
100 |
|
|
|
101 |
# Update posture label and set the text color |
|
|
102 |
posture_label = self.root.ids.posture_label |
|
|
103 |
posture_label.text = f"Posture: {posture}" |
|
|
104 |
posture_label.theme_text_color = "Error" if posture == "bad" else "Primary" |
|
|
105 |
|
|
|
106 |
prediction_label = self.root.ids.prediction_label |
|
|
107 |
prediction_label.text = f"Prediction Score: {int(prediction_score * 100)}%" |
|
|
108 |
|
|
|
109 |
self.prediction_scores.append(prediction_score) |
|
|
110 |
|
|
|
111 |
|
|
|
112 |
def show_average_popup(self): |
|
|
113 |
if self.prediction_scores: |
|
|
114 |
average = int(sum(self.prediction_scores) / len(self.prediction_scores) * 100) |
|
|
115 |
content = MDBoxLayout(orientation='vertical', padding=10) |
|
|
116 |
|
|
|
117 |
progress_label = MDLabel( |
|
|
118 |
text=f"Average Prediction Score: {average}%", |
|
|
119 |
theme_text_color="Secondary", |
|
|
120 |
font_style="H6", |
|
|
121 |
) |
|
|
122 |
content.add_widget(progress_label) |
|
|
123 |
|
|
|
124 |
popup = Popup( |
|
|
125 |
title="Average Score", |
|
|
126 |
content=content, |
|
|
127 |
size_hint=(None, None), |
|
|
128 |
size=("350dp", "200dp"), |
|
|
129 |
) |
|
|
130 |
|
|
|
131 |
# progress_label.theme_text_color = "Primary" |
|
|
132 |
if self.theme_cls.theme_style == "Light": |
|
|
133 |
# If the theme is "Light," set the background color and font color accordingly |
|
|
134 |
popup.background_color = self.theme_cls.bg_dark |
|
|
135 |
|
|
|
136 |
popup.open() |
|
|
137 |
|
|
|
138 |
# Clear the prediction scores list |
|
|
139 |
self.prediction_scores = [] |
|
|
140 |
else: |
|
|
141 |
# Handle the case where there are no prediction scores. |
|
|
142 |
content = MDLabel(text="No prediction scores yet") |
|
|
143 |
popup = Popup( |
|
|
144 |
title="Average Score", |
|
|
145 |
content=content, |
|
|
146 |
size_hint=(None, None), |
|
|
147 |
size=("350dp", "200dp"), # Adjust the size here to make it wider |
|
|
148 |
) |
|
|
149 |
|
|
|
150 |
if self.theme_cls.theme_style == "Light": |
|
|
151 |
# If the theme is "Light," set the background color and font color accordingly |
|
|
152 |
popup.background_color = self.theme_cls.bg_dark |
|
|
153 |
content.theme_text_color = "Primary" |
|
|
154 |
|
|
|
155 |
popup.open() |
|
|
156 |
|
|
|
157 |
if __name__ == '__main__': |
|
|
158 |
AutopostureApp().run() |