Spaces:
Sleeping
Sleeping
File size: 17,709 Bytes
2edf7af a84c078 2edf7af ddd1a18 a84c078 e8219cc a84c078 e8219cc a84c078 e8219cc a84c078 e8219cc a84c078 e8219cc a84c078 e8219cc a84c078 e8219cc 8289c13 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
import streamlit as st
import ee
import geemap.foliumap as geemap
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import os
# Set page title and layout
st.set_page_config(page_title="سیستم پایش مزارع نیشکر", layout="wide")
# Header
st.title("سیستم پایش هوشمند مزارع نیشکر")
st.markdown("---")
# Initialize Earth Engine
@st.cache_resource
def initialize_ee():
try:
# Path to your service account key file
service_account = 'dehkhodamap-e9f0da4ce9f6514021@ee-esmaeilkiani13877.iam.gserviceaccount.com'
credentials_path = 'ee-esmaeilkiani13877-cfdea6eaf411.json'
# Check if credentials file exists
if os.path.exists(credentials_path):
credentials = ee.ServiceAccountCredentials(service_account, credentials_path)
ee.Initialize(credentials)
return True
else:
st.error("فایل احراز هویت یافت نشد. لطفا مسیر فایل را بررسی کنید.")
return False
except Exception as e:
st.error(f"خطا در اتصال به Google Earth Engine: {str(e)}")
return False
# Initialize Earth Engine
ee_initialized = initialize_ee()
if ee_initialized:
# Define coordinates for the area of interest
LATITUDE = 31.534442
LONGITUDE = 48.724416
# Create a point geometry
point = ee.Geometry.Point([LONGITUDE, LATITUDE])
# Create a buffer around the point (5 km radius)
aoi = point.buffer(5000)
# Sidebar for controls
with st.sidebar:
st.header("تنظیمات")
# Date selection
st.subheader("انتخاب بازه زمانی")
today = datetime.datetime.now()
default_start_date = today - datetime.timedelta(days=365)
start_date = st.date_input("تاریخ شروع", default_start_date)
end_date = st.date_input("تاریخ پایان", today)
# Convert dates to strings
start_date_str = start_date.strftime("%Y-%m-%d")
end_date_str = end_date.strftime("%Y-%m-%d")
# Cloud cover filter
cloud_cover = st.slider("حداکثر درصد ابر", 0, 100, 10)
# Index selection
index_options = {
"NDVI (شاخص تفاضل نرمال شده پوشش گیاهی)": "NDVI",
"EVI (شاخص پوشش گیاهی بهبود یافته)": "EVI",
"SAVI (شاخص پوشش گیاهی تعدیل شده خاک)": "SAVI",
"NDMI (شاخص رطوبت تفاضل نرمال شده)": "NDMI"
}
selected_index = st.selectbox("انتخاب شاخص", list(index_options.keys()))
index_code = index_options[selected_index]
# Analysis type
analysis_type = st.selectbox(
"نوع تحلیل",
["پایش سلامت و رشد", "مدیریت آبیاری", "مدیریت آفات", "مدیریت برداشت", "مدیریت زمین"]
)
st.markdown("---")
st.info("برای بهترین نتیجه، تصاویر با درصد ابر کمتر از 10 درصد توصیه میشود.")
# Main content
col1, col2 = st.columns([2, 1])
with col1:
st.subheader("نقشه پایش مزارع نیشکر")
# Get Sentinel-2 collection
sentinel = ee.ImageCollection('COPERNICUS/S2_SR') \
.filterDate(start_date_str, end_date_str) \
.filterBounds(aoi) \
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', cloud_cover))
# Sort by cloud cover and get the most recent image
recent_image = sentinel.sort('CLOUDY_PIXEL_PERCENTAGE').first()
# Check if we have an image
if recent_image:
# Function to calculate indices
def calculate_index(image, index_name):
if index_name == 'NDVI':
# NDVI = (NIR - Red) / (NIR + Red)
return image.normalizedDifference(['B8', 'B4']).rename('NDVI')
elif index_name == 'EVI':
# EVI = 2.5 * ((NIR - Red) / (NIR + 6 * Red - 7.5 * Blue + 1))
return image.expression(
'2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR': image.select('B8'),
'RED': image.select('B4'),
'BLUE': image.select('B2')
}).rename('EVI')
elif index_name == 'SAVI':
# SAVI = ((NIR - Red) / (NIR + Red + L)) * (1 + L), where L = 0.5
return image.expression(
'((NIR - RED) / (NIR + RED + 0.5)) * 1.5', {
'NIR': image.select('B8'),
'RED': image.select('B4')
}).rename('SAVI')
elif index_name == 'NDMI':
# NDMI = (NIR - SWIR1) / (NIR + SWIR1)
return image.normalizedDifference(['B8', 'B11']).rename('NDMI')
# Calculate the selected index
index_image = calculate_index(recent_image, index_code)
# Create a map
Map = geemap.Map()
Map.centerObject(aoi, 13)
# Add the index layer with appropriate visualization parameters
if index_code == 'NDVI' or index_code == 'EVI' or index_code == 'SAVI':
vis_params = {'min': 0, 'max': 1, 'palette': ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901', '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01', '012E01', '011D01', '011301']}
elif index_code == 'NDMI':
vis_params = {'min': -1, 'max': 1, 'palette': ['red', 'orange', 'yellow', 'green', 'cyan', 'blue']}
Map.addLayer(index_image, vis_params, f'{index_code} Index')
# Add true color layer
true_color_vis = {'bands': ['B4', 'B3', 'B2'], 'min': 0, 'max': 3000}
Map.addLayer(recent_image, true_color_vis, 'True Color', False)
# Add AOI
Map.addLayer(aoi, {'color': 'red'}, 'Area of Interest')
# Display the map
Map.to_streamlit(height=600)
# Display image metadata
image_date = ee.Date(recent_image.get('system:time_start')).format('YYYY-MM-dd').getInfo()
cloud_percentage = recent_image.get('CLOUDY_PIXEL_PERCENTAGE').getInfo()
st.info(f"تاریخ تصویر: {image_date} | درصد ابر: {cloud_percentage:.2f}%")
else:
st.error("هیچ تصویری با شرایط مورد نظر یافت نشد. لطفا محدوده زمانی یا درصد ابر را تغییر دهید.")
with col2:
st.subheader("تحلیل و توصیهها")
if recent_image:
# Calculate statistics for the index
stats = index_image.reduceRegion(
reducer=ee.Reducer.mean().combine(
reducer2=ee.Reducer.stdDev(),
sharedInputs=True
).combine(
reducer2=ee.Reducer.minMax(),
sharedInputs=True
),
geometry=aoi,
scale=10,
maxPixels=1e9
).getInfo()
# Display statistics
if index_code in stats:
mean_val = stats[f'{index_code}_mean']
std_val = stats[f'{index_code}_stdDev']
min_val = stats[f'{index_code}_min']
max_val = stats[f'{index_code}_max']
st.write(f"**میانگین {index_code}:** {mean_val:.4f}")
st.write(f"**انحراف معیار:** {std_val:.4f}")
st.write(f"**حداقل:** {min_val:.4f}")
st.write(f"**حداکثر:** {max_val:.4f}")
# Interpretation based on index and analysis type
st.markdown("### تفسیر و توصیهها")
if index_code == 'NDVI':
if mean_val > 0.7:
health_status = "عالی"
color = "green"
elif mean_val > 0.5:
health_status = "خوب"
color = "lightgreen"
elif mean_val > 0.3:
health_status = "متوسط"
color = "orange"
else:
health_status = "ضعیف"
color = "red"
st.markdown(f"**وضعیت سلامت گیاه:** <span style='color:{color}'>{health_status}</span>", unsafe_allow_html=True)
if analysis_type == "پایش سلامت و رشد":
if mean_val > 0.7:
st.success("گیاهان در وضعیت سلامت عالی قرار دارند. رشد مطلوب است.")
elif mean_val > 0.5:
st.info("گیاهان در وضعیت سلامت خوبی قرار دارند. نظارت منظم توصیه میشود.")
elif mean_val > 0.3:
st.warning("سلامت گیاهان متوسط است. بررسی عوامل محدودکننده رشد توصیه میشود.")
else:
st.error("سلامت گیاهان ضعیف است. بررسی فوری عوامل تنشزا ضروری است.")
elif analysis_type == "مدیریت آبیاری":
if mean_val < 0.4:
st.error("احتمال تنش آبی وجود دارد. افزایش آبیاری توصیه میشود.")
elif mean_val > 0.7:
st.success("وضعیت آبیاری مطلوب است.")
else:
st.info("وضعیت آبیاری قابل قبول است. نظارت منظم توصیه میشود.")
elif index_code == 'NDMI':
if mean_val > 0.4:
moisture_status = "بالا"
color = "blue"
elif mean_val > 0.2:
moisture_status = "مناسب"
color = "green"
elif mean_val > 0:
moisture_status = "متوسط"
color = "orange"
else:
moisture_status = "پایین"
color = "red"
st.markdown(f"**وضعیت رطوبت:** <span style='color:{color}'>{moisture_status}</span>", unsafe_allow_html=True)
if analysis_type == "مدیریت آبیاری":
if mean_val < 0:
st.error("رطوبت خاک پایین است. افزایش آبیاری توصیه میشود.")
elif mean_val > 0.4:
st.warning("رطوبت خاک بالاست. کاهش آبیاری توصیه میشود.")
else:
st.success("رطوبت خاک در محدوده مناسبی قرار دارد.")
# Add more specific recommendations based on analysis type
st.markdown("### اقدامات پیشنهادی")
if analysis_type == "پایش سلامت و رشد":
st.write("1. بررسی منظم وضعیت سلامت گیاه")
st.write("2. نمونهبرداری از خاک برای بررسی وضعیت مواد مغذی")
st.write("3. بررسی علائم بیماریها و آفات در مناطق با NDVI پایین")
elif analysis_type == "مدیریت آبیاری":
st.write("1. تنظیم برنامه آبیاری بر اساس شاخصهای رطوبتی")
st.write("2. نصب سنسورهای رطوبت خاک در مناطق بحرانی")
st.write("3. بررسی سیستم زهکشی در مناطق با رطوبت بالا")
elif analysis_type == "مدیریت آفات":
st.write("1. بازرسی دقیق مناطق با NDVI پایین برای شناسایی آفات")
st.write("2. برنامهریزی سمپاشی هدفمند در مناطق آلوده")
st.write("3. پایش مستمر مناطق مستعد آلودگی")
elif analysis_type == "مدیریت برداشت":
st.write("1. اولویتبندی مناطق برای برداشت بر اساس شاخص بلوغ")
st.write("2. برنامهریزی مسیرهای بهینه برداشت")
st.write("3. تخمین عملکرد محصول بر اساس شاخصهای گیاهی")
elif analysis_type == "مدیریت زمین":
st.write("1. شناسایی مناطق با پتانسیل بهبود")
st.write("2. برنامهریزی کوددهی بر اساس نقشههای شاخص گیاهی")
st.write("3. ارزیابی تأثیر روشهای مدیریتی مختلف")
else:
st.error(f"خطا در محاسبه آمار {index_code}")
# Historical trend analysis section
if recent_image:
st.markdown("---")
st.subheader("تحلیل روند تاریخی")
# Get historical data for the selected index
def get_historical_data():
# Create a time series of the selected index
def calculate_index_for_collection(image):
index = calculate_index(image, index_code)
mean = index.reduceRegion(
reducer=ee.Reducer.mean(),
geometry=aoi,
scale=30,
maxPixels=1e9
).get(index_code)
return image.set('date', image.date().format('YYYY-MM-dd')).set('index_mean', mean)
# Get a 12-month collection
collection = sentinel.map(calculate_index_for_collection)
# Get the dates and index values
dates = collection.aggregate_array('date').getInfo()
values = collection.aggregate_array('index_mean').getInfo()
# Create a dataframe
data = {'date': dates, 'value': values}
df = pd.DataFrame(data)
df = df.dropna() # Remove any NaN values
# Convert to datetime
df['date'] = pd.to_datetime(df['date'])
# Sort by date
df = df.sort_values('date')
return df
# Get the historical data
try:
hist_data = get_historical_data()
if not hist_data.empty:
# Plot the data
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(hist_data['date'], hist_data['value'], marker='o', linestyle='-')
ax.set_title(f'روند تغییرات {index_code} در طول زمان')
ax.set_xlabel('تاریخ')
ax.set_ylabel(index_code)
ax.grid(True)
# Display the plot
st.pyplot(fig)
# Trend analysis
if len(hist_data) > 1:
first_value = hist_data['value'].iloc[0]
last_value = hist_data['value'].iloc[-1]
change = ((last_value - first_value) / first_value) * 100 if first_value != 0 else 0
if change > 10:
st.success(f"روند صعودی: افزایش {change:.2f}% در شاخص {index_code} از ابتدای دوره")
elif change < -10:
st.error(f"روند نزولی: کاهش {abs(change):.2f}% در شاخص {index_code} از ابتدای دوره")
else:
st.info(f"روند ثابت: تغییر {change:.2f}% در شاخص {index_code} از ابتدای دوره")
else:
st.warning("دادههای کافی برای تحلیل روند تاریخی وجود ندارد.")
except Exception as e:
st.error(f"خطا در تحلیل روند تاریخی: {str(e)}")
else:
st.error("اتصال به Google Earth Engine برقرار نشد. لطفا تنظیمات احراز هویت را بررسی کنید.") |