Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -17,9 +17,40 @@ pygame.mixer.init()
|
|
17 |
yolo = YOLO("yolov8n.pt")
|
18 |
|
19 |
# Streamlit app layout
|
20 |
-
st.set_page_config(page_title="Assistive Vision App", layout="
|
21 |
-
st.
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
# Directory to store temp audio files
|
25 |
audio_temp_dir = "audio_temp_files"
|
@@ -30,8 +61,11 @@ if not os.path.exists(audio_temp_dir):
|
|
30 |
stframe = st.empty()
|
31 |
|
32 |
# User controls
|
33 |
-
|
34 |
-
|
|
|
|
|
|
|
35 |
audio_activation = st.checkbox("Enable Audio Alerts", value=False)
|
36 |
|
37 |
# Categories for audio alerts (hazardous objects or living things)
|
@@ -51,33 +85,24 @@ def play_audio_alert(label, position):
|
|
51 |
]
|
52 |
caution_note = random.choice(phrases)
|
53 |
|
54 |
-
# Generate a unique audio filename using timestamp
|
55 |
temp_file_path = os.path.join(audio_temp_dir, f"temp_{datetime.now().strftime('%Y%m%d_%H%M%S_%f')}.mp3")
|
56 |
|
57 |
-
# Generate audio
|
58 |
tts = gTTS(caution_note)
|
59 |
tts.save(temp_file_path)
|
60 |
|
61 |
try:
|
62 |
-
# Load and play the audio using pygame
|
63 |
pygame.mixer.music.load(temp_file_path)
|
64 |
pygame.mixer.music.play()
|
65 |
|
66 |
-
# Create a new thread to handle file cleanup after playback
|
67 |
def cleanup_audio_file():
|
68 |
-
while pygame.mixer.music.get_busy():
|
69 |
time.sleep(0.1)
|
70 |
-
|
71 |
-
# After music finishes, stop the music and try to remove the file
|
72 |
-
pygame.mixer.music.stop() # Explicitly stop the music before cleanup
|
73 |
-
|
74 |
try:
|
75 |
-
# Try to remove the file after playback is finished
|
76 |
os.remove(temp_file_path)
|
77 |
except OSError as e:
|
78 |
print(f"Error deleting file {temp_file_path}: {e}")
|
79 |
|
80 |
-
# Start the cleanup thread
|
81 |
threading.Thread(target=cleanup_audio_file, daemon=True).start()
|
82 |
|
83 |
except Exception as e:
|
@@ -89,24 +114,20 @@ def process_frame(frame, audio_mode):
|
|
89 |
results = yolo(frame)
|
90 |
result = results[0]
|
91 |
|
92 |
-
detected_objects = {}
|
93 |
for box in result.boxes:
|
94 |
x1, y1, x2, y2 = map(int, box.xyxy[0])
|
95 |
label = result.names[int(box.cls[0])]
|
96 |
|
97 |
-
# Apply filtering logic for audio mode
|
98 |
if audio_mode and label not in alert_categories:
|
99 |
continue
|
100 |
|
101 |
-
# Determine position
|
102 |
frame_center_x = frame.shape[1] // 2
|
103 |
obj_center_x = (x1 + x2) // 2
|
104 |
position = "left" if obj_center_x < frame_center_x else "right"
|
105 |
|
106 |
-
# Update detected objects with label and position
|
107 |
detected_objects[label] = position
|
108 |
|
109 |
-
# Draw bounding boxes
|
110 |
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
|
111 |
cv2.putText(
|
112 |
frame,
|
@@ -135,26 +156,22 @@ if start_detection:
|
|
135 |
st.error("Failed to capture video. Please check your camera.")
|
136 |
break
|
137 |
|
138 |
-
# Process the frame based on whether audio alerts are enabled
|
139 |
detected_objects, processed_frame = process_frame(frame, audio_activation)
|
140 |
|
141 |
-
# Convert BGR to RGB for Streamlit
|
142 |
frame_rgb = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB)
|
143 |
stframe.image(frame_rgb, channels="RGB", use_container_width=True)
|
144 |
|
145 |
-
# Generate audio alerts for detected objects
|
146 |
if audio_activation:
|
147 |
current_time = datetime.now()
|
148 |
for label, position in detected_objects.items():
|
149 |
-
# Check if enough time has passed since the last alert for this object
|
150 |
if (
|
151 |
label not in last_alert_time
|
152 |
or current_time - last_alert_time[label] > alert_cooldown
|
153 |
):
|
154 |
play_audio_alert(label, position)
|
155 |
-
last_alert_time[label] = current_time
|
156 |
|
157 |
-
time.sleep(0.1)
|
158 |
|
159 |
except Exception as e:
|
160 |
st.error(f"An error occurred: {e}")
|
|
|
17 |
yolo = YOLO("yolov8n.pt")
|
18 |
|
19 |
# Streamlit app layout
|
20 |
+
st.set_page_config(page_title="Assistive Vision App", layout="wide")
|
21 |
+
st.markdown(
|
22 |
+
"""
|
23 |
+
<style>
|
24 |
+
body {
|
25 |
+
background-color: #f7f9fc;
|
26 |
+
font-family: "Arial", sans-serif;
|
27 |
+
}
|
28 |
+
.stButton>button {
|
29 |
+
background-color: #1a73e8;
|
30 |
+
color: white;
|
31 |
+
justify-content: center;
|
32 |
+
align-items: center;
|
33 |
+
border-radius: 10px;
|
34 |
+
padding: 10px;
|
35 |
+
margin: 5px;
|
36 |
+
}
|
37 |
+
.stCheckbox {
|
38 |
+
margin-top: 20px;
|
39 |
+
}
|
40 |
+
</style>
|
41 |
+
""",
|
42 |
+
unsafe_allow_html=True,
|
43 |
+
)
|
44 |
+
|
45 |
+
# Display welcome image
|
46 |
+
welcome_image_path = "bismillah.png" # Ensure this image exists in the script's directory
|
47 |
+
if os.path.exists(welcome_image_path):
|
48 |
+
st.image(welcome_image_path, use_container_width=True, caption="Bismillah hir Rehman Ar Raheem")
|
49 |
+
else:
|
50 |
+
st.warning("Welcome image not found! Please add 'bismillah.png' in the script directory.")
|
51 |
+
|
52 |
+
st.title("Object Detection & Assistive Vision App for Visually Impaired People")
|
53 |
+
st.write("This application provides real-time Object Recognition and Optional Audio Alerts.")
|
54 |
|
55 |
# Directory to store temp audio files
|
56 |
audio_temp_dir = "audio_temp_files"
|
|
|
61 |
stframe = st.empty()
|
62 |
|
63 |
# User controls
|
64 |
+
col1, col2 = st.columns(2)
|
65 |
+
with col1:
|
66 |
+
start_detection = st.button("Start Detection")
|
67 |
+
with col2:
|
68 |
+
stop_detection = st.button("Stop Detection")
|
69 |
audio_activation = st.checkbox("Enable Audio Alerts", value=False)
|
70 |
|
71 |
# Categories for audio alerts (hazardous objects or living things)
|
|
|
85 |
]
|
86 |
caution_note = random.choice(phrases)
|
87 |
|
|
|
88 |
temp_file_path = os.path.join(audio_temp_dir, f"temp_{datetime.now().strftime('%Y%m%d_%H%M%S_%f')}.mp3")
|
89 |
|
|
|
90 |
tts = gTTS(caution_note)
|
91 |
tts.save(temp_file_path)
|
92 |
|
93 |
try:
|
|
|
94 |
pygame.mixer.music.load(temp_file_path)
|
95 |
pygame.mixer.music.play()
|
96 |
|
|
|
97 |
def cleanup_audio_file():
|
98 |
+
while pygame.mixer.music.get_busy():
|
99 |
time.sleep(0.1)
|
100 |
+
pygame.mixer.music.stop()
|
|
|
|
|
|
|
101 |
try:
|
|
|
102 |
os.remove(temp_file_path)
|
103 |
except OSError as e:
|
104 |
print(f"Error deleting file {temp_file_path}: {e}")
|
105 |
|
|
|
106 |
threading.Thread(target=cleanup_audio_file, daemon=True).start()
|
107 |
|
108 |
except Exception as e:
|
|
|
114 |
results = yolo(frame)
|
115 |
result = results[0]
|
116 |
|
117 |
+
detected_objects = {}
|
118 |
for box in result.boxes:
|
119 |
x1, y1, x2, y2 = map(int, box.xyxy[0])
|
120 |
label = result.names[int(box.cls[0])]
|
121 |
|
|
|
122 |
if audio_mode and label not in alert_categories:
|
123 |
continue
|
124 |
|
|
|
125 |
frame_center_x = frame.shape[1] // 2
|
126 |
obj_center_x = (x1 + x2) // 2
|
127 |
position = "left" if obj_center_x < frame_center_x else "right"
|
128 |
|
|
|
129 |
detected_objects[label] = position
|
130 |
|
|
|
131 |
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
|
132 |
cv2.putText(
|
133 |
frame,
|
|
|
156 |
st.error("Failed to capture video. Please check your camera.")
|
157 |
break
|
158 |
|
|
|
159 |
detected_objects, processed_frame = process_frame(frame, audio_activation)
|
160 |
|
|
|
161 |
frame_rgb = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB)
|
162 |
stframe.image(frame_rgb, channels="RGB", use_container_width=True)
|
163 |
|
|
|
164 |
if audio_activation:
|
165 |
current_time = datetime.now()
|
166 |
for label, position in detected_objects.items():
|
|
|
167 |
if (
|
168 |
label not in last_alert_time
|
169 |
or current_time - last_alert_time[label] > alert_cooldown
|
170 |
):
|
171 |
play_audio_alert(label, position)
|
172 |
+
last_alert_time[label] = current_time
|
173 |
|
174 |
+
time.sleep(0.1)
|
175 |
|
176 |
except Exception as e:
|
177 |
st.error(f"An error occurred: {e}")
|