|
import os |
|
import urllib.request |
|
import time |
|
import gradio as gr |
|
import numpy as np |
|
from part1_data import TobaccoAnalyzer |
|
from part2_visualization import VisualizationHandler |
|
from part3 import SAMAnalyzer |
|
|
|
|
|
MODEL_PATH = 'sam_vit_h_4b8939.pth' |
|
|
|
def download_with_progress(url, filename): |
|
if os.path.exists(filename): |
|
print(f"Model already exists at {filename}") |
|
return |
|
print(f"Downloading {filename}...") |
|
start_time = time.time() |
|
urllib.request.urlretrieve(url, filename) |
|
end_time = time.time() |
|
print(f"Download completed in {end_time - start_time:.2f} seconds") |
|
|
|
|
|
if not os.path.exists(MODEL_PATH): |
|
try: |
|
download_with_progress( |
|
'https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth', |
|
MODEL_PATH |
|
) |
|
except Exception as e: |
|
print(f"Error downloading SAM model: {e}") |
|
print("Please ensure you have internet connection and sufficient disk space.") |
|
|
|
def analyze_location(location_name): |
|
"""Main analysis function with enhanced historical and forecast data""" |
|
try: |
|
analyzer = TobaccoAnalyzer() |
|
visualizer = VisualizationHandler(analyzer.optimal_conditions) |
|
|
|
|
|
location_data = analyzer.geocode_location(location_name) |
|
if not location_data: |
|
return None, None, "Location not found. Please try a different location name.", None |
|
|
|
lat, lon = location_data['lat'], location_data['lon'] |
|
|
|
|
|
df = analyzer.get_weather_data(lat, lon, historical_days=90, forecast_days=90) |
|
if df is None or df.empty: |
|
return None, None, "Unable to fetch weather data. Please try again.", None |
|
|
|
|
|
historical = df[df['type'] == 'historical'] |
|
forecast = df[df['type'] != 'historical'] |
|
|
|
if historical.empty: |
|
return None, None, "No historical data available.", None |
|
|
|
|
|
temp_score = np.clip((historical['temperature'].mean() - 15) / (30 - 15), 0, 1) |
|
humidity_score = np.clip((historical['humidity'].mean() - 50) / (80 - 50), 0, 1) |
|
rainfall_score = np.clip(historical['rainfall'].mean() / 5, 0, 1) |
|
ndvi_score = np.clip((historical['estimated_ndvi'].mean() + 1) / 2, 0, 1) |
|
|
|
|
|
trends = analyzer.analyze_trends(df) |
|
if trends is None: |
|
return None, None, "Error calculating trends.", None |
|
|
|
|
|
weights = { |
|
'temperature': 0.3, |
|
'humidity': 0.2, |
|
'rainfall': 0.2, |
|
'ndvi': 0.3 |
|
} |
|
|
|
overall_score = ( |
|
temp_score * weights['temperature'] + |
|
humidity_score * weights['humidity'] + |
|
rainfall_score * weights['rainfall'] + |
|
ndvi_score * weights['ndvi'] |
|
) |
|
|
|
|
|
time_series_plot = visualizer.create_interactive_plots(df) |
|
gauge_plot = visualizer.create_gauge_chart(overall_score) |
|
location_map = visualizer.create_enhanced_map(lat, lon, overall_score, historical['estimated_ndvi'].mean()) |
|
|
|
|
|
analysis_text = f""" |
|
📍 Location Analysis: |
|
Location: {location_data['address']} |
|
Coordinates: {lat:.4f}°N, {lon:.4f}°E |
|
Region: {location_data['region'] if location_data['region'] else 'Unknown'} |
|
|
|
🌡️ Historical Weather Analysis (Past 90 Days): |
|
Temperature: {historical['temperature'].mean():.1f}°C (±{historical['temperature'].std():.1f}°C) |
|
Daily Range: {historical['temp_range'].mean():.1f}°C |
|
Humidity: {historical['humidity'].mean():.1f}% (±{historical['humidity'].std():.1f}%) |
|
Rainfall: {historical['rainfall'].mean():.1f}mm/day (±{historical['rainfall'].std():.1f}mm) |
|
|
|
🌿 Vegetation Analysis: |
|
Current NDVI: {historical['estimated_ndvi'].mean():.2f} |
|
Minimum NDVI: {historical['estimated_ndvi'].min():.2f} |
|
Maximum NDVI: {historical['estimated_ndvi'].max():.2f} |
|
Vegetation Status: {get_vegetation_status(historical['estimated_ndvi'].mean())} |
|
|
|
🔮 Forecast Analysis (Next 90 Days): |
|
Temperature: {forecast['temperature'].mean():.1f}°C (±{forecast['temperature'].std():.1f}°C) |
|
Humidity: {forecast['humidity'].mean():.1f}% (±{forecast['humidity'].std():.1f}%) |
|
Rainfall: {forecast['rainfall'].mean():.1f}mm/day (±{forecast['rainfall'].std():.1f}mm) |
|
Expected NDVI: {forecast['estimated_ndvi'].mean():.2f} |
|
|
|
📊 Growing Condition Scores: |
|
Temperature Score: {temp_score:.2f} |
|
Humidity Score: {humidity_score:.2f} |
|
Rainfall Score: {rainfall_score:.2f} |
|
Vegetation Score: {ndvi_score:.2f} |
|
Overall Score: {overall_score:.2f} |
|
|
|
🎯 Recommendations: |
|
{get_recommendations(overall_score, ndvi_score)} |
|
|
|
⚠️ Risk Factors: |
|
{get_risk_factors(df, trends)} |
|
|
|
📝 Additional Notes: |
|
• Growing Season: {is_growing_season(historical['season'].iloc[-1])} |
|
• Weather Stability: {get_weather_stability(historical)} |
|
• Long-term Outlook: {get_long_term_outlook(trends)} |
|
""" |
|
|
|
return location_map, analysis_text, time_series_plot, gauge_plot |
|
|
|
except Exception as e: |
|
error_message = f"An error occurred: {str(e)}" |
|
print(f"Error details: {e}") |
|
return None, None, error_message, None |
|
|
|
def process_and_analyze_image(image): |
|
"""Process and analyze uploaded satellite image""" |
|
try: |
|
if image is None: |
|
return None, "Please upload an image first.", "No image provided" |
|
|
|
print("Starting image analysis...") |
|
analyzer = SAMAnalyzer(model_path=MODEL_PATH) |
|
|
|
print("Processing image...") |
|
veg_index, health_analysis, fig = analyzer.process_image(image) |
|
|
|
if veg_index is None: |
|
return None, "Error processing image.", "Image processing failed" |
|
|
|
analysis_text = f""" |
|
🌿 Vegetation Analysis Results: |
|
|
|
📊 Average Vegetation Index: {health_analysis['average_index']:.2f} |
|
|
|
🌱 Vegetation Distribution: |
|
• Low Vegetation: {health_analysis['health_distribution']['low_vegetation']*100:.1f}% |
|
• Moderate Vegetation: {health_analysis['health_distribution']['moderate_vegetation']*100:.1f}% |
|
• High Vegetation: {health_analysis['health_distribution']['high_vegetation']*100:.1f}% |
|
|
|
📋 Overall Health Status: {health_analysis['overall_health']} |
|
""" |
|
|
|
debug_msg = "Analysis completed successfully" |
|
return fig, analysis_text, debug_msg |
|
|
|
except Exception as e: |
|
error_msg = f"Error during analysis: {str(e)}" |
|
print(error_msg) |
|
return None, None, error_msg |
|
|
|
def get_vegetation_status(ndvi): |
|
"""Get detailed vegetation status based on NDVI value""" |
|
if ndvi < 0: |
|
return "Very Low - Bare soil or water bodies" |
|
elif ndvi < 0.1: |
|
return "Low - Very sparse vegetation" |
|
elif ndvi < 0.2: |
|
return "Sparse - Stressed vegetation" |
|
elif ndvi < 0.3: |
|
return "Moderate - Typical agricultural land" |
|
elif ndvi < 0.4: |
|
return "Good - Healthy vegetation" |
|
elif ndvi < 0.5: |
|
return "High - Very healthy vegetation" |
|
elif ndvi < 0.6: |
|
return "Very High - Dense vegetation" |
|
else: |
|
return "Dense - Very dense, healthy vegetation" |
|
|
|
def get_recommendations(score, ndvi): |
|
"""Get detailed recommendations based on scores""" |
|
if score >= 0.8 and ndvi >= 0.6: |
|
return """ |
|
✅ Excellent conditions for tobacco growing |
|
• Proceed with standard planting schedule |
|
• Regular monitoring recommended |
|
• Consider expansion opportunities |
|
""" |
|
elif score >= 0.6: |
|
return """ |
|
👍 Good conditions with some considerations |
|
• Implement basic risk mitigation measures |
|
• Regular monitoring essential |
|
• Consider crop insurance |
|
""" |
|
elif score >= 0.4: |
|
return """ |
|
⚠️ Marginal conditions - proceed with caution |
|
• Enhanced monitoring required |
|
• Strong risk mitigation needed |
|
• Crop insurance strongly recommended |
|
• Consider alternative timing |
|
""" |
|
else: |
|
return """ |
|
❌ Poor conditions - high risk |
|
• Not recommended for planting |
|
• Consider alternative locations |
|
• Extensive risk mitigation needed |
|
• Alternative crops suggested |
|
""" |
|
|
|
def get_risk_factors(df, trends): |
|
"""Analyze and return risk factors""" |
|
risks = [] |
|
|
|
if df['temp_range'].mean() > 15: |
|
risks.append("• High daily temperature variations") |
|
if trends['historical']['temperature']['trend'] < 0: |
|
risks.append("• Declining temperature trend") |
|
if df['rainfall'].std() > df['rainfall'].mean(): |
|
risks.append("• Inconsistent rainfall patterns") |
|
if trends['historical']['rainfall']['trend'] < 0: |
|
risks.append("• Decreasing rainfall trend") |
|
if trends['historical']['ndvi']['trend'] < 0: |
|
risks.append("• Declining vegetation health") |
|
|
|
return "\n".join(risks) if risks else "No major risk factors identified" |
|
|
|
def is_growing_season(season): |
|
"""Check if current season is suitable for growing""" |
|
season_suitability = { |
|
'Main': "Prime growing season - Optimal conditions", |
|
'Early': "Early growing season - Good potential", |
|
'Late': "Late growing season - Monitor closely", |
|
'Dry': "Dry season - Higher risk period" |
|
} |
|
return season_suitability.get(season, "Season not identified") |
|
|
|
def get_weather_stability(df): |
|
"""Assess weather stability""" |
|
temp_std = df['temperature'].std() |
|
if temp_std < 2: |
|
return "Very stable weather patterns" |
|
elif temp_std < 4: |
|
return "Moderately stable weather" |
|
return "Unstable weather patterns - higher risk" |
|
|
|
def get_long_term_outlook(trends): |
|
"""Assess long-term outlook based on trends""" |
|
temp_trend = trends['historical']['temperature']['trend'] |
|
rain_trend = trends['historical']['rainfall']['trend'] |
|
|
|
if temp_trend > 0 and rain_trend > 0: |
|
return "Improving conditions" |
|
elif temp_trend < 0 and rain_trend < 0: |
|
return "Deteriorating conditions" |
|
return "Mixed conditions - monitor closely" |
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Base()) as demo: |
|
gr.Markdown( |
|
""" |
|
# 🌱 Agricultural Credit Risk Assessment System |
|
## Weather, Vegetation, and Credit Scoring Analysis for Tobacco Farming |
|
""" |
|
) |
|
|
|
with gr.Tab("📊 Location Analysis"): |
|
with gr.Row(): |
|
location_input = gr.Textbox( |
|
label="Enter Location", |
|
placeholder="e.g., Tabora, Tanzania", |
|
scale=4 |
|
) |
|
analyze_button = gr.Button("Analyze", variant="primary", scale=1) |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
location_map = gr.HTML(label="NDVI Analysis Map") |
|
with gr.Column(scale=1): |
|
analysis_text = gr.Textbox( |
|
label="Analysis Results", |
|
lines=25, |
|
show_label=False |
|
) |
|
|
|
with gr.Row(): |
|
weather_plot = gr.Plot(label="Weather Analysis") |
|
|
|
with gr.Row(): |
|
score_gauge = gr.Plot(label="Growing Conditions Score") |
|
|
|
gr.Examples( |
|
examples=[ |
|
["Tabora, Tanzania"], |
|
["Urambo, Tabora, Tanzania"], |
|
["Sikonge, Tabora, Tanzania"], |
|
["Nzega, Tabora, Tanzania"] |
|
], |
|
inputs=location_input, |
|
outputs=[location_map, analysis_text, weather_plot, score_gauge], |
|
fn=analyze_location, |
|
cache_examples=True |
|
) |
|
|
|
analyze_button.click( |
|
fn=analyze_location, |
|
inputs=[location_input], |
|
outputs=[location_map, analysis_text, weather_plot, score_gauge] |
|
) |
|
|
|
with gr.Tab("🛰️ Satellite Image Analysis"): |
|
gr.Markdown(""" |
|
## Satellite Image Analysis with SAM2 |
|
Upload a satellite or aerial image to analyze vegetation health using advanced segmentation. |
|
""") |
|
|
|
with gr.Row(): |
|
image_input = gr.Image( |
|
label="Upload Satellite/Aerial Image", |
|
type="numpy" |
|
) |
|
|
|
with gr.Row(): |
|
analyze_image_button = gr.Button("🔍 Analyze Image", variant="primary") |
|
|
|
with gr.Row(): |
|
image_plot = gr.Plot( |
|
label="Vegetation Analysis Results" |
|
) |
|
|
|
with gr.Row(): |
|
image_analysis = gr.Textbox( |
|
label="Analysis Results", |
|
lines=10 |
|
) |
|
|
|
debug_output = gr.Textbox( |
|
label="Debug Information", |
|
lines=3, |
|
visible=True |
|
) |
|
|
|
analyze_image_button.click( |
|
fn=process_and_analyze_image, |
|
inputs=[image_input], |
|
outputs=[image_plot, image_analysis, debug_output] |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
demo.launch() |