AbdullahImran commited on
Commit
d8e87f2
·
verified ·
1 Parent(s): de67fba

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -198
app.py CHANGED
@@ -27,12 +27,10 @@ API_URL = (
27
  # --- LOAD MODELS ---
28
  def load_models():
29
  try:
30
- # Fire detector (VGG16)
31
  vgg_model = load_model(
32
  'vgg16_focal_unfreeze_more.keras',
33
  custom_objects={'BinaryFocalCrossentropy': BinaryFocalCrossentropy}
34
  )
35
- # Severity classifier (Xception)
36
  def focal_loss_fixed(gamma=2., alpha=.25):
37
  import tensorflow.keras.backend as K
38
  def loss_fn(y_true, y_pred):
@@ -45,7 +43,6 @@ def load_models():
45
  'severity_post_tta.keras',
46
  custom_objects={'focal_loss_fixed': focal_loss_fixed()}
47
  )
48
- # Ensemble and trend models
49
  rf_model = joblib.load('ensemble_rf_model.pkl')
50
  xgb_model = joblib.load('ensemble_xgb_model.pkl')
51
  lr_model = joblib.load('wildfire_logistic_model_synthetic.joblib')
@@ -55,218 +52,70 @@ def load_models():
55
  return None, None, None, None, None
56
 
57
  # --- RULES & TEMPLATES ---
58
- # Mapping severity levels and trends
59
- target_map = {0: 'mild', 1: 'moderate', 2: 'severe'}
60
- trend_map = {1: 'increase', 0: 'same', -1: 'decrease'}
61
 
62
  # Severity progression rules based on current severity and weather trend
63
  task_rules = {
64
- 'mild': {'decrease':'mild','same':'mild','increase':'moderate'},
65
- 'moderate':{'decrease':'mild','same':'moderate','increase':'severe'},
66
- 'severe': {'decrease':'moderate','same':'severe','increase':'severe'}
67
  }
68
 
69
- # Detailed recommendations for each severity level
70
- recommendations = {
71
- 'mild': {
72
- 'immediate': "Deploy spot crews for initial attack. Establish command post. Monitor fire behavior with drones or aircraft. Alert local fire stations.",
73
- 'evacuation': "No mass evacuation needed. Notify nearby communities of potential risk. Prepare evacuation routes if conditions change.",
74
- 'containment': "Establish initial fire lines. Use hand crews for direct attack. Position water resources. Clear fuel breaks where feasible.",
75
- 'prevention': "Implement controlled underburning in surrounding areas. Manage vegetation density. Create defensible spaces around structures.",
76
- 'education': "Inform public on fire watch protocols and reporting mechanisms. Train local volunteers in basic firefighting techniques."
77
- },
78
- 'moderate': {
79
- 'immediate': "Dispatch multiple engines and aerial support. Establish unified command system. Deploy heavy equipment. Request additional resources.",
80
- 'evacuation': "Prepare evacuation zones and staging areas. Advise voluntary evacuation for vulnerable populations. Alert emergency shelters.",
81
- 'containment': "Build substantial fire breaks. Conduct water drops from helicopters. Implement indirect attack strategies. Protect critical infrastructure.",
82
- 'prevention': "Initiate fuel reduction programs in adjacent areas. Create wider buffer zones. Assess watershed protection needs.",
83
- 'education': "Conduct community emergency drills. Launch awareness campaigns on evacuation procedures. Distribute preparedness materials."
84
- },
85
- 'severe': {
86
- 'immediate': "Implement full suppression with air tankers and multiple resources. Establish incident management team. Request state/federal assistance. Deploy specialized teams.",
87
- 'evacuation': "Issue mandatory evacuation orders. Open multiple emergency shelters. Implement traffic control measures. Assist vulnerable populations.",
88
- 'containment': "Deploy fire retardant lines from aircraft. Consider backfires and burnout operations. Protect critical infrastructure. Establish multiple control lines.",
89
- 'prevention': "Plan for reforestation and erosion control. Harden infrastructure against future fires. Implement watershed protection measures.",
90
- 'education': "Conduct comprehensive emergency response training. Implement risk communication strategies. Develop long-term community resilience programs."
91
- }
92
- }
93
 
94
  # --- PIPELINE FUNCTIONS ---
