solarrun / app.py
lolzysiu's picture
Update app.py
5027df7 verified
import cv2
import numpy as np
import pandas as pd
import gradio as gr
from keras.models import load_model
from sklearn.preprocessing import OneHotEncoder, StandardScaler
# Load the pre-trained model
loaded_model = load_model('solar_irradiance_model.keras')
# Load the dataset for encoder and scaler setup
data = pd.read_csv('Solar_Irradiance.csv')
data['Latitude'] = data['Latitude'].str.rstrip('°').astype(float)
data['Longitude'] = data['Longitude'].str.rstrip('°').astype(float)
# Features and encoder/scaler setup
features = data[['Month', 'Hour', 'Latitude', 'Longitude', 'Panel_Capacity(W)', 'Panel_Efficiency', 'Wind_Speed(km/h)', 'Cloud_Cover(%)', 'temperature (°f)']]
encoder = OneHotEncoder(sparse_output=False, categories='auto')
categorical_features = features[['Month', 'Hour']]
encoder.fit(categorical_features)
scaler = StandardScaler()
numerical_features = features[['Latitude', 'Longitude', 'Panel_Capacity(W)', 'Panel_Efficiency', 'Wind_Speed(km/h)', 'Cloud_Cover(%)', 'temperature (°f)']]
scaler.fit(numerical_features)
# Shadow Removal Function
def remove_shadows(image):
"""Removes shadows using illumination normalization."""
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (21, 21), 0)
normalized = cv2.divide(gray, blurred, scale=255)
result = cv2.cvtColor(normalized, cv2.COLOR_GRAY2BGR)
return result
# Preprocess Image with Canny Edge Detection
def apply_canny_edge(image):
# Step 1: Remove shadows
shadow_free_image = remove_shadows(image)
# Step 2: Convert to grayscale
gray = cv2.cvtColor(shadow_free_image, cv2.COLOR_BGR2GRAY)
# Step 3: Apply Canny edge detection
edges = cv2.Canny(gray, 100, 200)
# Step 4: Dilate the edges to make them more prominent
kernel = np.ones((5, 5), np.uint8)
dilated_edges = cv2.dilate(edges, kernel, iterations=2)
return dilated_edges
# Calculate Usable Roof Area using Flood Fill
def find_usable_area(image, min_area, panel_area):
edges = apply_canny_edge(image) # Apply edge detection.
# Find contours from the edges
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
usable_area = 0
output_image = image.copy() # Create a copy of the input image for visualization.
for contour in contours:
area = cv2.contourArea(contour) # Calculate the area of each contour.
if area >= min_area:
usable_area += area # Add the valid area to the total usable area.
cv2.drawContours(output_image, [contour], -1, (0, 255, 0), 3) # Mark usable area in green.
else:
cv2.drawContours(output_image, [contour], -1, (0, 0, 255), 3) # Mark unusable area in red.
usable_area /= 100 # Divide the usable area by 1000 to scale it down.
num_panels = usable_area // panel_area # Number of panels that fit in the usable area.
return usable_area, int(num_panels), output_image
def predict_irradiance(month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature):
# Ensure the month is passed as a string (e.g., "January", "February")
print(f"Input month: {month}, Input hour: {hour}")
# Encode the month and hour using the same encoder fitted during training
encoded_month_hour = encoder.transform([[month, hour]])
# Check the shape of the encoded features
print(f"Encoded month-hour features: {encoded_month_hour.shape}")
# Scale the numerical features
scaled_features = scaler.transform([[latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature]])
# Combine the encoded categorical features with the scaled numerical features
processed_features = np.concatenate((encoded_month_hour, scaled_features), axis=1)
# Reshape features to match LSTM input
reshaped_features = np.reshape(processed_features, (1, 1, processed_features.shape[1]))
# Predict the irradiance using the trained model
predicted_irradiance = loaded_model.predict(reshaped_features)
# Ensure the result is not negative
return max(predicted_irradiance[0][0], 0.0)
# Main Function to Calculate Solar Energy
def calculate_solar_energy(image, month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature):
panel_area = 22 # m² per panel
min_area = 5000 # Minimum contour area to consider for valid roof
# Step 1: Find usable roof area from segmented image
usable_area, num_panels, segmented_image = find_usable_area(image, min_area, panel_area)
if usable_area == 0:
return "No valid roof detected.", segmented_image
# Step 2: Predict irradiance for the given environmental conditions
irradiance = predict_irradiance(month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature)
# Step 3: Calculate potential energy and cost based on panels and irradiance
potential_energy = num_panels * panel_area * irradiance * panel_efficiency # in Watts
potential_energy_kwh = potential_energy / 1000 # Convert to kWh
cost_per_panel = 1111 # Rs. per panel
total_cost = num_panels * cost_per_panel
results = (f"Usable Roof Area: {usable_area:.2f} m²\n"
f"Number of Panels: {num_panels}\n"
f"Predicted Irradiance: {irradiance:.2f} W/m²\n"
f"Potential Solar Energy: {potential_energy_kwh:.2f} kWh\n"
f"Total Cost of Panels: Rs. {total_cost}")
return results, segmented_image
# Gradio Interface function
def interface_fn(image, month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature):
results, segmented_image = calculate_solar_energy(image, month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature)
return results, segmented_image
# Gradio interface setup
interface = gr.Interface(
fn=interface_fn,
inputs=[
gr.Image(type="numpy", label="Upload Rooftop Image"),
gr.Dropdown(['January', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'], label="Month"),
gr.Slider(0, 23, step=1, label="Hour"),
gr.Number(label="Latitude"),
gr.Number(label="Longitude"),
gr.Number(label="Panel Capacity (W)"),
gr.Number(label="Panel Efficiency (0-1)"),
gr.Number(label="Wind Speed (km/h)"),
gr.Number(label="Cloud Cover (%)"),
gr.Number(label="Temperature (°F)")
],
outputs=[
gr.Textbox(label="Results"),
gr.Image(type="numpy", label="Segmented Rooftop Area")
],
title="Solar Energy Potential and Cost Estimator",
description="Upload an image of the rooftop and enter environmental details to calculate potential solar energy, number of panels, and cost."
)
interface.launch()