ai-lover commited on
Commit
3852507
·
verified ·
1 Parent(s): ab1a3de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -0
app.py CHANGED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import streamlit as st
3
+ from ultralytics import YOLO
4
+ import cv2
5
+ import random
6
+ import time
7
+ from gtts import gTTS
8
+ import pygame
9
+ import threading
10
+ from datetime import datetime, timedelta
11
+
12
+ # Initialize pygame mixer
13
+ pygame.mixer.quit() # Ensure the mixer is fully stopped
14
+ pygame.mixer.init()
15
+
16
+ # Load YOLOv8 model
17
+ yolo = YOLO("yolov8n.pt")
18
+
19
+ # Streamlit app layout
20
+ st.set_page_config(page_title="Assistive Vision App", layout="centered")
21
+ st.title("Assistive Vision App for Visual Impairments")
22
+ st.write("This application provides real-time object recognition and optional audio alerts.")
23
+
24
+ # Directory to store temp audio files
25
+ audio_temp_dir = "audio_temp_files"
26
+ if not os.path.exists(audio_temp_dir):
27
+ os.makedirs(audio_temp_dir)
28
+
29
+ # Placeholder for video frames
30
+ stframe = st.empty()
31
+
32
+ # User controls
33
+ start_detection = st.button("Start Detection")
34
+ stop_detection = st.button("Stop Detection")
35
+ audio_activation = st.checkbox("Enable Audio Alerts", value=False)
36
+
37
+ # Categories for audio alerts (hazardous objects or living things)
38
+ alert_categories = {"person", "cat", "dog", "knife", "fire", "gun"}
39
+
40
+ # Dictionary to store the last alert timestamp for each object
41
+ last_alert_time = {}
42
+ alert_cooldown = timedelta(seconds=10) # 10-second cooldown for alerts
43
+
44
+
45
+ def play_audio_alert(label, position):
46
+ """Generate and play an audio alert."""
47
+ phrases = [
48
+ f"Be careful, there's a {label} on your {position}.",
49
+ f"Watch out! {label} detected on your {position}.",
50
+ f"Alert! A {label} is on your {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(): # Wait until audio finishes playing
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:
84
+ print(f"Error playing audio alert: {e}")
85
+
86
+
87
+ def process_frame(frame, audio_mode):
88
+ """Process a single video frame for object detection."""
89
+ results = yolo(frame)
90
+ result = results[0]
91
+
92
+ detected_objects = {} # Dictionary to store object labels and their positions
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,
113
+ f"{label}",
114
+ (x1, y1 - 10),
115
+ cv2.FONT_HERSHEY_SIMPLEX,
116
+ 0.5,
117
+ (0, 255, 0),
118
+ 2,
119
+ )
120
+
121
+ return detected_objects, frame
122
+
123
+
124
+ # Main logic
125
+ if start_detection:
126
+ st.success("Object detection started.")
127
+ try:
128
+ video_capture = cv2.VideoCapture(0)
129
+ if not video_capture.isOpened():
130
+ st.error("Could not access the webcam. Please check your camera settings.")
131
+ else:
132
+ while not stop_detection:
133
+ ret, frame = video_capture.read()
134
+ if not ret:
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 # Update the last alert time
156
+
157
+ time.sleep(0.1) # Small delay for smoother updates
158
+
159
+ except Exception as e:
160
+ st.error(f"An error occurred: {e}")
161
+ finally:
162
+ if 'video_capture' in locals() and video_capture.isOpened():
163
+ video_capture.release()
164
+ cv2.destroyAllWindows()
165
+ pygame.mixer.quit()
166
+
167
+ elif stop_detection:
168
+ st.warning("Object detection stopped.")