95
- def detect_fire(img):
96
- """Detect if a wildfire is present in the image"""
97
- try:
98
- if vgg_model is None:
99
- return True, 0.85 # Fallback if model not loaded
100
-
101
- x = keras_image.img_to_array(img.resize((128,128)))[None]
102
- x = vgg_preprocess(x)
103
- prob = float(vgg_model.predict(x)[0][0])
104
- return prob >= 0.5, prob
105
- except Exception as e:
106
- print(f"Error in fire detection: {e}")
107
- return False, 0.0
108
-
109
- def classify_severity(img):
110
- """Classify the severity of the detected wildfire"""
111
- try:
112
- if xception_model is None or rf_model is None or xgb_model is None:
113
- return 'moderate' # Fallback if models not loaded
114
-
115
- x = keras_image.img_to_array(img.resize((224,224)))[None]
116
- x = xce_preprocess(x)
117
- preds = xception_model.predict(x)
118
- rf_p = rf_model.predict(preds)[0]
119
- xgb_p = xgb_model.predict(preds)[0]
120
- ensemble = int(round((rf_p + xgb_p)/2))
121
- return target_map.get(ensemble, 'moderate')
122
- except Exception as e:
123
- print(f"Error in severity classification: {e}")
124
- return 'moderate' # Default to moderate severity if error occurs
125
-
126
- def fetch_weather_trend(lat, lon):
127
- """Fetch weather data and determine trend"""
128
- try:
129
- # Use local weather calculation if API fails
130
- try:
131
- end = datetime.utcnow()
132
- start = end - timedelta(days=1)
133
- url = API_URL.format(
134
- lat=lat, lon=lon,
135
- start=start.strftime('%Y-%m-%d'),
136
- end=end.strftime('%Y-%m-%d')
137
- )
138
- response = requests.get(url, timeout=5)
139
- if response.status_code != 200:
140
- raise Exception(f"API returned status code {response.status_code}")
141
-
142
- df = pd.DataFrame(response.json().get('daily', {}))
143
- except Exception as e:
144
- print(f"API error: {e}. Using synthetic data.")
145
- # Create synthetic weather data if API fails
146
- df = pd.DataFrame({
147
- 'date': [(datetime.utcnow() - timedelta(days=i)).strftime('%Y-%m-%d') for i in range(1, -1, -1)],
148
- 'precipitation_sum': [5, 2],
149
- 'temperature_2m_max': [28, 30],
150
- 'temperature_2m_min': [18, 20],
151
- 'relative_humidity_2m_max': [70, 65],
152
- 'relative_humidity_2m_min': [40, 35],
153
- 'windspeed_10m_max': [15, 18]
154
- })
155
-
156
- # Process weather data
157
- for c in ['precipitation_sum','temperature_2m_max','temperature_2m_min',
158
- 'relative_humidity_2m_max','relative_humidity_2m_min','windspeed_10m_max']:
159
- df[c] = pd.to_numeric(df.get(c,[]), errors='coerce')
160
-
161
- df['precipitation'] = df['precipitation_sum'].fillna(0)
162
- df['temperature'] = (df['temperature_2m_max'] + df['temperature_2m_min'])/2
163
- df['humidity'] = (df['relative_humidity_2m_max'] + df['relative_humidity_2m_min'])/2
164
- df['wind_speed'] = df['windspeed_10m_max']
165
-
166
- # Calculate fire risk score based on weather parameters
167
- df['fire_risk_score'] = (
168
- 0.4*(df['temperature']/55) +
169
- 0.2*(1-df['humidity']/100) +
170
- 0.3*(df['wind_speed']/60) +
171
- 0.1*(1-df['precipitation']/50)
172
- )
173
-
174
- # Prepare features for trend prediction
175
- feats = df[['temperature','humidity','wind_speed','precipitation','fire_risk_score']]
176
- feat = feats.fillna(feats.mean()).iloc[-1].values.reshape(1,-1)
177
-
178
- # Predict trend using logistic regression model or fallback
179
- if lr_model is not None:
180
- trend_cl = lr_model.predict(feat)[0]
181
- return trend_map.get(trend_cl, 'same')
182
- else:
183
- # Fallback logic if model isn't loaded
184
- if df['fire_risk_score'].iloc[-1] > 0.6:
185
- return 'increase'
186
- elif df['fire_risk_score'].iloc[-1] < 0.4:
187
- return 'decrease'
188
- return 'same'
189
-
190
- except Exception as e:
191
- print(f"Error in weather trend analysis: {e}")
192
- return 'same' # Default to 'same' trend if all else fails
193
-
194
- def generate_recommendations(original_severity, weather_trend):
195
- """Generate comprehensive recommendations based on severity and trend"""
196
- # Determine projected severity
197
- projected_severity = task_rules[original_severity][weather_trend]
198
-
199
- # Get recommendations for projected severity
200
- rec = recommendations[projected_severity]
201
-
202
- # Create detailed recommendation text
203
- recommendation_text = f"""**Original Severity:** {original_severity.title()}
204
- **Weather Trend:** {weather_trend.title()}
205
- **Projected Severity:** {projected_severity.title()}
206
-
207
- ### Management Recommendations:
208
-
209
- **1. Immediate Actions:**
210
- {rec['immediate']}
211
-
212
- **2. Evacuation Guidelines:**
213
- {rec['evacuation']}
214
-
215
- **3. Short-term Containment:**
216
- {rec['containment']}
217
-
218
- **4. Long-term Prevention & Recovery:**
219
- {rec['prevention']}
220
-
221
- **5. Community Education:**
222
- {rec['education']}
223
- """
224
- return recommendation_text
225
 
