tstone87 commited on
Commit
8a3e216
·
verified ·
1 Parent(s): 86b94b7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -232
app.py CHANGED
@@ -1,255 +1,145 @@
 
1
  import PIL
2
  import cv2
3
  import streamlit as st
4
  from ultralytics import YOLO
5
  import tempfile
6
  import time
7
- import requests
8
- import numpy as np
9
  import os
10
 
11
- # Page Config
12
- st.set_page_config(page_title="WildfireWatch", page_icon="🔥", layout="wide")
13
 
14
- # CSS for layout stability and dark tab text
15
- st.markdown(
16
- """
17
- <style>
18
- .stApp {
19
- background-color: #f5f5f5;
20
- color: #1a1a1a;
21
- }
22
- h1 {
23
- color: #1a1a1a;
24
- }
25
- .stTabs > div > button {
26
- background-color: #e0e0e0;
27
- color: #333333;
28
- font-weight: bold;
29
- }
30
- .stTabs > div > button:hover {
31
- background-color: #d0d0d0;
32
- color: #333333;
33
- }
34
- .stTabs > div > button[aria-selected="true"] {
35
- background-color: #ffffff;
36
- color: #333333;
37
- }
38
- .main .block-container {
39
- max-height: 100vh;
40
- overflow-y: auto;
41
- }
42
- .stImage > img {
43
- max-height: 50vh;
44
- object-fit: contain;
45
- }
46
- </style>
47
- """,
48
- unsafe_allow_html=True
49
  )
50
 
51
- # Load Model
52
- model_path = 'https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/best.pt'
53
- try:
54
- model = YOLO(model_path)
55
- except Exception as ex:
56
- st.error(f"Unable to load model. Check the specified path: {model_path}")
57
- st.error(ex)
58
- st.stop()
59
-
60
- # Initialize Session State
61
- if 'monitoring' not in st.session_state:
62
- st.session_state.monitoring = False
63
- if 'current_webcam_url' not in st.session_state:
64
- st.session_state.current_webcam_url = None
 
 
65
 
66
- # Header
67
  st.title("WildfireWatch: Detecting Wildfire using AI")
 
 
 
 
 
 
 
 
68
  st.markdown("""
69
- Wildfires are a major environmental issue, causing substantial losses to ecosystems, human livelihoods, and potentially leading to loss of life. Early detection of wildfires can prevent these losses. Our application uses state-of-the-art YOLOv8 model for real-time wildfire and smoke detection.
70
  """)
 
71
  st.markdown("---")
72
 
73
- # Tabs
74
- tabs = st.tabs(["Upload", "Webcam"])
75
 
