Santipab commited on
Commit
42f114a
·
verified ·
1 Parent(s): 1e130cb

Upload 11 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ viirs-jpss1_2024_Thailand.csv filter=lfs diff=lfs merge=lfs -text
15_3000-104_8500.jpg ADDED
18_5880-98_4870.jpg ADDED
6_1000-101_7000.jpg ADDED
app.py CHANGED
@@ -1,211 +1,211 @@
1
- import streamlit as st
2
- import pandas as pd
3
- import folium
4
- from folium.plugins import HeatMap, MarkerCluster
5
- from streamlit_folium import st_folium
6
- import geopandas as gpd
7
- import lightgbm as lgb
8
- from shapely.geometry import Point
9
- import os
10
- from google import genai
11
- from ultralytics import YOLO
12
- import cv2
13
-
14
- # === ตั้งค่า UI ===
15
- st.set_page_config(page_title="🔥 Wildfire Hotspot Prediction", layout="wide")
16
-
17
- # === โหลดโมเดลและข้อมูลพยากรณ์ ===
18
- booster = lgb.Booster(model_file="model.txt")
19
- to_pred = pd.read_csv("to_pred.csv")
20
-
21
- features = [
22
- "lag1","lag3","lag7","lag14",
23
- "rollsum_3","rollsum_7","rollsum_14",
24
- "sin_doy","cos_doy","month","dow"
25
- ]
26
-
27
- proba = booster.predict(to_pred[features], num_iteration=booster.best_iteration)
28
- to_pred["proba_next_day"] = proba
29
-
30
- # === โหลด polygon ประเทศไทย ===
31
- url = "https://raw.githubusercontent.com/datasets/geo-boundaries-world-110m/master/countries.geojson"
32
- world = gpd.read_file(url)
33
- th = world[world["name"]=="Thailand"].to_crs(epsg=4326)
34
-
35
- gdf_pred = gpd.GeoDataFrame(
36
- to_pred,
37
- geometry=[Point(xy) for xy in zip(to_pred["lon_c"], to_pred["lat_c"])],
38
- crs="EPSG:4326"
39
- )
40
- gdf_pred = gdf_pred[gdf_pred.within(th.iloc[0].geometry)].copy()
41
-
42
- # === UI Header ===
43
- st.markdown(
44
- """
45
- <div style='border: 3px solid #FF4B4B; padding: 15px; border-radius: 10px; text-align: center;'>
46
- <h1 style='color: #FF4B4B;'>🔥 ระบบพยากรณ์ไฟป่าในประเทศไทย 🔥</h1>
47
- </div>
48
- """,
49
- unsafe_allow_html=True
50
- )
51
- st.markdown("")
52
- st.sidebar.markdown(
53
- """
54
- <div style='border: 3px solid green; padding: 10px; border-radius: 8px; text-align: center;'>
55
- <h2 style='color:green;'>🌱 Py PHAR</h2>
56
- </div>
57
- """,
58
- unsafe_allow_html=True
59
- )
60
-
61
- st.sidebar.header("⚙️ ตั้งค่าการแสดงผล")
62
-
63
- # ปุ่มเปิด/ปิด Forecasting
64
- use_forecast = st.sidebar.checkbox("เปิดระบบ Forecasting", value=True)
65
- # ปุ่มเปิด/ปิด Historical
66
- show_hist = st.sidebar.checkbox("แสดงจุดไฟป่าที่เคยเกิดขึ้น (Historical)", value=False)
67
-
68
- # === Folium Map ===
69
- center = [th.geometry.iloc[0].centroid.y, th.geometry.iloc[0].centroid.x]
70
- m = folium.Map(location=center, zoom_start=5, tiles="CartoDB positron")
71
- folium.GeoJson(th.__geo_interface__, name="Thailand").add_to(m)
72
-
73
- if use_forecast:
74
- radius = st.sidebar.slider("ขนาดรัศมี (radius)", 5, 30, 12)
75
- blur = st.sidebar.slider("Blur", 1, 30, 8)
76
- min_opacity = st.sidebar.slider("ความเข้มขั้นต่ำ (min_opacity)", 0.0, 1.0, 0.4, 0.05)
77
- threshold = st.sidebar.slider("แสดงเฉพาะความเสี่ยง ≥ ", 0.0, 1.0, 0.3, 0.05)
78
-
79
- heat_data = gdf_pred[gdf_pred["proba_next_day"] >= threshold][
80
- ["lat_c","lon_c","proba_next_day"]
81
- ].values.tolist()
82
-
83
- HeatMap(
84
- heat_data,
85
- radius=radius,
86
- blur=blur,
87
- min_opacity=min_opacity,
88
- max_val=1.0,
89
- name="Prediction HeatMap"
90
- ).add_to(m)
91
-
92
- # === Historical Hotspots ===
93
- if show_hist:
94
- hist_path = os.path.join(".", "viirs-jpss1_2024_Thailand.csv")
95
- if os.path.exists(hist_path):
96
- hist_df = pd.read_csv(hist_path)
97
-
98
- def pick_col(df, keys):
99
- for c in df.columns:
100
- if any(k in c.lower() for k in keys):
101
- return c
102
- return None
103
-
104
- lat_col = pick_col(hist_df, ["lat", "latitude"])
105
- lon_col = pick_col(hist_df, ["lon", "longitude"])
106
-
107
- if lat_col and lon_col:
108
- hist_df = hist_df.rename(columns={lat_col: "lat", lon_col: "lon"})
109
- gdf_hist = gpd.GeoDataFrame(
110
- hist_df,
111
- geometry=[Point(xy) for xy in zip(hist_df["lon"], hist_df["lat"])],
112
- crs="EPSG:4326"
113
- )
114
- gdf_hist = gdf_hist[gdf_hist.within(th.iloc[0].geometry)].copy()
115
- if not gdf_hist.empty:
116
- marker_cluster = MarkerCluster(name="Historical Hotspots").add_to(m)
117
- for _, row in gdf_hist.head(int(len(gdf_hist) * 0.01)).iterrows():
118
- folium.CircleMarker(
119
- location=[row["lat"], row["lon"]],
120
- radius=2,
121
- color="blue",
122
- fill=True,
123
- fill_opacity=0.6
124
- ).add_to(marker_cluster)
125
-
126
- folium.LayerControl().add_to(m)
127
-
128
- # === Layout ครึ่งจอ ===
129
- col1, col2 = st.columns([1,1])
130
-
131
- with col1:
132
- map_data = st_folium(m, use_container_width=True, height=500)
133
-
134
- with col2:
135
- st.markdown("### 🧾 เลือกชื่อดามเทียม")
136
- names = ["THEOS-2", "Sentinel-2", "NOAA-20"]
137
- selected_name = st.selectbox("เลือกชื่อ:", names, key="prosthetic_name")
138
- st.success(f"คุณเลือก: {selected_name}")
139
-
140
- model = YOLO("best.pt")
141
-
142
- example_map = {
143
- "เชียงใหม่ – ดอยอินทนนท์": "18_5880-98_4870.jpg",
144
- "อุบลราชธานี – ป่าดงใหญ่": "15_3000-104_8500.jpg",
145
- "นราธิวาส – ริมทะเล": "6_1000-101_7000.jpg"
146
- }
147
-
148
- colA, colB = st.columns([1,2])
149
-
150
- with colA:
151
- choice = st.radio("Example:", list(example_map.keys()))
152
-
153
- with colB:
154
- if choice:
155
- file = example_map[choice]
156
- if os.path.exists(file):
157
- results = model.predict(source=file, conf=0.25, save=False, verbose=False)
158
-
159
- # วาด bounding box
160
- result_img = results[0].plot()
161
- result_img = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
162
-
163
- st.image(result_img, use_container_width=True)
164
-
165
- # === แปลงชื่อไฟล์เป็น lat/lon ===
166
- basename = os.path.splitext(file)[0] # ตัด .jpg ออก
167
- lat_str, lon_str = basename.split("-")
168
- lat = float(lat_str.replace("_", "."))
169
- lon = float(lon_str.replace("_", "."))
170
- # === Gemini Integration ===
171
- api_key = "AIzaSyCNGmO0X87UdOnkk6FNkn-2mZLe0ysmW10" # <<== ใส่คีย์ตรงนี้
172
- if api_key:
173
- client = genai.Client(api_key=api_key)
174
-
175
- # ✅ ตรวจว่ามี source ไหนบ้าง (Example หรือ Map)
176
- lat, lon = None, None
177
-
178
- if choice: # กรณีเลือก Example
179
- file = example_map[choice]
180
- basename = os.path.splitext(file)[0]
181
- lat_str, lon_str = basename.split("-")
182
- lat = float(lat_str.replace("_", "."))
183
- lon = float(lon_str.replace("_", "."))
184
- st.info(f"📍 พิกัดจาก Example: {lat:.4f}, {lon:.4f}")
185
-
186
- elif map_data and map_data["last_clicked"]: # กรณีคลิกจากแผนที่
187
- lat = map_data["last_clicked"]["lat"]
188
- lon = map_data["last_clicked"]["lng"]
189
- st.info(f"📍 พิกัดจาก Map: {lat:.4f}, {lon:.4f}")
190
-
191
- # ✅ ถ้ามีพิกัดจากที่ใดที่หนึ่ง
192
- if lat and lon:
193
- if st.button("🪴 วิธีการดำเนินการฟื้นฟู ⚡", use_container_width=True):
194
- if api_key:
195
- prompt = f"""
196
- แนะนำวิธีการฟื้นฟูพื้นที่ป่าไม้ในประเทศไทยที่พิกัด โดยในรายงานระบุจังหวัดแทน ไม่ต้องใส่ Latitude และ Longitude ซ้ำ:
197
- Latitude: {lat}, Longitude: {lon}.
198
- กรุณาอธิบายว่าควรใช้พันธุ์ไม้พื้นถิ่นชนิดใด
199
- และวิธีการปลูก/การจัดการที่เหมาะสม
200
- โดยอิงกับภูมิภาคประเทศไทย
201
- """
202
- try:
203
- response = client.models.generate_content(
204
- model="gemini-2.5-flash-lite",
205
- contents=prompt
206
- )
207
- st.write(response.text)
208
- except Exception as e:
209
- st.error(f"เกิดข้อผิดพลาด: {e}")
210
-
211
-
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import folium
4
+ from folium.plugins import HeatMap, MarkerCluster
5
+ from streamlit_folium import st_folium
6
+ import geopandas as gpd
7
+ import lightgbm as lgb
8
+ from shapely.geometry import Point
9
+ import os
10
+ from google import genai
11
+ from ultralytics import YOLO
12
+ import cv2
13
+
14
+ # === ตั้งค่า UI ===
15
+ st.set_page_config(page_title="🔥 Wildfire Hotspot Prediction", layout="wide")
16
+
17
+ # === โหลดโมเดลและข้อมูลพยากรณ์ ===
18
+ booster = lgb.Booster(model_file="model.txt")
19
+ to_pred = pd.read_csv("to_pred.csv")
20
+
21
+ features = [
22
+ "lag1","lag3","lag7","lag14",
23
+ "rollsum_3","rollsum_7","rollsum_14",
24
+ "sin_doy","cos_doy","month","dow"
25
+ ]
26
+
27
+ proba = booster.predict(to_pred[features], num_iteration=booster.best_iteration)
28
+ to_pred["proba_next_day"] = proba
29
+
30
+ # === โหลด polygon ประเทศไทย ===
31
+ url = "https://raw.githubusercontent.com/datasets/geo-boundaries-world-110m/master/countries.geojson"
32
+ world = gpd.read_file(url)
33
+ th = world[world["name"]=="Thailand"].to_crs(epsg=4326)
34
+
35
+ gdf_pred = gpd.GeoDataFrame(
36
+ to_pred,
37
+ geometry=[Point(xy) for xy in zip(to_pred["lon_c"], to_pred["lat_c"])],
38
+ crs="EPSG:4326"
39
+ )
40
+ gdf_pred = gdf_pred[gdf_pred.within(th.iloc[0].geometry)].copy()
41
+
42
+ # === UI Header ===
43
+ st.markdown(
44
+ """
45
+ <div style='border: 3px solid #FF4B4B; padding: 15px; border-radius: 10px; text-align: center;'>
46
+ <h1 style='color: #FF4B4B;'>🔥 ระบบพยากรณ์ไฟป่าในประเทศไทย 🔥</h1>
47
+ </div>
48
+ """,
49
+ unsafe_allow_html=True
50
+ )
51
+ st.markdown("")
52
+ st.sidebar.markdown(
53
+ """
54
+ <div style='border: 3px solid green; padding: 10px; border-radius: 8px; text-align: center;'>
55
+ <h2 style='color:green;'>🌱 Py PHAR</h2>
56
+ </div>
57
+ """,
58
+ unsafe_allow_html=True
59
+ )
60
+
61
+ st.sidebar.header("⚙️ ตั้งค่าการแสดงผล")
62
+
63
+ # ปุ่มเปิด/ปิด Forecasting
64
+ use_forecast = st.sidebar.checkbox("เปิดระบบ Forecasting", value=True)
65
+ # ปุ่มเปิด/ปิด Historical
66
+ show_hist = st.sidebar.checkbox("แสดงจุดไฟป่าที่เคยเกิดขึ้น (Historical)", value=False)
67
+
68
+ # === Folium Map ===
69
+ center = [th.geometry.iloc[0].centroid.y, th.geometry.iloc[0].centroid.x]
70
+ m = folium.Map(location=center, zoom_start=5, tiles="CartoDB positron")
71
+ folium.GeoJson(th.__geo_interface__, name="Thailand").add_to(m)
72
+
73
+ if use_forecast:
74
+ radius = st.sidebar.slider("ขนาดรัศมี (radius)", 5, 30, 12)
75
+ blur = st.sidebar.slider("Blur", 1, 30, 8)
76
+ min_opacity = st.sidebar.slider("ความเข้มขั้นต่ำ (min_opacity)", 0.0, 1.0, 0.4, 0.05)
77
+ threshold = st.sidebar.slider("แสดงเฉพาะความเสี่ยง ≥ ", 0.0, 1.0, 0.3, 0.05)
78
+
79
+ heat_data = gdf_pred[gdf_pred["proba_next_day"] >= threshold][
80
+ ["lat_c","lon_c","proba_next_day"]
81
+ ].values.tolist()
82
+
83
+ HeatMap(
84
+ heat_data,
85
+ radius=radius,
86
+ blur=blur,
87
+ min_opacity=min_opacity,
88
+ max_val=1.0,
89
+ name="Prediction HeatMap"
90
+ ).add_to(m)
91
+
92
+ # === Historical Hotspots ===
93
+ if show_hist:
94
+ hist_path = os.path.join(".", "viirs-jpss1_2024_Thailand.csv")
95
+ if os.path.exists(hist_path):
96
+ hist_df = pd.read_csv(hist_path)
97
+
98
+ def pick_col(df, keys):
99
+ for c in df.columns:
100
+ if any(k in c.lower() for k in keys):
101
+ return c
102
+ return None
103
+
104
+ lat_col = pick_col(hist_df, ["lat", "latitude"])
105
+ lon_col = pick_col(hist_df, ["lon", "longitude"])
106
+
107
+ if lat_col and lon_col:
108
+ hist_df = hist_df.rename(columns={lat_col: "lat", lon_col: "lon"})
109
+ gdf_hist = gpd.GeoDataFrame(
110
+ hist_df,
111
+ geometry=[Point(xy) for xy in zip(hist_df["lon"], hist_df["lat"])],
112
+ crs="EPSG:4326"
113
+ )
114
+ gdf_hist = gdf_hist[gdf_hist.within(th.iloc[0].geometry)].copy()
115
+ if not gdf_hist.empty:
116
+ marker_cluster = MarkerCluster(name="Historical Hotspots").add_to(m)
117
+ for _, row in gdf_hist.head(int(len(gdf_hist) * 0.01)).iterrows():
118
+ folium.CircleMarker(
119
+ location=[row["lat"], row["lon"]],
120
+ radius=2,
121
+ color="blue",
122
+ fill=True,
123
+ fill_opacity=0.6
124
+ ).add_to(marker_cluster)
125
+
126
+ folium.LayerControl().add_to(m)
127
+
128
+ # === Layout ครึ่งจอ ===
129
+ col1, col2 = st.columns([1,1])
130
+
131
+ with col1:
132
+ map_data = st_folium(m, use_container_width=True, height=500)
133
+
134
+ with col2:
135
+ st.markdown("### 🧾 เลือกชื่อดามเทียม")
136
+ names = ["THEOS-2", "Sentinel-2", "NOAA-20"]
137
+ selected_name = st.selectbox("เลือกชื่อ:", names, key="prosthetic_name")
138
+ st.success(f"คุณเลือก: {selected_name}")
139
+
140
+ model = YOLO("best.pt")
141
+
142
+ example_map = {
143
+ "เชียงใหม่ – ดอยอินทนนท์": "18_5880-98_4870.jpg",
144
+ "อุบลราชธานี – ป่าดงใหญ่": "15_3000-104_8500.jpg",
145
+ "นราธิวาส – ริมทะเล": "6_1000-101_7000.jpg"
146
+ }
147
+
148
+ colA, colB = st.columns([1,2])
149
+
150
+ with colA:
151
+ choice = st.radio("Example:", list(example_map.keys()))
152
+
153
+ with colB:
154
+ if choice:
155
+ file = example_map[choice]
156
+ if os.path.exists(file):
157
+ results = model.predict(source=file, conf=0.25, save=False, verbose=False)
158
+
159
+ # วาด bounding box
160
+ result_img = results[0].plot()
161
+ result_img = cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)
162
+
163
+ st.image(result_img, use_container_width=True)
164
+
165
+ # === แปลงชื่อไฟล์เป็น lat/lon ===
166
+ basename = os.path.splitext(file)[0] # ตัด .jpg ออก
167
+ lat_str, lon_str = basename.split("-")
168
+ lat = float(lat_str.replace("_", "."))
169
+ lon = float(lon_str.replace("_", "."))
170
+ # === Gemini Integration ===
171
+ api_key = "AIzaSyCNGmO0X87UdOnkk6FNkn-2mZLe0ysmW10" # <<== ใส่คีย์ตรงนี้
172
+ if api_key:
173
+ client = genai.Client(api_key=api_key)
174
+
175
+ # ✅ ตรวจว่ามี source ไหนบ้าง (Example หรือ Map)
176
+ lat, lon = None, None
177
+
178
+ if choice: # กรณีเลือก Example
179
+ file = example_map[choice]
180
+ basename = os.path.splitext(file)[0]
181
+ lat_str, lon_str = basename.split("-")
182
+ lat = float(lat_str.replace("_", "."))
183
+ lon = float(lon_str.replace("_", "."))
184
+ st.info(f"📍 พิกัดจาก Example: {lat:.4f}, {lon:.4f}")
185
+
186
+ elif map_data and map_data["last_clicked"]: # กรณีคลิกจากแผนที่
187
+ lat = map_data["last_clicked"]["lat"]
188
+ lon = map_data["last_clicked"]["lng"]
189
+ st.info(f"📍 พิกัดจาก Map: {lat:.4f}, {lon:.4f}")
190
+
191
+ # ✅ ถ้ามีพิกัดจากที่ใดที่หนึ่ง
192
+ if lat and lon:
193
+ if st.button("🪴 วิธีการดำเนินการฟื้นฟู ⚡", use_container_width=True):
194
+ if api_key:
195
+ prompt = f"""
196
+ แนะนำวิธีการฟื้นฟูพื้นที่ป่าไม้ในประเทศไทยที่พิกัด โดยในรายงานระบุจังหวัดแทน ไม่ต้องใส่ Latitude และ Longitude ซ้ำ:
197
+ Latitude: {lat}, Longitude: {lon}.
198
+ กรุณาอธิบายว่าควรใช้พันธุ์ไม้พื้นถิ่นชนิดใด
199
+ และวิธีการปลูก/การจัดการที่เหมาะสม
200
+ โดยอิงกับภูมิภาคประเทศไทย
201
+ """
202
+ try:
203
+ response = client.models.generate_content(
204
+ model="gemini-2.5-flash-lite",
205
+ contents=prompt
206
+ )
207
+ st.write(response.text)
208
+ except Exception as e:
209
+ st.error(f"เกิดข้อผิดพลาด: {e}")
210
+
211
+
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8f10ea53bcd4f31a0acd57af2f4b3de01b3779183edc70e94493cdb114aba088
3
+ size 5471194
best_model_lightgbm.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1d67f9058e4a0ecae72ed9d27b79ceaa3d48b83501fc745343024859c7bf2e02
3
+ size 1745380
model.json ADDED
The diff for this file is too large to render. See raw diff
 
model.txt ADDED
The diff for this file is too large to render. See raw diff
 
requirement.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ folium
4
+ streamlit-folium
5
+ geopandas
6
+ lightgbm
7
+ shapely
8
+ google-generativeai
9
+ ultralytics
10
+ opencv-python-headless
to_pred.csv ADDED
The diff for this file is too large to render. See raw diff
 
viirs-jpss1_2024_Thailand.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dab18e541f924cc07e2d2beba7efa9a409a2ba923774fb2cad5840fb8865303b
3
+ size 11810940