sollar / app.py
lolzysiu's picture
Update app.py
743cf47 verified
import cv2
import numpy as np
import gradio as gr
import os
import tensorflow as tf
import pandas as pd
# Disable GPU (if necessary)
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
# Solar panel specifications for different types
PANEL_TYPES = {
"Monocrystalline": {"efficiency": 0.22, "cost_per_watt": 0.8},
"Polycrystalline": {"efficiency": 0.18, "cost_per_watt": 0.6},
"Thin-Film": {"efficiency": 0.12, "cost_per_watt": 0.5}
}
# Constants
AVERAGE_SUNLIGHT_HOURS_PER_DAY = 5
USD_TO_INR_CONVERSION_RATE = 83 # Convert USD to INR
# Load the pre-trained LSTM model
model_path = 'solar_irradiance_model.keras'
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model file not found at: {model_path}")
model = tf.keras.models.load_model(model_path)
# Preprocessing image
def preprocess_image(image, clip_limit=2.0, tile_size=8):
try:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=(tile_size, tile_size))
equalized = clahe.apply(gray)
_, thresholded = cv2.threshold(equalized, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
return thresholded
except Exception as e:
return f"Error in image preprocessing: {str(e)}"
# Find the roof contour
def find_roof_contour(mask, min_area=1000):
try:
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
filtered_contours = [contour for contour in contours if cv2.contourArea(contour) >= min_area]
if not filtered_contours:
return None
return max(filtered_contours, key=cv2.contourArea)
except Exception as e:
return f"Error in finding roof contour: {str(e)}"
# Calculate roof area
def calculate_roof_area(contour, pixel_area=0.1):
try:
if contour is None:
return 0
contour_area_pixels = cv2.contourArea(contour)
real_area = contour_area_pixels * pixel_area
return real_area
except Exception as e:
return f"Error in calculating roof area: {str(e)}"
# Calculate panels, energy, and cost
def calculate_panels_and_energy(roof_area, panel_length, panel_width, panel_type, irradiance):
try:
panel_area = panel_length * panel_width
panel_info = PANEL_TYPES[panel_type]
panel_efficiency = panel_info["efficiency"]
power_per_square_meter = irradiance * panel_efficiency
energy_per_panel = power_per_square_meter * panel_area
num_panels = int(roof_area / panel_area)
total_energy_output = num_panels * energy_per_panel * AVERAGE_SUNLIGHT_HOURS_PER_DAY
total_energy_kwh = total_energy_output / 1000
cost_per_panel_inr = 1000 # Fixed cost in INR per panel
total_cost_inr = num_panels * cost_per_panel_inr
return num_panels, total_energy_kwh, total_cost_inr
except Exception as e:
return f"Error in calculating panels and energy: {str(e)}"
# Estimate yearly savings
def estimate_savings(total_energy_kwh, electricity_rate):
try:
yearly_energy = total_energy_kwh * 365
savings = yearly_energy * electricity_rate
return savings
except Exception as e:
return f"Error in estimating savings: {str(e)}"
# Forecast future solar energy production using LSTM model
def forecast_solar_energy(historical_data):
try:
# Clean the input data
historical_data_clean = historical_data.replace(';', ',').strip()
data_list = [float(x) for x in historical_data_clean.split(',') if x.strip()]
# Ensure the correct shape (1, 43, 7)
if len(data_list) != 43 * 7:
return "Error: Input data length does not match expected size"
sequence = np.array(data_list).reshape((1, 43, 7))
predicted_energy = model.predict(sequence)
predicted_value = float(predicted_energy[0][0])
return f"{predicted_value:.2f} kWh"
except ValueError as e:
return f"Error: Could not convert prediction to float - {str(e)}"
except Exception as e:
return f"Error in forecasting: {str(e)}"
# Read and preprocess CSV data for prediction
# Read and preprocess CSV data for prediction
def preprocess_csv_for_prediction(csv_file):
try:
# Load the dataset
data = pd.read_csv(csv_file.name)
# Validate column names
expected_columns = ['Month', 'Hour', 'Irradiance(W/m^2)', 'Latitude', 'Longitude',
'Panel_Capacity(W)', 'Panel_Efficiency', 'Wind_Speed(km/h)',
'Cloud_Cover(%)', 'temperature (°f)']
if not all(col in data.columns for col in expected_columns):
return f"Error: Missing expected columns. Required: {expected_columns}"
# Ensure columns with string values like 'Month' are removed or processed
data = data[expected_columns]
# Convert all non-numeric columns to numeric (handling errors where conversion is not possible)
data = data.apply(pd.to_numeric, errors='coerce')
# Handle any missing values (NaNs)
data.fillna(0, inplace=True)
# Select the relevant last row for prediction
last_row = data.tail(1)
# Reshape the data to match the model's input shape
sequence = last_row.values.astype(np.float32)
sequence = sequence.reshape((1, 1, 43)) # (batch_size, time_step, features)
return sequence
except Exception as e:
return f"Error in preprocessing CSV: {str(e)}"
# Function to process image and forecast energy using CSV file
# Function to process image and forecast energy using CSV file
def process_image_and_forecast(image, min_area, pixel_area, clip_limit, tile_size, panel_type,
panel_length, panel_width, irradiance, electricity_rate, historical_data_csv):
try:
# Process the uploaded image
if image is None:
return None, "Error: No image provided."
preprocessed = preprocess_image(image, clip_limit, tile_size)
roof_contour = find_roof_contour(preprocessed, min_area)
roof_area = calculate_roof_area(roof_contour, pixel_area)
# Calculate panels, energy, and cost
num_panels, total_energy_kwh, total_cost_inr = calculate_panels_and_energy(
roof_area, panel_length, panel_width, panel_type, irradiance
)
yearly_savings = estimate_savings(total_energy_kwh, electricity_rate)
# Forecast energy using the CSV data
forecast_text = ""
if historical_data_csv:
sequence = preprocess_csv_for_prediction(historical_data_csv)
if isinstance(sequence, str): # Handle errors during preprocessing
return image, sequence
# Predict energy output
predicted_energy = model.predict(sequence)
forecast_text = f"Predicted Energy Output for Next Day: {predicted_energy[0][0]:.2f} kWh"
# Draw the roof contour on the image
if roof_contour is not None:
cv2.drawContours(image, [roof_contour], -1, (0, 255, 0), 2)
# Compile results
result_text = (
f"Roof Area: {roof_area:.2f} sq.m | Panels: {num_panels} | "
f"Energy Output: {total_energy_kwh:.2f} kWh | Cost: ₹{total_cost_inr:.2f} | "
f"Yearly Savings: ₹{yearly_savings:.2f}\n{forecast_text}"
)
return image, result_text
except Exception as e:
return image, f"Error: {str(e)}"
# Gradio Interface
interface = gr.Interface(
fn=process_image_and_forecast,
inputs=[
gr.Image(type="numpy", label="Upload Image"),
gr.Slider(500, 5000, value=1000, step=100, label="Minimum Contour Area"),
gr.Number(value=0.1, label="Pixel to Area Conversion (sq. meters)"),
gr.Slider(1.0, 5.0, value=2.0, step=0.1, label="CLAHE Clip Limit"),
gr.Slider(2, 16, value=8, step=1, label="CLAHE Tile Grid Size"),
gr.Dropdown(list(PANEL_TYPES.keys()), label="Panel Type"),
gr.Number(value=1.6, label="Panel Length (m)"),
gr.Number(value=1.0, label="Panel Width (m)"),
gr.Number(value=1000, label="Average Solar Irradiance (W/m²)"),
gr.Number(value=0.15, label="Electricity Rate (INR/kWh)"),
gr.File(label="Upload CSV for Prediction (Optional)")
],
outputs=[
gr.Image(label="Processed Image with Roof Contour"),
gr.Textbox(label="Results")
],
live=True
)
# Launch the interface
interface.launch()