AbdullahImran commited on
Commit
daf8395
·
verified ·
1 Parent(s): 7681b94

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -106
app.py CHANGED
@@ -96,6 +96,7 @@ def detect_fire(img):
96
  print(f"Error in fire detection: {e}")
97
  return False, 0.0
98
 
 
99
  def classify_severity(img):
100
  try:
101
  if xception_model is None or rf_model is None or xgb_model is None:
@@ -111,141 +112,115 @@ def classify_severity(img):
111
  print(f"Error in severity classification: {e}")
112
  return 'moderate'
113
 
 
114
  def fetch_weather_trend(lat, lon):
115
  try:
116
- try:
117
- end = datetime.utcnow()
118
- start = end - timedelta(days=1)
119
- url = API_URL.format(lat=lat, lon=lon, start=start.strftime('%Y-%m-%d'), end=end.strftime('%Y-%m-%d'))
120
- response = requests.get(url, timeout=5)
121
- if response.status_code != 200:
122
- raise Exception(f"API returned status code {response.status_code}")
123
- df = pd.DataFrame(response.json().get('daily', {}))
124
- except Exception as e:
125
- print(f"API error: {e}. Using synthetic data.")
126
- df = pd.DataFrame({
127
- 'date': [(datetime.utcnow() - timedelta(days=i)).strftime('%Y-%m-%d') for i in range(1, -1, -1)],
128
- 'precipitation_sum': [5, 2],
129
- 'temperature_2m_max': [28, 30],
130
- 'temperature_2m_min': [18, 20],
131
- 'relative_humidity_2m_max': [70, 65],
132
- 'relative_humidity_2m_min': [40, 35],
133
- 'windspeed_10m_max': [15, 18]
134
- })
135
- for c in ['precipitation_sum','temperature_2m_max','temperature_2m_min',
136
- 'relative_humidity_2m_max','relative_humidity_2m_min','windspeed_10m_max']:
137
- df[c] = pd.to_numeric(df.get(c,[]), errors='coerce')
138
- df['precipitation'] = df['precipitation_sum'].fillna(0)
139
- df['temperature'] = (df['temperature_2m_max'] + df['temperature_2m_min'])/2
140
- df['humidity'] = (df['relative_humidity_2m_max'] + df['relative_humidity_2m_min'])/2
141
- df['wind_speed'] = df['windspeed_10m_max']
142
- df['fire_risk_score'] = (
143
- 0.4*(df['temperature']/55) +
144
- 0.2*(1-df['humidity']/100) +
145
- 0.3*(df['wind_speed']/60) +
146
- 0.1*(1-df['precipitation']/50)
147
  )
148
- feats = df[['temperature','humidity','wind_speed','precipitation','fire_risk_score']]
149
- feat = feats.fillna(feats.mean()).iloc[-1].values.reshape(1,-1)
150
- if lr_model is not None:
151
- trend_cl = lr_model.predict(feat)[0]
152
- return trend_map.get(trend_cl, 'same')
153
- else:
154
- if df['fire_risk_score'].iloc[-1] > 0.6:
155
- return 'increase'
156
- elif df['fire_risk_score'].iloc[-1] < 0.4:
157
- return 'decrease'
158
- return 'same'
159
- except Exception as e:
160
- print(f"Error in weather trend analysis: {e}")
161
- return 'same'
162
-
163
- def generate_recommendations(original_severity, weather_trend):
164
- projected_severity = task_rules[original_severity][weather_trend]
165
- rec = recommendations[projected_severity]
166
- recommendation_text = f"""**Original Severity:** {original_severity.title()}
167
- **Weather Trend:** {weather_trend.title()}
168
- **Projected Severity:** {projected_severity.title()}
169
-
170
- ### Management Recommendations:
171
-
172
- **1. Immediate Actions:**
173
- {rec['immediate']}
174
-
175
- **2. Evacuation Guidelines:**
176
- {rec['evacuation']}
177
-
178
- **3. Short-term Containment:**
179
- {rec['containment']}
180
 
181
- **4. Long-term Prevention & Recovery:**
182
- {rec['prevention']}
183
 
184
- **5. Community Education:**
185
- {rec['education']}
186
- """
187
- return recommendation_text
 
 
 
 
 
 
 
 
188
 
189
  # --- MAIN PIPELINE ---
190
  def pipeline(image):
191
  if image is None:
192
- return "No image provided", "N/A", "N/A", "**Please upload an image to analyze**"
193
  img = Image.fromarray(image).convert('RGB')
194
  fire, prob = detect_fire(img)
195
  if not fire:
196
- return f"No wildfire detected (confidence: {(1-prob)*100:.1f}%)", "N/A", "N/A", "**No wildfire detected. Stay alert and maintain regular monitoring.**"
197
- severity = classify_severity(img)
 
198
  trend = fetch_weather_trend(*FOREST_COORDS['Pakistan Forest'])
