Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,21 +1,15 @@
|
|
1 |
import streamlit as st
|
2 |
import cv2
|
3 |
-
import PIL
|
4 |
from ultralytics import YOLO
|
5 |
import tempfile
|
|
|
|
|
6 |
import time
|
|
|
7 |
|
8 |
-
#
|
9 |
-
#
|
10 |
-
model_path = 'https://huggingface.co/spaces/tstone87/ccr-colorado/blob/main/best.pt'
|
11 |
-
try:
|
12 |
-
model = YOLO(model_path)
|
13 |
-
except Exception as ex:
|
14 |
-
st.error(f"Unable to load model. Check the specified path: {model_path}")
|
15 |
-
st.error(ex)
|
16 |
-
|
17 |
-
# ----------------------------------------------------------------
|
18 |
-
# Set page configuration
|
19 |
st.set_page_config(
|
20 |
page_title="WildfireWatch",
|
21 |
page_icon="🔥",
|
@@ -23,90 +17,151 @@ st.set_page_config(
|
|
23 |
initial_sidebar_state="expanded"
|
24 |
)
|
25 |
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
# App Title and Description
|
28 |
st.title("WildfireWatch: Detecting Wildfire using AI")
|
29 |
-
st.markdown(
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
Use this app to analyze images, videos, or live webcam streams for signs of fire.
|
34 |
-
"""
|
35 |
-
)
|
36 |
|
37 |
-
#
|
38 |
-
#
|
39 |
-
|
40 |
|
41 |
-
#
|
42 |
-
# Tab 1: File Upload
|
43 |
-
with
|
44 |
-
st.header("
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
50 |
|
51 |
-
if uploaded_file
|
52 |
-
|
53 |
-
|
54 |
image = PIL.Image.open(uploaded_file)
|
55 |
-
|
56 |
-
if st.button("Detect Wildfire
|
57 |
-
results = model.predict(image, conf=
|
58 |
-
|
59 |
-
|
60 |
-
with
|
61 |
for box in results[0].boxes:
|
62 |
-
|
63 |
-
elif
|
64 |
-
# Process uploaded video
|
65 |
tfile = tempfile.NamedTemporaryFile(delete=False)
|
66 |
tfile.write(uploaded_file.read())
|
67 |
cap = cv2.VideoCapture(tfile.name)
|
68 |
-
if st.button("Detect Wildfire in Video"):
|
69 |
-
frame_placeholder = st.empty()
|
70 |
while cap.isOpened():
|
71 |
ret, frame = cap.read()
|
72 |
if not ret:
|
73 |
break
|
74 |
-
results = model.predict(frame, conf=
|
75 |
-
|
76 |
-
|
77 |
-
time.sleep(0.05)
|
78 |
cap.release()
|
79 |
|
80 |
-
#
|
81 |
-
# Tab 2:
|
82 |
-
with
|
83 |
-
st.header("
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
-
|
93 |
-
|
|
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
st.error("Failed to retrieve frame from stream.")
|
106 |
break
|
107 |
-
results = model.predict(frame, conf=
|
108 |
-
|
109 |
-
|
110 |
-
time.sleep(
|
111 |
-
|
112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import cv2
|
3 |
+
import PIL.Image
|
4 |
from ultralytics import YOLO
|
5 |
import tempfile
|
6 |
+
import requests
|
7 |
+
import numpy as np
|
8 |
import time
|
9 |
+
import streamlink # pip install streamlink
|
10 |
|
11 |
+
# -------------------------------
|
12 |
+
# Page & Model Setup
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
st.set_page_config(
|
14 |
page_title="WildfireWatch",
|
15 |
page_icon="🔥",
|
|
|
17 |
initial_sidebar_state="expanded"
|
18 |
)
|
19 |
|
20 |
+
model_path = 'https://huggingface.co/spaces/tstone87/ccr-colorado/blob/main/best.pt'
|
21 |
+
try:
|
22 |
+
model = YOLO(model_path)
|
23 |
+
except Exception as ex:
|
24 |
+
st.error(f"Unable to load model from: {model_path}")
|
25 |
+
st.error(ex)
|
26 |
+
|
27 |
+
# -------------------------------
|
28 |
# App Title and Description
|
29 |
st.title("WildfireWatch: Detecting Wildfire using AI")
|
30 |
+
st.markdown("""
|
31 |
+
Wildfires are a major environmental issue that cause substantial losses.
|
32 |
+
Use this app to detect wildfires in images, videos, updating image URLs, or live YouTube streams.
|
33 |
+
""")
|
|
|
|
|
|
|
34 |
|
35 |
+
# -------------------------------
|
36 |
+
# Tabs for Detection Modes
|
37 |
+
tabs = st.tabs(["File Upload", "Image URL", "YouTube Live Stream"])
|
38 |
|
39 |
+
# ===============================
|
40 |
+
# Tab 1: File Upload Mode
|
41 |
+
with tabs[0]:
|
42 |
+
st.header("Detect Wildfire from Uploaded File")
|
43 |
+
col_input, col_result = st.columns(2)
|
44 |
+
|
45 |
+
with col_input:
|
46 |
+
uploaded_file = st.file_uploader(
|
47 |
+
"Choose an image or video...",
|
48 |
+
type=["jpg", "jpeg", "png", "bmp", "webp", "mp4"]
|
49 |
+
)
|
50 |
+
file_confidence = st.slider("Select Detection Confidence", 25, 100, 40) / 100
|
51 |
|
52 |
+
if uploaded_file:
|
53 |
+
file_type = uploaded_file.type.split('/')[0]
|
54 |
+
if file_type == "image":
|
55 |
image = PIL.Image.open(uploaded_file)
|
56 |
+
col_input.image(image, caption="Uploaded Image", use_column_width=True)
|
57 |
+
if st.button("Detect Wildfire", key="detect_file_image"):
|
58 |
+
results = model.predict(image, conf=file_confidence)
|
59 |
+
annotated = results[0].plot()[:, :, ::-1]
|
60 |
+
col_result.image(annotated, caption="Detection Result", use_column_width=True)
|
61 |
+
with col_result.expander("Detection Details"):
|
62 |
for box in results[0].boxes:
|
63 |
+
col_result.write("Box (xywh):", box.xywh)
|
64 |
+
elif file_type == "video":
|
|
|
65 |
tfile = tempfile.NamedTemporaryFile(delete=False)
|
66 |
tfile.write(uploaded_file.read())
|
67 |
cap = cv2.VideoCapture(tfile.name)
|
68 |
+
if st.button("Detect Wildfire in Video", key="detect_file_video"):
|
|
|
69 |
while cap.isOpened():
|
70 |
ret, frame = cap.read()
|
71 |
if not ret:
|
72 |
break
|
73 |
+
results = model.predict(frame, conf=file_confidence)
|
74 |
+
annotated = results[0].plot()[:, :, ::-1]
|
75 |
+
col_result.image(annotated, caption="Detection Result", channels="BGR", use_column_width=True)
|
76 |
+
time.sleep(0.05)
|
77 |
cap.release()
|
78 |
|
79 |
+
# ===============================
|
80 |
+
# Tab 2: Updating Image URL Mode
|
81 |
+
with tabs[1]:
|
82 |
+
st.header("Detect Wildfire from Updating Image URL")
|
83 |
+
col_input, col_result = st.columns(2)
|
84 |
+
|
85 |
+
with col_input:
|
86 |
+
image_url = st.text_input(
|
87 |
+
"Enter the URL of the updating image",
|
88 |
+
value="http://<your_updating_image_url>/current.jpg"
|
89 |
+
)
|
90 |
+
url_confidence = st.slider("Select Detection Confidence", 25, 100, 40, key="url_conf") / 100
|
91 |
+
start_detection = st.button("Start Detection", key="start_url")
|
92 |
+
|
93 |
+
if start_detection:
|
94 |
+
placeholder = col_result.empty()
|
95 |
+
if "stop_url" not in st.session_state:
|
96 |
+
st.session_state.stop_url = False
|
97 |
|
98 |
+
# Provide a stop button (the button will update session_state.stop_url on click)
|
99 |
+
def stop_detection():
|
100 |
+
st.session_state.stop_url = True
|
101 |
|
102 |
+
st.button("Stop Detection", on_click=stop_detection, key="url_stop")
|
103 |
+
|
104 |
+
# Loop until stop button is clicked
|
105 |
+
while not st.session_state.stop_url:
|
106 |
+
try:
|
107 |
+
response = requests.get(image_url, timeout=5)
|
108 |
+
image_array = np.asarray(bytearray(response.content), dtype=np.uint8)
|
109 |
+
frame = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
|
110 |
+
if frame is None:
|
111 |
+
col_result.error("Failed to decode image from URL.")
|
|
|
112 |
break
|
113 |
+
results = model.predict(frame, conf=url_confidence)
|
114 |
+
annotated = results[0].plot()[:, :, ::-1]
|
115 |
+
placeholder.image(annotated, channels="BGR", use_column_width=True)
|
116 |
+
time.sleep(1) # update interval in seconds
|
117 |
+
# Rerun the loop by breaking out of script execution cycle.
|
118 |
+
st.experimental_rerun()
|
119 |
+
except Exception as e:
|
120 |
+
col_result.error(f"Error fetching image: {e}")
|
121 |
+
break
|
122 |
+
|
123 |
+
# ===============================
|
124 |
+
# Tab 3: YouTube Live Stream Mode
|
125 |
+
with tabs[2]:
|
126 |
+
st.header("Detect Wildfire from YouTube Live Stream")
|
127 |
+
col_input, col_result = st.columns(2)
|
128 |
+
|
129 |
+
with col_input:
|
130 |
+
youtube_url = st.text_input(
|
131 |
+
"Enter YouTube Live URL",
|
132 |
+
value="https://www.youtube.com/watch?v=<live_stream_id>"
|
133 |
+
)
|
134 |
+
yt_confidence = st.slider("Select Detection Confidence", 25, 100, 40, key="yt_conf") / 100
|
135 |
+
start_yt = st.button("Start Live Detection", key="start_yt")
|
136 |
+
|
137 |
+
if start_yt:
|
138 |
+
try:
|
139 |
+
streams = streamlink.streams(youtube_url)
|
140 |
+
if not streams:
|
141 |
+
st.error("No streams found. Please check the URL or ensure the stream is live.")
|
142 |
+
else:
|
143 |
+
best_stream = streams.get("best")
|
144 |
+
if best_stream is None:
|
145 |
+
st.error("No suitable stream found.")
|
146 |
+
else:
|
147 |
+
stream_url = best_stream.to_url()
|
148 |
+
cap = cv2.VideoCapture(stream_url)
|
149 |
+
if not cap.isOpened():
|
150 |
+
st.error("Unable to open YouTube live stream.")
|
151 |
+
else:
|
152 |
+
# Provide a stop button for live stream detection
|
153 |
+
stop_live = st.button("Stop Live Detection", key="yt_stop")
|
154 |
+
while cap.isOpened() and not stop_live:
|
155 |
+
ret, frame = cap.read()
|
156 |
+
if not ret:
|
157 |
+
col_result.error("Failed to retrieve frame from YouTube stream.")
|
158 |
+
break
|
159 |
+
results = model.predict(frame, conf=yt_confidence)
|
160 |
+
annotated = results[0].plot()[:, :, ::-1]
|
161 |
+
col_result.image(annotated, channels="BGR", use_column_width=True)
|
162 |
+
time.sleep(0.05)
|
163 |
+
# Check for stop command during loop
|
164 |
+
stop_live = st.button("Stop Live Detection", key="yt_stop_loop")
|
165 |
+
cap.release()
|
166 |
+
except Exception as e:
|
167 |
+
st.error(f"Error processing YouTube stream: {e}")
|