Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -25,7 +25,7 @@ def show_autoplay_video(video_bytes: bytes, title: str = "Video"):
|
|
25 |
st.markdown(video_html, unsafe_allow_html=True)
|
26 |
|
27 |
###############################################################################
|
28 |
-
# Session state initialization (for
|
29 |
###############################################################################
|
30 |
if "processed_frames" not in st.session_state:
|
31 |
st.session_state["processed_frames"] = []
|
@@ -45,22 +45,6 @@ st.set_page_config(
|
|
45 |
initial_sidebar_state="expanded"
|
46 |
)
|
47 |
|
48 |
-
st.title("Fire Watch: Detecting fire using AI vision models")
|
49 |
-
col1, col2 = st.columns(2)
|
50 |
-
with col1:
|
51 |
-
st.image("https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/Fire_1.jpeg", use_column_width=True)
|
52 |
-
with col2:
|
53 |
-
st.image("https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/Fire_3.png", use_column_width=True)
|
54 |
-
|
55 |
-
st.markdown("""
|
56 |
-
Fires in Colorado present a serious challenge, threatening urban communities, highways, and even remote areas.
|
57 |
-
Early detection is critical. Fire Watch uses the model YOLOv8 for real-time fire and smoke detection
|
58 |
-
in images and videos.
|
59 |
-
""")
|
60 |
-
st.markdown("---")
|
61 |
-
st.header("Fire Detection:")
|
62 |
-
|
63 |
-
|
64 |
###############################################################################
|
65 |
# SIDEBAR: Video input options, confidence, sampling options, and example selection
|
66 |
###############################################################################
|
@@ -106,7 +90,6 @@ processed_video_data = None # For example pairs
|
|
106 |
if example_option != "None":
|
107 |
# Use example videos from remote URLs.
|
108 |
if example_option == "T Example":
|
109 |
-
# For T Example: set your URLs for original and processed videos.
|
110 |
orig_url = "https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/T1.mp4"
|
111 |
proc_url = "https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/T2.mpg"
|
112 |
elif example_option == "LA Example":
|
@@ -122,14 +105,12 @@ else:
|
|
122 |
if source_file:
|
123 |
file_type = source_file.type.split('/')[0]
|
124 |
if file_type == 'image':
|
125 |
-
# For images, convert to video-like display (or you could run image detection).
|
126 |
original_image = PIL.Image.open(source_file)
|
127 |
buf = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
|
128 |
original_image.save(buf.name, format="PNG")
|
129 |
with open(buf.name, "rb") as f:
|
130 |
original_video_data = f.read()
|
131 |
else:
|
132 |
-
# For video uploads, save to a temp file.
|
133 |
tfile = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
|
134 |
tfile.write(source_file.read())
|
135 |
tfile.flush()
|
@@ -155,13 +136,11 @@ with col1:
|
|
155 |
with col2:
|
156 |
st.subheader("Result File")
|
157 |
if example_option != "None":
|
158 |
-
# For example pairs, the processed video is already available.
|
159 |
if processed_video_data:
|
160 |
show_autoplay_video(processed_video_data, title="Processed Video")
|
161 |
else:
|
162 |
st.info("No processed video available in example.")
|
163 |
else:
|
164 |
-
# For uploaded files, if a processed video is ready, show it.
|
165 |
if st.session_state["shortened_video_ready"] and st.session_state["shortened_video_data"]:
|
166 |
show_autoplay_video(st.session_state["shortened_video_data"], title="Processed Video")
|
167 |
else:
|
@@ -172,7 +151,7 @@ with col2:
|
|
172 |
###############################################################################
|
173 |
if example_option == "None" and source_file and source_file.type.split('/')[0] != 'image':
|
174 |
if st.sidebar.button("Let's Detect Wildfire"):
|
175 |
-
# Reset
|
176 |
st.session_state["processed_frames"] = []
|
177 |
st.session_state["shortened_video_data"] = None
|
178 |
st.session_state["shortened_video_ready"] = False
|
@@ -185,7 +164,7 @@ if example_option == "None" and source_file and source_file.type.split('/')[0] !
|
|
185 |
width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
186 |
height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
187 |
|
188 |
-
# Determine sampling interval
|
189 |
if video_option == "Original FPS":
|
190 |
sample_interval = 1
|
191 |
output_fps = orig_fps
|
@@ -211,7 +190,6 @@ if example_option == "None" and source_file and source_file.type.split('/')[0] !
|
|
211 |
res = model.predict(image, conf=confidence)
|
212 |
res_plotted = res[0].plot()[:, :, ::-1]
|
213 |
processed_frames.append(res_plotted)
|
214 |
-
# Update progress
|
215 |
if total_frames > 0:
|
216 |
progress_pct = int((frame_count / total_frames) * 100)
|
217 |
progress_text.text(f"Processing frame {frame_count} / {total_frames} ({progress_pct}%)")
|
@@ -227,10 +205,12 @@ if example_option == "None" and source_file and source_file.type.split('/')[0] !
|
|
227 |
# Create shortened video from processed frames.
|
228 |
if processed_frames:
|
229 |
temp_video_file = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
|
230 |
-
|
|
|
231 |
out = cv2.VideoWriter(temp_video_file.name, fourcc, output_fps, (width, height))
|
232 |
for frame in processed_frames:
|
233 |
-
|
|
|
234 |
out.release()
|
235 |
|
236 |
with open(temp_video_file.name, 'rb') as video_file:
|
@@ -242,7 +222,7 @@ if example_option == "None" and source_file and source_file.type.split('/')[0] !
|
|
242 |
st.error("No frames were processed from the video.")
|
243 |
|
244 |
###############################################################################
|
245 |
-
# Always
|
246 |
###############################################################################
|
247 |
if st.session_state["shortened_video_ready"] and st.session_state["shortened_video_data"]:
|
248 |
st.download_button(
|
|
|
25 |
st.markdown(video_html, unsafe_allow_html=True)
|
26 |
|
27 |
###############################################################################
|
28 |
+
# Session state initialization (for processed results)
|
29 |
###############################################################################
|
30 |
if "processed_frames" not in st.session_state:
|
31 |
st.session_state["processed_frames"] = []
|
|
|
45 |
initial_sidebar_state="expanded"
|
46 |
)
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
###############################################################################
|
49 |
# SIDEBAR: Video input options, confidence, sampling options, and example selection
|
50 |
###############################################################################
|
|
|
90 |
if example_option != "None":
|
91 |
# Use example videos from remote URLs.
|
92 |
if example_option == "T Example":
|
|
|
93 |
orig_url = "https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/T1.mp4"
|
94 |
proc_url = "https://huggingface.co/spaces/tstone87/ccr-colorado/resolve/main/T2.mpg"
|
95 |
elif example_option == "LA Example":
|
|
|
105 |
if source_file:
|
106 |
file_type = source_file.type.split('/')[0]
|
107 |
if file_type == 'image':
|
|
|
108 |
original_image = PIL.Image.open(source_file)
|
109 |
buf = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
|
110 |
original_image.save(buf.name, format="PNG")
|
111 |
with open(buf.name, "rb") as f:
|
112 |
original_video_data = f.read()
|
113 |
else:
|
|
|
114 |
tfile = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
|
115 |
tfile.write(source_file.read())
|
116 |
tfile.flush()
|
|
|
136 |
with col2:
|
137 |
st.subheader("Result File")
|
138 |
if example_option != "None":
|
|
|
139 |
if processed_video_data:
|
140 |
show_autoplay_video(processed_video_data, title="Processed Video")
|
141 |
else:
|
142 |
st.info("No processed video available in example.")
|
143 |
else:
|
|
|
144 |
if st.session_state["shortened_video_ready"] and st.session_state["shortened_video_data"]:
|
145 |
show_autoplay_video(st.session_state["shortened_video_data"], title="Processed Video")
|
146 |
else:
|
|
|
151 |
###############################################################################
|
152 |
if example_option == "None" and source_file and source_file.type.split('/')[0] != 'image':
|
153 |
if st.sidebar.button("Let's Detect Wildfire"):
|
154 |
+
# Reset previous processed results.
|
155 |
st.session_state["processed_frames"] = []
|
156 |
st.session_state["shortened_video_data"] = None
|
157 |
st.session_state["shortened_video_ready"] = False
|
|
|
164 |
width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
165 |
height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
166 |
|
167 |
+
# Determine sampling interval.
|
168 |
if video_option == "Original FPS":
|
169 |
sample_interval = 1
|
170 |
output_fps = orig_fps
|
|
|
190 |
res = model.predict(image, conf=confidence)
|
191 |
res_plotted = res[0].plot()[:, :, ::-1]
|
192 |
processed_frames.append(res_plotted)
|
|
|
193 |
if total_frames > 0:
|
194 |
progress_pct = int((frame_count / total_frames) * 100)
|
195 |
progress_text.text(f"Processing frame {frame_count} / {total_frames} ({progress_pct}%)")
|
|
|
205 |
# Create shortened video from processed frames.
|
206 |
if processed_frames:
|
207 |
temp_video_file = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
|
208 |
+
# Use the 'avc1' codec (H.264) for better compatibility
|
209 |
+
fourcc = cv2.VideoWriter_fourcc(*'avc1')
|
210 |
out = cv2.VideoWriter(temp_video_file.name, fourcc, output_fps, (width, height))
|
211 |
for frame in processed_frames:
|
212 |
+
frame_out = cv2.convertScaleAbs(frame)
|
213 |
+
out.write(frame_out)
|
214 |
out.release()
|
215 |
|
216 |
with open(temp_video_file.name, 'rb') as video_file:
|
|
|
222 |
st.error("No frames were processed from the video.")
|
223 |
|
224 |
###############################################################################
|
225 |
+
# Always display the download button if a processed video is ready.
|
226 |
###############################################################################
|
227 |
if st.session_state["shortened_video_ready"] and st.session_state["shortened_video_data"]:
|
228 |
st.download_button(
|