AbdullahImran commited on
Commit
7b96ae6
·
verified ·
1 Parent(s): f0aec78

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -88
app.py CHANGED
@@ -26,12 +26,10 @@ 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):
@@ -44,7 +42,6 @@ def load_models():
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')
@@ -52,7 +49,7 @@ def load_models():
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 = {
@@ -62,105 +59,85 @@ task_rules = {
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
  vgg_model = load_model(
30
  'vgg16_focal_unfreeze_more.keras',
31
  custom_objects={'BinaryFocalCrossentropy': BinaryFocalCrossentropy}
32
  )
 
33
  def focal_loss_fixed(gamma=2., alpha=.25):
34
  import tensorflow.keras.backend as K
35
  def loss_fn(y_true, y_pred):
 
42
  'severity_post_tta.keras',
43
  custom_objects={'focal_loss_fixed': focal_loss_fixed()}
44
  )
 
45
  rf_model = joblib.load('ensemble_rf_model.pkl')
46
  xgb_model = joblib.load('ensemble_xgb_model.pkl')
47
  lr_model = joblib.load('wildfire_logistic_model_synthetic.joblib')
 
49
 
50
  vgg_model, xception_model, rf_model, xgb_model, lr_model = load_models()
51
 
52
+ # --- RULES & TEMPLATES (expanded!) ---
53
  target_map = {0: 'mild', 1: 'moderate', 2: 'severe'}
54
  trend_map = {1: 'increase', 0: 'same', -1: 'decrease'}
55
  task_rules = {
 
59
  }
60
  templates = {
61
  'mild': (
62
+ "📌 **Immediate Monitoring:** Although fire intensity is low, assign lookouts to monitor hotspots every 30 minutes. Use handheld IR cameras to detect any hidden flare-ups.\n\n"
63
+ "📌 **Community Alert:** Send SMS alerts to nearby villages reminding them to stay vigilant. Provide clear instructions on how to report any smoke sightings.\n\n"
64
+ "📌 **Fuel Management:** Conduct targeted removal of leaf litter and dry underbrush within a 100 m radius to reduce the chance of flare-ups.\n\n"
65
+ "📌 **Preparedness Drills:** Hold a quick drill with ground crews to review communication protocols and ensure equipment (hoses, pumps) is ready.\n\n"
66
+ "📌 **Public Education:** Distribute flyers on safe fire-watch practices and set up a hotline for rapid reporting."
67
  ),
68
  'moderate': (
69
+ "🚒 **Rapid Response:** Dispatch two engine crews and one aerial water-drop helicopter. Coordinate with the regional command center to stage retardant tanks nearby.\n\n"
70
+ "🏃‍♂️ **Evacuation Prep:** Pre-position evacuation buses at community centers. Issue voluntary evacuation notices to residents within 5 km downwind.\n\n"
71
+ "🛠 **Containment Lines:** Construct a 10 m fire break using both hand tools and bulldozers. Apply fire-retardant gel along the anticipated flank.\n\n"
72
+ "🌱 **Fuel Reduction:** Begin mechanical thinning of small trees and brush in high-risk zones adjacent to critical infrastructure.\n\n"
73
+ "📣 **Awareness Campaign:** Launch radio spots explaining what to do if fire approaches, including evacuation routes and shelter locations."
74
  ),
75
  'severe': (
76
+ "✈️ **Full Suppression:** Mobilize two air tankers for retardant drops and four ground crews with heavy equipment. Integrate real-time satellite imagery for targeting.\n\n"
77
+ "🚨 **Mandatory Evacuation:** Issue immediate evacuation orders for all residents within a 10 km radius. Open three emergency shelters with medical staff on standby.\n\n"
78
+ "🔥 **Backfire Operations:** Conduct controlled backfires under supervision of senior incident commanders to remove fuel ahead of the main front.\n\n"
79
+ "🌳 **Post-Fire Rehabilitation:** Plan reforestation with fire-resistant native species; stabilize soil to prevent erosion in burn scar areas.\n\n"
80
+ "🗣 **Crisis Communication:** Hold daily press briefings and social media updates. Provide mental-health support hotlines for displaced families."
81
  )
82
  }
83
 
84
+ # --- RECOMMENDATION GENERATOR ---
85
+ def generate_recommendations(original, trend):
86
+ projected = task_rules[original][trend]
87
+ header = (
88
+ f"## 🔥 Wildfire Situation Update\n"
89
+ f"- **Original Severity:** {original.title()}\n"
90
+ f"- **Weather Trend:** {trend.title()}\n"
91
+ f"- **Projected Severity:** {projected.title()}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  )
93
+ # build bullet paragraphs
94
+ paras = templates[projected].split("\n\n")
95
+ formatted = "\n\n".join(paras)
96
+ return header + formatted
97
 
98
+ # --- PIPELINE ---
 
 
 
 
 
 
 
 
 
 
 
99
  def pipeline(image):
100
  img = Image.fromarray(image).convert('RGB')
101
  fire, prob = detect_fire(img)
102
  if not fire:
103
+ return (
104
+ f"**No wildfire detected** (probability={prob:.2f})",
105
+ "N/A",
106
+ "N/A",
107
+ "There is currently no sign of wildfire in the image. Continue normal monitoring."
108
+ )
109
  sev = classify_severity(img)
110
  trend = fetch_weather_trend(*FOREST_COORDS['Pakistan Forest'])
111
  recs = generate_recommendations(sev, trend)
112
+ return (
113
+ f"**🔥 Fire Detected** (probability={prob:.2f})",
114
+ sev.title(),
115
+ trend.title(),
116
+ recs
117
+ )
118
 
119
+ # --- GRADIO BLOCKS UI ---
120
+ with gr.Blocks(css="""
121
+ .result-box {border: 1px solid #ddd; padding: 10px; border-radius: 8px;}
122
+ .section-title {font-size: 1.2em; font-weight: bold; margin-bottom: 5px;}
123
+ """) as demo:
124
+ gr.Markdown("# Wildfire Detection & Management Assistant")
125
+ gr.Markdown("Upload a forest image from Pakistan; the system will detect fire, assess severity, analyze weather trends, and provide in-depth recommendations.")
126
+
127
+ with gr.Row():
128
+ inp = gr.Image(type="numpy", label="Upload Wildfire Image")
129
+ with gr.Column():
130
+ status = gr.Textbox(label="Fire Status", interactive=False)
131
+ severity = gr.Textbox(label="Severity Level", interactive=False)
132
+ trend = gr.Textbox(label="Weather Trend", interactive=False)
133
+
134
+ with gr.Accordion("📋 Detailed Recommendations", open=False):
135
+ rec_box = gr.Markdown(label="Recommendations")
136
+
137
+ btn = gr.Button("Analyze")
138
+ btn.click(fn=pipeline, inputs=inp, outputs=[status, severity, trend, rec_box])
139
+
140
+ gr.HTML("<p style='font-size:0.8em; color:#666;'>© 2025 ForestAI Labs</p>")
141
 
142
+ if __name__ == "__main__":
143
+ demo.launch()