76
- # Tab 1: Upload (Simplified to match original, with new features)
77
- with tabs[0]:
78
- col1, col2 = st.columns(2)
79
- with col1:
80
- st.markdown("**Add Your File**")
81
- st.write("Upload an image or video to scan for fire or smoke.")
82
- source_file = st.file_uploader("", type=["jpg", "jpeg", "png", "mp4"], label_visibility="collapsed")
83
- confidence = st.slider("Detection Threshold", 0.25, 1.0, 0.4, key="upload_conf")
84
- sampling_options = {
85
- "Every Frame": 0,
86
- "1 FPS": 1,
87
- "2 FPS": 2,
88
- "5 FPS": 5,
89
- "1 frame / 5s": 5,
90
- "1 frame / 10s": 10,
91
- "1 frame / 15s": 15
92
- }
93
- sampling_rate = st.selectbox("Analysis Rate", list(sampling_options.keys()), index=1, key="sampling_rate")
94
-
95
- with col2:
96
- frame_placeholder = st.empty()
97
- status_placeholder = st.empty()
98
- download_placeholder = st.empty()
99
-
100
- if source_file and st.button("Detect Wildfire", key="upload_detect"):
101
- try:
102
- st.write(f"File size: {source_file.size / 1024 / 1024:.2f} MB") # Diagnostic
103
- file_type = source_file.type.split('/')[0]
104
- if file_type == 'image':
105
- uploaded_image = PIL.Image.open(source_file)
106
- res = model.predict(uploaded_image, conf=confidence)
107
- detected_image = res[0].plot()[:, :, ::-1]
108
- frame_placeholder.image(detected_image, use_column_width=True)
109
- status_placeholder.write(f"Objects detected: {len(res[0].boxes)}")
110
- elif file_type == 'video':
111
- # Save input video
112
- tfile = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
113
- tfile.write(source_file.read())
114
- tfile.close()
115
-
116
- # Open video
117
- vidcap = cv2.VideoCapture(tfile.name)
118
- if not vidcap.isOpened():
119
- status_placeholder.error("Failed to open video file.")
120
- else:
121
- total_frames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
122
- fps = int(vidcap.get(cv2.CAP_PROP_FPS)) or 30
123
- frame_width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))
124
- frame_height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))
125
-
126
- # Frame sampling
127
- target_rate = sampling_options[sampling_rate]
128
- frame_skip = 1 if target_rate == 0 else max(1, int(fps / target_rate) if target_rate <= 5 else int(fps * target_rate))
129
-
130
- # Output video (only analyzed frames)
131
- output_tfile = tempfile.NamedTemporaryFile(delete=False, suffix='_detected.mp4')
132
- fourcc = cv2.VideoWriter_fourcc(*'mp4v')
133
- output_fps = 1 # Fixed for short compilation
134
- out = cv2.VideoWriter(output_tfile.name, fourcc, output_fps, (frame_width, frame_height))
135
-
136
- success, frame = vidcap.read()
137
- frame_count = 0
138
- processed_count = 0
139
-
140
- while success:
141
- if frame_count % frame_skip == 0:
142
- res = model.predict(frame, conf=confidence)
143
- detected_frame = res[0].plot()[:, :, ::-1]
144
- frame_placeholder.image(detected_frame, use_column_width=True)
145
- status_placeholder.write(f"Frame {frame_count}: Objects detected: {len(res[0].boxes)}")
146
- out.write(detected_frame[:, :, ::-1])
147
- processed_count += 1
148
- if total_frames > 0:
149
- progress = (frame_count + 1) / total_frames * 100
150
- st.write(f"Progress: {progress:.1f}% (Analyzed {processed_count} frames)")
151
- success, frame = vidcap.read()
152
- frame_count += 1
153
- time.sleep(0.05)
154
-
155
- vidcap.release()
156
- out.release()
157
-
158
- os.unlink(tfile.name)
159
- with open(output_tfile.name, 'rb') as f:
160
- download_placeholder.download_button(
161
- label="Download Analyzed Video",
162
- data=f,
163
- file_name="analyzed_video.mp4",
164
- mime="video/mp4"
165
- )
166
- status_placeholder.write(f"Video processing complete. Analyzed {processed_count} frames.")
167
- except Exception as e:
168
- status_placeholder.error(f"Error: {str(e)}")
169
 
170
- # Tab 2: Webcam (Unchanged)
171
- with tabs[1]:
172
- col1, col2 = st.columns([1, 1])
173
- with col1:
174
- st.markdown("**Webcam Feed**")
175
- st.write("Provide a webcam URL (image or video stream) to monitor for hazards.")
176
- webcam_url = st.text_input("Webcam URL", "http://<your_webcam_ip>/current.jpg", label_visibility="collapsed")
177
- confidence = st.slider("Detection Threshold", 0.25, 1.0, 0.4, key="webcam_conf")
178
- refresh_rate = st.slider("Refresh Rate (seconds)", 1, 60, 30, key="webcam_rate")
179
- start = st.button("Begin Monitoring", key="webcam_start")
180
- stop = st.button("Stop Monitoring", key="webcam_stop")
181
 
182
- if start:
183
- st.session_state.monitoring = True
184
- st.session_state.current_webcam_url = webcam_url
185
- if stop or (st.session_state.monitoring and webcam_url != st.session_state.current_webcam_url):
186
- st.session_state.monitoring = False
187
- st.session_state.current_webcam_url = None
188
 
189
- with col2:
190
- frame_placeholder = st.empty()
191
- status_placeholder = st.empty()
192
- timer_placeholder = st.empty()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
 