226
  # --- MAIN PIPELINE ---
227
- def pipeline(image):
228
- """Main processing pipeline for wildfire detection and analysis"""
229
  if image is None:
230
- return "No image provided", "N/A", "N/A", "**Please upload an image to analyze**"
231
-
232
- # Convert to PIL Image
233
  img = Image.fromarray(image).convert('RGB')
234
-
235
- # Step 1: Detect fire
236
  fire, prob = detect_fire(img)
 
237
  if not fire:
238
- return f"No wildfire detected (confidence: {(1-prob)*100:.1f}%)", "N/A", "N/A", "**No wildfire detected. Stay alert and maintain regular monitoring.**"
239
-
240
- # Step 2: Classify severity
241
  severity = classify_severity(img)
242
-
243
- # Step 3: Fetch weather trend
244
  trend = fetch_weather_trend(*FOREST_COORDS['Pakistan Forest'])
245
-
246
- # Step 4: Generate recommendations
247
- recommendations_text = generate_recommendations(severity, trend)
248
-
249
- return f"Wildfire detected (confidence: {prob*100:.1f}%)", severity.title(), trend.title(), recommendations_text
250
 
251
- # --- LOAD MODELS GLOBALLY ---
252
  vgg_model, xception_model, rf_model, xgb_model, lr_model = load_models()
253
 
254
- # --- GRADIO INTERFACE ---
255
- interface = gr.Interface(
256
- fn=pipeline,
257
- inputs=gr.Image(type='numpy', label='Upload Wildfire Image'),
258
- outputs=[
259
- gr.Textbox(label='Fire Status'),
260
- gr.Textbox(label='Current Severity Level'),
261
- gr.Textbox(label='Weather Trend'),
262
- gr.Markdown(label='Management Recommendations')
263
- ],
264
- title='Wildfire Detection & Management Assistant',
265
- description='Upload an image from a forest region in Pakistan to determine wildfire presence, severity, weather-driven trend, and get expert management recommendations.',
266
- examples=[],
267
- theme=gr.themes.Base(),
268
- allow_flagging='never'
269
- ).queue(api_open=True)
 
 
 
 
 
 
 
 
 
 
 
270
 
271
  if __name__ == '__main__':
272
- interface.launch(share=False)
 
27
  # --- LOAD MODELS ---
28
  def load_models():
29
  try:
 
30
  vgg_model = load_model(
31
  'vgg16_focal_unfreeze_more.keras',
32
  custom_objects={'BinaryFocalCrossentropy': BinaryFocalCrossentropy}
33
  )
 
34
  def focal_loss_fixed(gamma=2., alpha=.25):
35
  import tensorflow.keras.backend as K
36
  def loss_fn(y_true, y_pred):
 
43
  'severity_post_tta.keras',
44
  custom_objects={'focal_loss_fixed': focal_loss_fixed()}
45
  )
 
46
  rf_model = joblib.load('ensemble_rf_model.pkl')
47
  xgb_model = joblib.load('ensemble_xgb_model.pkl')
48
  lr_model = joblib.load('wildfire_logistic_model_synthetic.joblib')
 