199
- recommendations_text = generate_recommendations(severity, trend)
200
- return f"Wildfire detected (confidence: {prob*100:.1f}%)", severity.title(), trend.title(), recommendations_text
 
 
 
201
 
202
  # --- LOAD MODELS GLOBALLY ---
203
  vgg_model, xception_model, rf_model, xgb_model, lr_model = load_models()
204
 
205
- # --- GRADIO BLOCKS UI WITH ENHANCED TEXT & STYLING ---
206
  custom_css = """
207
- .sidebar { background: #1f2937; color: #f9fafb; padding: 1rem; border-radius: 1rem; height: 100%; }
208
- #main-title { font-size: 2.75rem; font-weight: 700; color: #111827; margin-bottom: 0.25em; }
209
- #sub-title { font-size: 1.125rem; color: #4b5563; margin-bottom: 1.5em; }
210
- .card { background: #ffffff; border-radius: 1rem; box-shadow: 0 4px 16px rgba(0,0,0,0.08); padding: 1rem; margin-bottom: 1rem; }
211
- .gr-button { border-radius: 0.75rem; padding: 0.75rem 1.5rem; font-size: 1rem; }
212
- .status-badge { display: inline-block; padding: 0.25em 0.75em; border-radius: 9999px; font-weight: 600; margin-bottom: 0.5em; }
213
- .status-fire { background: #dc2626; color: white; }
214
- .status-no-fire { background: #16a34a; color: white; }
 
215
  """
216
 
217
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
218
  with gr.Row():
219
  with gr.Column(scale=2):
220
- gr.Markdown("🔥 **Wildfire Command Center**", elem_id="main-title")
221
  gr.Markdown(
222
- "Upload a **forest image** from Pakistan to automatically detect wildfire, "
223
- "classify its severity, fetch the latest weather-driven risk trend, "
224
- "and receive expert management recommendations.",
225
  elem_id="sub-title"
226
  )
227
- image_input = gr.Image(type="numpy", label="Select Forest Image")
228
- run_btn = gr.Button("Analyze Image", variant="primary")
229
  with gr.Column(scale=1, elem_classes="sidebar"):
230
- gr.Markdown("### 📊 Last Analysis")
231
- last_status = gr.HTML("<div class='card'>No run yet</div>")
232
- last_severity = gr.HTML("<div class='card'>–</div>")
233
- last_trend = gr.HTML("<div class='card'>–</div>")
234
- last_recs = gr.HTML("<div class='card'><i>Recommendations will appear here</i></div>")
235
-
236
- def run_and_update(image):
237
- status, sev, trend, recs = pipeline(image)
238
- badge_class = "status-fire" if "Wildfire detected" in status else "status-no-fire"
239
- status_html = f"<div class='card'><span class='status-badge {badge_class}'>{status}</span></div>"
240
- return (
241
- status_html,
242
- f"<div class='card'><b>{sev}</b></div>",
243
- f"<div class='card'><b>{trend}</b></div>",
244
- f"<div class='card'>{recs}</div>"
245
- )
246
 
247
  run_btn.click(
248
- fn=run_and_update,
249
  inputs=image_input,
250
  outputs=[last_status, last_severity, last_trend, last_recs]
251
  )
 
96
  print(f"Error in fire detection: {e}")
97
  return False, 0.0
98
 
99
+
100
  def classify_severity(img):
101
  try:
102
  if xception_model is None or rf_model is None or xgb_model is None:
 
112
  print(f"Error in severity classification: {e}")
113
  return 'moderate'
114
 
115
+
116
  def fetch_weather_trend(lat, lon):
117
  try:
118
+ end = datetime.utcnow()
119
+ start = end - timedelta(days=1)
120
+ url = API_URL.format(
121
+ lat=lat, lon=lon,
122
+ start=start.strftime('%Y-%m-%d'),
123
+ end=end.strftime('%Y-%m-%d')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  )
125
+ response = requests.get(url, timeout=5)
126
+ if response.status_code != 200:
127
+ raise Exception(f"API returned status {response.status_code}")
128
+ df = pd.DataFrame(response.json().get('daily', {}))
129
+ except Exception:
130
+ df = pd.DataFrame({
131
+ 'date': [(datetime.utcnow() - timedelta(days=i)).strftime('%Y-%m-%d') for i in range(1,-1,-1)],
132
+ 'precipitation_sum': [5, 2],
133
+ 'temperature_2m_max': [28, 30],
134
+ 'temperature_2m_min': [18, 20],
135
+ 'relative_humidity_2m_max': [70, 65],
136
+ 'relative_humidity_2m_min': [40, 35],
137
+ 'windspeed_10m_max': [15, 18]
138
+ })
139
+ for c in ['precipitation_sum','temperature_2m_max','temperature_2m_min',
140
+ 'relative_humidity_2m_max','relative_humidity_2m_min','windspeed_10m_max']:
141
+ df[c] = pd.to_numeric(df[c], errors='coerce')
142
+ df['precipitation'] = df['precipitation_sum']
143
+ df['temperature'] = (df['temperature_2m_max'] + df['temperature_2m_min'])/2
144
+ df['humidity'] = (df['relative_humidity_2m_max'] + df['relative_humidity_2m_min'])/2
145
+ df['wind_speed'] = df['windspeed_10m_max']
146
+ df['fire_risk_score'] = (
147
+ 0.4*(df['temperature']/55) +
148
+ 0.2*(1-df['humidity']/100) +
149
+ 0.3*(df['wind_speed']/60) +
150
+ 0.1*(1-df['precipitation']/50)
151
+ )
152
+ feat = df[['temperature','humidity','wind_speed','precipitation','fire_risk_score']].iloc[-1].values.reshape(1,-1)
153
+ if lr_model is not None:
154
+ trend_cl = lr_model.predict(feat)[0]
155
+ return trend_map.get(trend_cl,'same')
156
+ return 'same'
157
 
 
 