194
- if st.session_state.monitoring and st.session_state.current_webcam_url:
195
- cap = cv2.VideoCapture(webcam_url)
196
- is_video_stream = cap.isOpened()
197
-
198
- if is_video_stream:
199
- status_placeholder.write("Connected to video stream...")
200
- while st.session_state.monitoring and cap.isOpened():
201
- try:
202
- ret, frame = cap.read()
203
- if not ret:
204
- status_placeholder.error("Video stream interrupted.")
205
- break
206
- if webcam_url != st.session_state.current_webcam_url:
207
- status_placeholder.write("URL changed. Stopping video monitoring.")
208
- break
209
- res = model.predict(frame, conf=confidence)
210
- detected_frame = res[0].plot()[:, :, ::-1]
211
- frame_placeholder.image(detected_frame, use_column_width=True)
212
- status_placeholder.write(f"Objects detected: {len(res[0].boxes)}")
213
- time.sleep(0.1)
214
- except Exception as e:
215
- status_placeholder.error(f"Video error: {e}")
216
- st.session_state.monitoring = False
217
- break
218
- cap.release()
219
- else:
220
- status_placeholder.write("Monitoring image-based webcam...")
221
- while st.session_state.monitoring:
222
  try:
223
- start_time = time.time()
224
- if webcam_url != st.session_state.current_webcam_url:
225
- status_placeholder.write("URL changed. Stopping image monitoring.")
226
- break
227
- response = requests.get(webcam_url, timeout=5)
228
- if response.status_code != 200:
229
- status_placeholder.error(f"Fetch failed: HTTP {response.status_code}")
230
- break
231
- image_array = np.asarray(bytearray(response.content), dtype=np.uint8)
232
- frame = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
233
- if frame is None:
234
- status_placeholder.error("Image decoding failed.")
235
- break
236
-
237
- res = model.predict(frame, conf=confidence)
238
- detected_frame = res[0].plot()[:, :, ::-1]
239
- frame_placeholder.image(detected_frame, use_column_width=True)
240
- status_placeholder.write(f"Objects detected: {len(res[0].boxes)}")
241
-
242
- elapsed = time.time() - start_time
243
- remaining = max(0, refresh_rate - elapsed)
244
- for i in range(int(remaining), -1, -1):
245
- if not st.session_state.monitoring or webcam_url != st.session_state.current_webcam_url:
246
- status_placeholder.write("Monitoring interrupted or URL changed.")
247
- break
248
- timer_placeholder.write(f"Next scan: {i}s")
249
- time.sleep(1)
250
- except Exception as e:
251
- status_placeholder.error(f"Image fetch error: {e}")
252
- st.session_state.monitoring = False
253
- break
254
- if not st.session_state.monitoring:
255
- timer_placeholder.write("Monitoring stopped.")
 
1
+ # Import required libraries
2
  import PIL
3
  import cv2
4
  import streamlit as st
5
  from ultralytics import YOLO
6
  import tempfile
7
  import time
 
 
8
  import os
9
 
10
+ # Replace the relative path to your weight file
11
+ model_path = 'https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/best.pt' # Your correct model
12
 
13
+ # Setting page layout
14
+ st.set_page_config(
15
+ page_title="WildfireWatch",
16
+ page_icon="🔥",
17
+ layout="wide",
18
+ initial_sidebar_state="expanded"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  )
20
 
21
+ # Creating sidebar
22
+ with st.sidebar:
23
+ st.header("IMAGE/VIDEO UPLOAD")
24
+ source_file = st.file_uploader(
25
+ "Choose an image or video...", type=("jpg", "jpeg", "png", 'bmp', 'webp', 'mp4'))
26
+ confidence = float(st.slider("Select Model Confidence", 25, 100, 40)) / 100
27
+ sampling_options = {
28
+ "Every Frame": 0,
29
+ "1 FPS": 1,
30
+ "2 FPS": 2,
31
+ "5 FPS": 5,
32
+ "1 frame / 5s": 5,
33
+ "1 frame / 10s": 10,
34
+ "1 frame / 15s": 15
35
+ }
36
+ sampling_rate = st.selectbox("Analysis Rate", list(sampling_options.keys()), index=1)
37
 
38
+ # Creating main page heading
39
  st.title("WildfireWatch: Detecting Wildfire using AI")
40
+
41
+ # Adding informative pictures and description about the motivation for the app
42
+ col1, col2 = st.columns(2)
43
+ with col1:
44
+ st.image("https://huggingface.co/spaces/ankitkupadhyay/fire_and_smoke/resolve/main/Fire_1.jpeg", use_column_width=True)
45
+ with col2:
46
+ st.image("https://huggingface.co/spaces/ankitkupadhyay/fire_and_smoke/resolve/main/Fire_2.jpeg", use_column_width=True)
47
+
48
  st.markdown("""
49
+ Wildfires are a major environmental issue, causing substantial losses to ecosystems, human livelihoods, and potentially leading to loss of life. Early detection of wildfires can prevent these losses. Our application, WildfireWatch, uses state-of-the-art YOLOv8 model for real-time wildfire and smoke detection in images and videos.
50
  """)