52
  return None, None, None, None, None
53
 
54
  # --- RULES & TEMPLATES ---
55
+ target_map = {0: 'Mild', 1: 'Moderate', 2: 'Severe'}
56
+ trend_map = {1: 'Increasing', 0: 'Stable', -1: 'Decreasing'}
 
57
 
58
  # Severity progression rules based on current severity and weather trend
59
  task_rules = {
60
+ 'Mild': {'Decreasing':'Mild','Stable':'Mild','Increasing':'Moderate'},
61
+ 'Moderate':{'Decreasing':'Mild','Stable':'Moderate','Increasing':'Severe'},
62
+ 'Severe': {'Decreasing':'Moderate','Stable':'Severe','Increasing':'Severe'}
63
  }
64
 
65
+ recommendations = { ... } # same as before
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  # --- PIPELINE FUNCTIONS ---
68
+ def detect_fire(img): ...
69
+ def classify_severity(img): ...
70
+ def fetch_weather_trend(lat, lon): ...
71
+ def generate_recommendations(original_severity, weather_trend): ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  # --- MAIN PIPELINE ---
74
+ def pipeline(image, progress=gr.Progress()):
75
+ progress(0.1, "Analyzing image…")
76
  if image is None:
77
+ return ("No image provided", "N/A", "N/A", "**Please upload an image to analyze.**")
 
 
78
  img = Image.fromarray(image).convert('RGB')
 
 
79
  fire, prob = detect_fire(img)
80
+ progress(0.3, "Detecting fire presence…")
81
  if not fire:
82
+ return (f"No wildfire detected (confidence {(1-prob)*100:.1f}% )", "N/A", "N/A", "**No wildfire detected. Continue monitoring.**")
 
 
83
  severity = classify_severity(img)
84
+ progress(0.6, "Classifying severity…")
 
85
  trend = fetch_weather_trend(*FOREST_COORDS['Pakistan Forest'])
86
+ progress(0.8, "Computing recommendations…")
87
+ recs = generate_recommendations(severity, trend)
88
+ return (f"🔥 Wildfire detected! Confidence: {prob*100:.1f}%", severity, trend, recs)
 
 
89
 
 
90
  vgg_model, xception_model, rf_model, xgb_model, lr_model = load_models()
91
 
92
+ # --- GRADIO BLOCKS UI ---
93
+ css = '''
94
+ .sidebar { background: #111827; color: #F9FAFB; padding: 1rem; border-radius: 0.5rem; }
95
+ .card { background: #FFFFFF; border-radius: 1rem; box-shadow: 0 4px 12px rgba(0,0,0,0.1); padding: 1rem; margin-bottom: 1rem; }
96
+ #title { font-size: 2.25rem; font-weight: 700; color: #1F2937; }
97
+ #desc { font-size: 1rem; color: #4B5563; margin-bottom: 1rem; }
98
+ .gr-button { background: #EF4444 !important; color: white !important; border-radius: 0.75rem; padding: 0.75rem 1.25rem; }
99
+ '''
100
+
101
+ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
102
+ with gr.Row():
103
+ with gr.Column(scale=1):
104
+ gr.Markdown("<div id='title'>Wildfire Command Center</div>", elem_id="title")
105
+ gr.Markdown("<div id='desc'>Upload a forest image from Pakistan to detect wildfires, assess severity, forecast weather-driven trends, and receive expert management plans.</div>", elem_id="desc")
106
+ image_input = gr.Image(type='numpy', label='Upload Forest Image', tool='editor')
107
+ run_btn = gr.Button("🔍 Analyze Now", variant="primary")
108
+ with gr.Column(scale=0.6, elem_classes="sidebar"):
109
+ gr.Markdown("### Last Analysis", elem_classes="card")
110
+ last_status = gr.Textbox(label='Fire Status', interactive=False)
111
+ last_severity = gr.Textbox(label='Severity Level', interactive=False)
112
+ last_trend = gr.Textbox(label='Weather Trend', interactive=False)
113
+ last_recs = gr.Markdown(label='Recommendations', interactive=False)
114
+ run_btn.click(
115
+ fn=pipeline,
116
+ inputs=image_input,
117
+ outputs=[last_status, last_severity, last_trend, last_recs]
118
+ )
119
 
120
  if __name__ == '__main__':
121
+ demo.queue(api_open=True).launch(share=False)