|
|
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 |
|
|
|
|
|
|
|
|
loaded_model = load_model('solar_irradiance_model.keras') |
|
|
|
|
|
|
|
|
data = pd.read_csv('Solar_Irradiance.csv') |
|
|
data['Latitude'] = data['Latitude'].str.rstrip('°').astype(float) |
|
|
data['Longitude'] = data['Longitude'].str.rstrip('°').astype(float) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
def apply_canny_edge(image): |
|
|
|
|
|
shadow_free_image = remove_shadows(image) |
|
|
|
|
|
|
|
|
gray = cv2.cvtColor(shadow_free_image, cv2.COLOR_BGR2GRAY) |
|
|
|
|
|
|
|
|
edges = cv2.Canny(gray, 100, 200) |
|
|
|
|
|
|
|
|
kernel = np.ones((5, 5), np.uint8) |
|
|
dilated_edges = cv2.dilate(edges, kernel, iterations=2) |
|
|
|
|
|
return dilated_edges |
|
|
|
|
|
|
|
|
def find_usable_area(image, min_area, panel_area): |
|
|
edges = apply_canny_edge(image) |
|
|
|
|
|
|
|
|
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) |
|
|
|
|
|
usable_area = 0 |
|
|
output_image = image.copy() |
|
|
|
|
|
for contour in contours: |
|
|
area = cv2.contourArea(contour) |
|
|
if area >= min_area: |
|
|
usable_area += area |
|
|
cv2.drawContours(output_image, [contour], -1, (0, 255, 0), 3) |
|
|
else: |
|
|
cv2.drawContours(output_image, [contour], -1, (0, 0, 255), 3) |
|
|
|
|
|
usable_area /= 100 |
|
|
num_panels = usable_area // panel_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): |
|
|
|
|
|
print(f"Input month: {month}, Input hour: {hour}") |
|
|
|
|
|
|
|
|
encoded_month_hour = encoder.transform([[month, hour]]) |
|
|
|
|
|
|
|
|
print(f"Encoded month-hour features: {encoded_month_hour.shape}") |
|
|
|
|
|
|
|
|
scaled_features = scaler.transform([[latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature]]) |
|
|
|
|
|
|
|
|
processed_features = np.concatenate((encoded_month_hour, scaled_features), axis=1) |
|
|
|
|
|
|
|
|
reshaped_features = np.reshape(processed_features, (1, 1, processed_features.shape[1])) |
|
|
|
|
|
|
|
|
predicted_irradiance = loaded_model.predict(reshaped_features) |
|
|
|
|
|
|
|
|
return max(predicted_irradiance[0][0], 0.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def calculate_solar_energy(image, month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature): |
|
|
panel_area = 22 |
|
|
min_area = 5000 |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
irradiance = predict_irradiance(month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature) |
|
|
|
|
|
|
|
|
potential_energy = num_panels * panel_area * irradiance * panel_efficiency |
|
|
potential_energy_kwh = potential_energy / 1000 |
|
|
cost_per_panel = 1111 |
|
|
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 |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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() |