51
+
52
  st.markdown("---")
53
 
54
+ st.header("Let's Detect Wildfire")
 
55
 
56
+ # Creating two columns on the main page
57
+ col1, col2 = st.columns(2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
+ # Adding image to the first column if image is uploaded
60
+ with col1:
61
+ if source_file:
62
+ if source_file.type.split('/')[0] == 'image':
63
+ uploaded_image = PIL.Image.open(source_file)
64
+ st.image(source_file, caption="Uploaded Image", use_column_width=True)
65
+ else:
66
+ tfile = tempfile.NamedTemporaryFile(delete=False)
67
+ tfile.write(source_file.read())
68
+ vidcap = cv2.VideoCapture(tfile.name)
 
69
 
70
+ try:
71
+ model = YOLO(model_path)
72
+ except Exception as ex:
73
+ st.error(f"Unable to load model. Check the specified path: {model_path}")
74
+ st.error(ex)
75
+ st.stop()
76
 
77
+ if st.sidebar.button('Let\'s Detect Wildfire'):
78
+ if not source_file:
79
+ st.error("Please upload a file first!")
80
+ elif source_file.type.split('/')[0] == 'image':
81
+ res = model.predict(uploaded_image, conf=confidence)
82
+ boxes = res[0].boxes
83
+ res_plotted = res[0].plot()[:, :, ::-1]
84
+ with col2:
85
+ st.image(res_plotted, caption='Detected Image', use_column_width=True)
86
+ try:
87
+ with st.expander("Detection Results"):
88
+ for box in boxes:
89
+ st.write(box.xywh)
90
+ except Exception as ex:
91
+ st.write("No image is uploaded yet!")
92
+ else:
93
+ # Frame sampling setup
94
+ total_frames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
95
+ fps = int(vidcap.get(cv2.CAP_PROP_FPS)) or 30
96
+ frame_width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))
97
+ frame_height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))
98
+ target_rate = sampling_options[sampling_rate]
99
+ frame_skip = 1 if target_rate == 0 else max(1, int(fps / target_rate) if target_rate <= 5 else int(fps * target_rate))
100
 
101
+ # Output video setup
102
+ output_tfile = tempfile.NamedTemporaryFile(delete=False, suffix='_detected.mp4')
103
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
104
+ output_fps = 1 # Fixed for short compilation
105
+ out = cv2.VideoWriter(output_tfile.name, fourcc, output_fps, (frame_width, frame_height))
106
+
107
+ success, image = vidcap.read()
108
+ frame_count = 0
109
+ processed_count = 0
110
+
111
+ while success:
112
+ if frame_count % frame_skip == 0:
113
+ res = model.predict(image, conf=confidence)
114
+ boxes = res[0].boxes
115
+ res_plotted = res[0].plot()[:, :, ::-1]
116
+ with col2:
117
+ st.image(res_plotted, caption=f'Detected Frame {frame_count}', use_column_width=True)
 
 
 
 
 
 
 
 
 
 
 
118
  try:
119
+ with st.expander("Detection Results"):
120
+ for box in boxes:
121
+ st.write(box.xywh)
122
+ except Exception as ex:
123
+ st.write("No detection results available.")
124
+ out.write(res_plotted[:, :, ::-1]) # Write only analyzed frame
125
+ processed_count += 1
126
+ if total_frames > 0:
127
+ progress = (frame_count + 1) / total_frames * 100
128
+ st.write(f"Progress: {progress:.1f}% (Analyzed {processed_count} frames)")
129
+ success, image = vidcap.read()
130
+ frame_count += 1
131
+ time.sleep(0.05)
132
+
133
+ vidcap.release()
134
+ out.release()
135
+ os.unlink(tfile.name)
136
+
137
+ with col2:
138
+ with open(output_tfile.name, 'rb') as f:
139
+ st.download_button(
140
+ label="Download Analyzed Video",
141
+ data=f,
142
+ file_name="analyzed_video.mp4",
143
+ mime="video/mp4"
144
+ )
145
+ st.write(f"Video processing complete. Analyzed {processed_count} frames.")