|
import cv2 |
|
import numpy as np |
|
import gradio as gr |
|
import os |
|
import tensorflow as tf |
|
import pandas as pd |
|
|
|
|
|
os.environ["CUDA_VISIBLE_DEVICES"] = "-1" |
|
|
|
|
|
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} |
|
} |
|
|
|
|
|
AVERAGE_SUNLIGHT_HOURS_PER_DAY = 5 |
|
USD_TO_INR_CONVERSION_RATE = 83 |
|
|
|
|
|
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) |
|
|
|
|
|
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)}" |
|
|
|
|
|
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)}" |
|
|
|
|
|
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)}" |
|
|
|
|
|
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 |
|
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)}" |
|
|
|
|
|
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)}" |
|
|
|
|
|
def forecast_solar_energy(historical_data): |
|
try: |
|
|
|
historical_data_clean = historical_data.replace(';', ',').strip() |
|
data_list = [float(x) for x in historical_data_clean.split(',') if x.strip()] |
|
|
|
|
|
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)}" |
|
|
|
|
|
|
|
def preprocess_csv_for_prediction(csv_file): |
|
try: |
|
|
|
data = pd.read_csv(csv_file.name) |
|
|
|
|
|
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}" |
|
|
|
|
|
data = data[expected_columns] |
|
|
|
|
|
data = data.apply(pd.to_numeric, errors='coerce') |
|
|
|
|
|
data.fillna(0, inplace=True) |
|
|
|
|
|
last_row = data.tail(1) |
|
|
|
|
|
sequence = last_row.values.astype(np.float32) |
|
sequence = sequence.reshape((1, 1, 43)) |
|
|
|
return sequence |
|
except Exception as e: |
|
return f"Error in preprocessing CSV: {str(e)}" |
|
|
|
|
|
|
|
|
|
|
|
|
|
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: |
|
|
|
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) |
|
|
|
|
|
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_text = "" |
|
if historical_data_csv: |
|
sequence = preprocess_csv_for_prediction(historical_data_csv) |
|
if isinstance(sequence, str): |
|
return image, sequence |
|
|
|
|
|
predicted_energy = model.predict(sequence) |
|
forecast_text = f"Predicted Energy Output for Next Day: {predicted_energy[0][0]:.2f} kWh" |
|
|
|
|
|
if roof_contour is not None: |
|
cv2.drawContours(image, [roof_contour], -1, (0, 255, 0), 2) |
|
|
|
|
|
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)}" |
|
|
|
|
|
|
|
|
|
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 |
|
) |
|
|
|
|
|
interface.launch() |
|
|