tstone87 commited on
Commit
debd205
·
verified ·
1 Parent(s): 423354e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -95
app.py CHANGED
@@ -3,9 +3,9 @@ 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
  # -------------------------------
@@ -17,132 +17,123 @@ st.set_page_config(
17
  initial_sidebar_state="expanded"
18
  )
19
 
20
- # IMPORTANT: Ensure the model file is a valid PyTorch model file.
21
- # If using a URL, it must directly point to the raw .pt file, not an HTML page.
22
- model_path = 'best.pt' # Change this to a valid path or direct URL to your model file
23
  try:
24
  model = YOLO(model_path)
25
  except Exception as ex:
26
  st.error(f"Unable to load model from: {model_path}")
27
  st.error(ex)
28
- st.stop() # Stop the app if the model isn't loaded
29
 
30
- # -------------------------------
31
- # App Title and Description
32
- st.title("WildfireWatch: Detecting Wildfire using AI")
33
  st.markdown("""
34
- Wildfires are a major environmental issue that cause substantial losses.
35
- Use this app to detect wildfires in images, videos, updating image URLs, or live YouTube streams.
 
 
36
  """)
37
 
38
  # -------------------------------
39
- # Tabs for Detection Modes
40
- tabs = st.tabs(["File Upload", "Image URL", "YouTube Live Stream"])
41
 
42
  # ===============================
43
- # Tab 1: File Upload Mode (with auto-detection for images)
44
  with tabs[0]:
45
- st.header("Detect Wildfire from Uploaded File")
46
- col_input, col_result = st.columns(2)
47
-
48
- with col_input:
49
- uploaded_file = st.file_uploader(
50
- "Choose an image or video...",
51
- type=["jpg", "jpeg", "png", "bmp", "webp", "mp4"]
52
- )
53
  file_confidence = st.slider("Select Detection Confidence", 25, 100, 40) / 100
54
-
55
  if uploaded_file:
56
  file_type = uploaded_file.type.split('/')[0]
57
- if file_type == "image":
58
- # Load image and allow toggle between Original and Detection result
59
  image = PIL.Image.open(uploaded_file)
60
- display_option = st.radio("Display Mode", options=["Original", "Detection"], index=1)
61
-
62
- if display_option == "Original":
63
- col_result.image(image, caption="Original Image", use_column_width=True)
 
64
  else:
65
- # Auto-detect without a button click
66
- results = model.predict(image, conf=file_confidence)
67
- annotated = results[0].plot()[:, :, ::-1]
68
- col_result.image(annotated, caption="Detection Result", use_column_width=True)
69
- with col_result.expander("Detection Details"):
70
- for box in results[0].boxes:
71
- col_result.write("Box (xywh):", box.xywh)
72
-
73
- elif file_type == "video":
74
  tfile = tempfile.NamedTemporaryFile(delete=False)
75
  tfile.write(uploaded_file.read())
76
  cap = cv2.VideoCapture(tfile.name)
77
- # For videos, detection is triggered with a button due to processing cost
78
- if st.button("Detect Wildfire in Video", key="detect_file_video"):
79
  while cap.isOpened():
80
  ret, frame = cap.read()
81
  if not ret:
82
  break
83
  results = model.predict(frame, conf=file_confidence)
84
- annotated = results[0].plot()[:, :, ::-1]
85
- col_result.image(annotated, caption="Detection Result", channels="BGR", use_column_width=True)
86
  time.sleep(0.05)
87
  cap.release()
88
 
89
  # ===============================
90
- # Tab 2: Updating Image URL Mode
91
  with tabs[1]:
92
- st.header("Detect Wildfire from Updating Image URL")
93
- col_input, col_result = st.columns(2)
94
-
95
- with col_input:
96
- image_url = st.text_input(
97
- "Enter the URL of the updating image",
98
- value="http://<your_updating_image_url>/current.jpg"
99
- )
100
- url_confidence = st.slider("Select Detection Confidence", 25, 100, 40, key="url_conf") / 100
101
- start_detection = st.button("Start Detection", key="start_url")
102
-
103
- if start_detection:
104
- placeholder = col_result.empty()
105
- if "stop_url" not in st.session_state:
106
- st.session_state.stop_url = False
107
-
108
- # Provide a stop button (the button will update session_state.stop_url on click)
109
- def stop_detection():
110
- st.session_state.stop_url = True
111
-
112
- st.button("Stop Detection", on_click=stop_detection, key="url_stop")
113
-
114
- # Loop until stop button is clicked
115
- while not st.session_state.stop_url:
116
- try:
117
- response = requests.get(image_url, timeout=5)
118
- image_array = np.asarray(bytearray(response.content), dtype=np.uint8)
119
- frame = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
120
- if frame is None:
121
- col_result.error("Failed to decode image from URL.")
122
  break