158
 
159
+ def generate_recommendations(original_severity, weather_trend):
160
+ projected = task_rules[original_severity][weather_trend]
161
+ rec = recommendations[projected]
162
+ return f"**Original Severity:** {original_severity.title()} \n" \
163
+ f"**Weather Trend:** {weather_trend.title()} \n" \
164
+ f"**Projected Severity:** {projected.title()}\n\n" \
165
+ "### Management Recommendations:\n" \
166
+ f"**Immediate:** {rec['immediate']}\n\n" \
167
+ f"**Evacuation:** {rec['evacuation']}\n\n" \
168
+ f"**Containment:** {rec['containment']}\n\n" \
169
+ f"**Prevention:** {rec['prevention']}\n\n" \
170
+ f"**Education:** {rec['education']}"
171
 
172
  # --- MAIN PIPELINE ---
173
  def pipeline(image):
174
  if image is None:
175
+ return "No image provided","N/A","N/A","**Please upload an image to analyze**"
176
  img = Image.fromarray(image).convert('RGB')
177
  fire, prob = detect_fire(img)
178
  if not fire:
179
+ return (f"No wildfire detected (confidence: {(1-prob)*100:.1f}%)",
180
+ "N/A","N/A","**No wildfire detected. Stay alert.**")
181
+ sev = classify_severity(img)
182
  trend = fetch_weather_trend(*FOREST_COORDS['Pakistan Forest'])
183
+ recs = generate_recommendations(sev, trend)
184
+ return (f"**Wildfire detected** (confidence: {prob*100:.1f}%)",
185
+ f"**{sev.title()}**",
186
+ f"**{trend.title()}**",
187
+ recs)
188
 
189
  # --- LOAD MODELS GLOBALLY ---
190
  vgg_model, xception_model, rf_model, xgb_model, lr_model = load_models()
191
 
192
+ # --- GRADIO BLOCKS UI & STYLING ---
193
  custom_css = """
194
+ .sidebar { background: #2e3440; color: #eceff4; padding: 1rem; border-radius: 1rem; }
195
+ #main-title { font-size: 2.5rem; color: #3b4252; }
196
+ #sub-title { font-size: 1.125rem; color: #4c566a; }
197
+ .card { background: #eceff4; color: #2e3440; border-radius: 0.75rem; padding: 1rem; margin-bottom: 1rem; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
198
+ .gr-button { background: #5e81ac !important; color: white !important; border-radius: 0.5rem; }
199
+ .status-badge { padding: 0.25em 0.75em; border-radius: 9999px; font-weight: 600; }
200
+ .status-fire { background: #bf616a; color: white; }
201
+ .status-no-fire { background: #a3be8c; color: white; }
202
+ .gr-markdown { color: #2e3440; }
203
  """
204
 
205
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
206
  with gr.Row():
207
  with gr.Column(scale=2):
208
+ gr.Markdown("# 🔥 Wildfire Command Center", elem_id="main-title")
209
  gr.Markdown(
210
+ "Upload a **forest image** to detect wildfire, classify severity, fetch weather trend, and get management recommendations.",
 
 
211
  elem_id="sub-title"
212
  )
213
+ image_input = gr.Image(type="numpy", label="Upload Forest Image")
214
+ run_btn = gr.Button("Analyze Now", variant="primary")
215
  with gr.Column(scale=1, elem_classes="sidebar"):
216
+ gr.Markdown("## 📊 Last Analysis")
217
+ last_status = gr.Markdown("*No analysis yet*")
218
+ last_severity = gr.Markdown("---")
219
+ last_trend = gr.Markdown("---")
220
+ last_recs = gr.Markdown("---")
 
 
 
 
 
 
 
 
 
 
 
221
 
222
  run_btn.click(
223
+ fn=pipeline,
224
  inputs=image_input,
225
  outputs=[last_status, last_severity, last_trend, last_recs]
226
  )