AbdullahImran commited on
Commit
bb48649
·
verified ·
1 Parent(s): 6eeb9e0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +207 -101
app.py CHANGED
@@ -26,141 +26,247 @@ API_URL = (
26
 
27
  # --- LOAD MODELS ---
28
  def load_models():
29
- # Fire detector (VGG16)
30
- vgg_model = load_model(
31
- 'vgg16_focal_unfreeze_more.keras',
32
- custom_objects={'BinaryFocalCrossentropy': BinaryFocalCrossentropy}
33
- )
34
- # Severity classifier (Xception)
35
- def focal_loss_fixed(gamma=2., alpha=.25):
36
- import tensorflow.keras.backend as K
37
- def loss_fn(y_true, y_pred):
38
- eps = K.epsilon(); y_pred = K.clip(y_pred, eps, 1.-eps)
39
- ce = -y_true * K.log(y_pred)
40
- w = alpha * K.pow(1-y_pred, gamma)
41
- return K.mean(w * ce, axis=-1)
42
- return loss_fn
43
- xce_model = load_model(
44
- 'severity_post_tta.keras',
45
- custom_objects={'focal_loss_fixed': focal_loss_fixed()}
46
- )
47
- # Ensemble and trend models
48
- rf_model = joblib.load('ensemble_rf_model.pkl')
49
- xgb_model = joblib.load('ensemble_xgb_model.pkl')
50
- lr_model = joblib.load('wildfire_logistic_model_synthetic.joblib')
51
- return vgg_model, xce_model, rf_model, xgb_model, lr_model
52
-
53
- vgg_model, xception_model, rf_model, xgb_model, lr_model = load_models()
 
 
54
 
55
  # --- RULES & TEMPLATES ---
 
56
  target_map = {0: 'mild', 1: 'moderate', 2: 'severe'}
57
  trend_map = {1: 'increase', 0: 'same', -1: 'decrease'}
 
 
58
  task_rules = {
59
  'mild': {'decrease':'mild','same':'mild','increase':'moderate'},
60
  'moderate':{'decrease':'mild','same':'moderate','increase':'severe'},
61
  'severe': {'decrease':'moderate','same':'severe','increase':'severe'}
62
  }
63
- templates = {
64
- 'mild': (
65
- "**1. Immediate actions:** Monitor fire; deploy spot crews.\n"
66
- "**2. Evacuation:** No mass evacuation; notify nearby communities.\n"
67
- "**3. Short-term containment:** Establish fire lines.\n"
68
- "**4. Long-term prevention:** Controlled underburning; vegetation management.\n"
69
- "**5. Education:** Inform public on firewatch and reporting."
70
- ),
71
- 'moderate': (
72
- "**1. Immediate actions:** Dispatch engines and aerial support.\n"
73
- "**2. Evacuation:** Prepare evacuation zones; advise voluntary evacuation.\n"
74
- "**3. Short-term containment:** Build fire breaks; water drops.\n"
75
- "**4. Long-term prevention:** Fuel reduction programs.\n"
76
- "**5. Education:** Community drills and awareness campaigns."
77
- ),
78
- 'severe': (
79
- "**1. Immediate actions:** Full suppression with air tankers.\n"
80
- "**2. Evacuation:** Mandatory evacuation; open shelters.\n"
81
- "**3. Short-term containment:** Fire retardant lines; backfires.\n"
82
- "**4. Long-term prevention:** Reforestation; infrastructure hardening.\n"
83
- "**5. Education:** Emergency response training; risk communication."
84
- )
 
 
85
  }
86
 
87
  # --- PIPELINE FUNCTIONS ---
88
  def detect_fire(img):
89
- x = keras_image.img_to_array(img.resize((128,128)))[None]
90
- x = vgg_preprocess(x)
91
- prob = float(vgg_model.predict(x)[0][0])
92
- return prob >= 0.5, prob
93
-
 
 
 
 
 
 
 
94
 
95
  def classify_severity(img):
96
- x = keras_image.img_to_array(img.resize((224,224)))[None]
97
- x = xce_preprocess(x)
98
- preds = xception_model.predict(x)
99
- rf_p = rf_model.predict(preds)[0]
100
- xgb_p = xgb_model.predict(preds)[0]
101
- ensemble = int(round((rf_p + xgb_p)/2))
102
- return target_map.get(ensemble, 'moderate')
103
-
 
 
 
 
 
 
 
104
 
105
  def fetch_weather_trend(lat, lon):
106
- end = datetime.utcnow()
107
- start = end - timedelta(days=1)
108
- url = API_URL.format(lat=lat, lon=lon,
109
- start=start.strftime('%Y-%m-%d'),
110
- end=end.strftime('%Y-%m-%d'))
111
- df = pd.DataFrame(requests.get(url).json().get('daily', {}))
112
- for c in ['precipitation_sum','temperature_2m_max','temperature_2m_min',
113
- 'relative_humidity_2m_max','relative_humidity_2m_min','windspeed_10m_max']:
114
- df[c] = pd.to_numeric(df.get(c,[]), errors='coerce')
115
- df['precipitation'] = df['precipitation_sum'].fillna(0)
116
- df['temperature'] = (df['temperature_2m_max'] + df['temperature_2m_min'])/2
117
- df['humidity'] = (df['relative_humidity_2m_max'] + df['relative_humidity_2m_min'])/2
118
- df['wind_speed'] = df['windspeed_10m_max']
119
- df['fire_risk_score'] = (
120
- 0.4*(df['temperature']/55) +
121
- 0.2*(1-df['humidity']/100) +
122
- 0.3*(df['wind_speed']/60) +
123
- 0.1*(1-df['precipitation']/50)
124
- )
125
- feats = df[['temperature','humidity','wind_speed','precipitation','fire_risk_score']]
126
- feat = feats.fillna(feats.mean()).iloc[-1].values.reshape(1,-1)
127
- trend_cl = lr_model.predict(feat)[0]
128
- return trend_map.get(trend_cl, 'same')
129
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  def generate_recommendations(original_severity, weather_trend):
132
- # determine projected severity
133
- proj = task_rules[original_severity][weather_trend]
134
- rec = templates[proj]
135
- # proper multi-line header
136
- header = f"""**Original:** {original_severity.title()}
137
- **Trend:** {weather_trend.title()}
138
- **Projected:** {proj.title()}\n\n"""
139
- return header + rec
 
 
 
140
 
141
- # --- GRADIO INTERFACE ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  def pipeline(image):
 
 
 
 
 
143
  img = Image.fromarray(image).convert('RGB')
 
 
144
  fire, prob = detect_fire(img)
145
  if not fire:
146
- return f"No wildfire detected (prob={prob:.2f})", "N/A", "N/A", "**No wildfire detected. Stay alert.**"
147
- sev = classify_severity(img)
 
 
 
 
148
  trend = fetch_weather_trend(*FOREST_COORDS['Pakistan Forest'])
149
- recs = generate_recommendations(sev, trend)
150
- return f"Fire Detected (prob={prob:.2f})", sev.title(), trend, recs
 
 
 
 
 
 
151
 
 
152
  interface = gr.Interface(
153
  fn=pipeline,
154
  inputs=gr.Image(type='numpy', label='Upload Wildfire Image'),
155
  outputs=[
156
  gr.Textbox(label='Fire Status'),
157
- gr.Textbox(label='Severity Level'),
158
  gr.Textbox(label='Weather Trend'),
159
- gr.Markdown(label='Recommendations')
160
  ],
161
  title='Wildfire Detection & Management Assistant',
162
- description='Upload an image from a forest region in Pakistan to determine wildfire presence, severity, weather-driven trend, projection, and get expert recommendations.'
 
 
 
163
  )
164
 
165
  if __name__ == '__main__':
166
- interface.launch()
 
26
 
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):
39
+ eps = K.epsilon(); y_pred = K.clip(y_pred, eps, 1.-eps)
40
+ ce = -y_true * K.log(y_pred)
41
+ w = alpha * K.pow(1-y_pred, gamma)
42
+ return K.mean(w * ce, axis=-1)
43
+ return loss_fn
44
+ xce_model = load_model(
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')
52
+ return vgg_model, xce_model, rf_model, xgb_model, lr_model
53
+ except Exception as e:
54
+ print(f"Error loading models: {e}")
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
  )
270
 
271
  if __name__ == '__main__':
272
+ interface.launch(share=False)