123
- results = model.predict(frame, conf=url_confidence)
124
- annotated = results[0].plot()[:, :, ::-1]
125
- placeholder.image(annotated, channels="BGR", use_column_width=True)
126
- time.sleep(1) # update interval in seconds
127
- st.experimental_rerun()
128
- except Exception as e:
129
- col_result.error(f"Error fetching image: {e}")
130
- break
 
 
 
 
 
 
 
 
 
131
 
132
  # ===============================
133
  # Tab 3: YouTube Live Stream Mode
134
  with tabs[2]:
135
- st.header("Detect Wildfire from YouTube Live Stream")
136
- col_input, col_result = st.columns(2)
137
-
138
- with col_input:
139
- youtube_url = st.text_input(
140
- "Enter YouTube Live URL",
141
- value="https://www.youtube.com/watch?v=<live_stream_id>"
142
- )
143
  yt_confidence = st.slider("Select Detection Confidence", 25, 100, 40, key="yt_conf") / 100
144
  start_yt = st.button("Start Live Detection", key="start_yt")
145
-
146
  if start_yt:
147
  try:
148
  streams = streamlink.streams(youtube_url)
@@ -158,17 +149,17 @@ with tabs[2]:
158
  if not cap.isOpened():
159
  st.error("Unable to open YouTube live stream.")
160
  else:
161
- stop_live = st.button("Stop Live Detection", key="yt_stop")
162
- while cap.isOpened() and not stop_live:
163
  ret, frame = cap.read()
164
  if not ret:
165
- col_result.error("Failed to retrieve frame from YouTube stream.")
166
  break
167
  results = model.predict(frame, conf=yt_confidence)
168
- annotated = results[0].plot()[:, :, ::-1]
169
- col_result.image(annotated, channels="BGR", use_column_width=True)
170
  time.sleep(0.05)
171
- stop_live = st.button("Stop Live Detection", key="yt_stop_loop")
172
  cap.release()
173
  except Exception as e:
174
  st.error(f"Error processing YouTube stream: {e}")
 
3
  import PIL.Image
4
  from ultralytics import YOLO
5
  import tempfile
6
+ import time
7
  import requests
8
  import numpy as np
 
9
  import streamlink # pip install streamlink
10
 
11
  # -------------------------------
 
17
  initial_sidebar_state="expanded"
18
  )
19
 
20
+ # IMPORTANT: Ensure the model URL returns the raw .pt file. Otherwise, use a local path.
21
+ model_path = 'https://huggingface.co/spaces/ankitkupadhyay/fire_and_smoke/resolve/main/best.pt'
 
22
  try:
23
  model = YOLO(model_path)
24
  except Exception as ex:
25
  st.error(f"Unable to load model from: {model_path}")
26
  st.error(ex)
27
+ st.stop() # Stop the app if the model cannot load
28
 
29
+ st.title("WildfireWatch: Detecting Fire and Smoke using AI")
 
 
30
  st.markdown("""
31
+ Wildfires and smoke are a major threat. This app uses a YOLOv8 model to detect fire/smoke in:
32
+ - Uploaded images or videos,
33
+ - Webcam snapshots or live streams,
34
+ - YouTube live streams.
35
  """)
36
 
37
  # -------------------------------
38
+ # Create three tabs for different modes
39
+ tabs = st.tabs(["File Upload", "Webcam / Image URL", "YouTube Live Stream"])
40
 
41
  # ===============================
42
+ # Tab 1: File Upload Mode
43
  with tabs[0]:
44
+ st.header("File Upload Mode")
45
+ col_left, col_right = st.columns(2)
46
+ with col_left:
47
+ uploaded_file = st.file_uploader("Choose an image or video...", type=["jpg", "jpeg", "png", "bmp", "webp", "mp4"])
 
 
 
 
48
  file_confidence = st.slider("Select Detection Confidence", 25, 100, 40) / 100
49
+ display_mode = st.radio("Display Mode", options=["Detection", "Original"], index=0)
50
  if uploaded_file:
51
  file_type = uploaded_file.type.split('/')[0]
52
+ if file_type == 'image':
 
53
  image = PIL.Image.open(uploaded_file)
54
+ col_left.image(image, caption="Uploaded Image", use_column_width=True)
55
+ results = model.predict(image, conf=file_confidence)
56
+ detected_image = results[0].plot()[:, :, ::-1]
57
+ if display_mode == "Detection":
58
+ col_right.image(detected_image, caption="Detection Result", use_column_width=True)
59
  else:
60
+ col_right.image(image, caption="Original Image", use_column_width=True)
61
+ with col_right.expander("Detection Details"):
62
+ for box in results[0].boxes:
63
+ st.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("Start Video Detection"):
 
69
  while cap.isOpened():
70
  ret, frame = cap.read()
71
  if not ret:
72
  break
73
  results = model.predict(frame, conf=file_confidence)
74
+ detected_frame = results[0].plot()[:, :, ::-1]
75
+ col_right.image(detected_frame, caption="Detection Frame", channels="BGR", use_column_width=True)
76
  time.sleep(0.05)
77
  cap.release()
78
 
79
  # ===============================
80
+ # Tab 2: Webcam / Image URL Mode
81
  with tabs[1]:
82
+ st.header("Webcam / Image URL Mode")
83
+ col_left, col_right = st.columns(2)
84
+ with col_left:
85
+ # Enter a webcam snapshot URL (e.g. an updating JPEG) or a live stream URL
86
+ webcam_url = st.text_input("Enter Webcam URL", value="http://<your_webcam_ip>/current.jpg")
87
+ webcam_confidence = st.slider("Select Detection Confidence", 25, 100, 40, key="webcam_conf") / 100
88
+ input_mode = st.radio("Input Mode", options=["Snapshot (Updating Image)", "Live Stream"], index=0)
89
+ start_webcam = st.button("Start Detection", key="start_webcam")
90
+ if start_webcam:
91
+ if input_mode == "Snapshot (Updating Image)":
92
+ placeholder = col_right.empty()
93
+ # Loop to periodically fetch the snapshot
94
+ while True:
95
+ try:
96
+ response = requests.get(webcam_url, timeout=5)
97
+ image_array = np.asarray(bytearray(response.content), dtype=np.uint8)
98
+ frame = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
99
+ if frame is None:
100
+ col_right.error("Failed to decode image from URL.")
101
+ break
102
+ results = model.predict(frame, conf=webcam_confidence)
103
+ detected_frame = results[0].plot()[:, :, ::-1]
104
+ placeholder.image(detected_frame, channels="BGR", use_column_width=True)
105
+ time.sleep(1) # Adjust refresh rate as needed
106
+ st.experimental_rerun()
107
+ except Exception as e:
108
+ col_right.error(f"Error fetching image: {e}")
 
 
 
109
  break
110
+ else:
111
+ cap = cv2.VideoCapture(webcam_url)
112
+ if not cap.isOpened():
113
+ col_right.error("Unable to open webcam stream. Check the URL and network connectivity.")
114
+ else:
115
+ stop_button = st.button("Stop Live Detection", key="stop_webcam")
116
+ while cap.isOpened() and not stop_button:
117
+ ret, frame = cap.read()
118
+ if not ret:
119
+ col_right.error("Failed to retrieve frame from stream.")
120
+ break
121
+ results = model.predict(frame, conf=webcam_confidence)
122
+ detected_frame = results[0].plot()[:, :, ::-1]
123
+ col_right.image(detected_frame, channels="BGR", use_column_width=True)
124
+ time.sleep(0.05)
125
+ stop_button = st.button("Stop Live Detection", key="stop_webcam_loop")
126
+ cap.release()
127
 
128
  # ===============================
129
  # Tab 3: YouTube Live Stream Mode
130
  with tabs[2]:
131
+ st.header("YouTube Live Stream Mode")
132
+ col_left, col_right = st.columns(2)
133
+ with col_left:
134
+ youtube_url = st.text_input("Enter YouTube Live URL", value="https://www.youtube.com/watch?v=<live_stream_id>")
 
 
 
 
135
  yt_confidence = st.slider("Select Detection Confidence", 25, 100, 40, key="yt_conf") / 100
136
  start_yt = st.button("Start Live Detection", key="start_yt")
 
137
  if start_yt:
138
  try:
139
  streams = streamlink.streams(youtube_url)
 
149
  if not cap.isOpened():
150
  st.error("Unable to open YouTube live stream.")
151
  else:
152
+ stop_yt = st.button("Stop Live Detection", key="stop_yt")
153
+ while cap.isOpened() and not stop_yt:
154
  ret, frame = cap.read()
155
  if not ret:
156
+ col_right.error("Failed to retrieve frame from YouTube stream.")
157
  break
158
  results = model.predict(frame, conf=yt_confidence)
159
+ detected_frame = results[0].plot()[:, :, ::-1]
160
+ col_right.image(detected_frame, channels="BGR", use_column_width=True)
161
  time.sleep(0.05)
162
+ stop_yt = st.button("Stop Live Detection", key="stop_yt_loop")
163
  cap.release()
164
  except Exception as e:
165
  st.error(f"Error processing YouTube stream: {e}")