|
import cv2 |
|
import numpy as np |
|
import gradio as gr |
|
import tensorflow as tf |
|
import matplotlib.pyplot as plt |
|
from mpl_toolkits.mplot3d import Axes3D |
|
|
|
|
|
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 = tf.keras.models.load_model('solar_energy_forecast_model.h5') |
|
|
|
|
|
def preprocess_image(image, clip_limit=2.0, tile_size=8): |
|
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 |
|
|
|
|
|
def find_roof_contour(mask, min_area=1000): |
|
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) |
|
|
|
|
|
def calculate_roof_area(contour, pixel_area=0.1): |
|
if contour is None: |
|
return 0 |
|
return cv2.contourArea(contour) * pixel_area |
|
|
|
|
|
def calculate_panels_and_energy(roof_area, panel_length, panel_width, panel_type, irradiance): |
|
panel_area = panel_length * panel_width |
|
panel_info = PANEL_TYPES[panel_type] |
|
panel_efficiency = panel_info["efficiency"] |
|
|
|
|
|
num_panels = int(roof_area / panel_area) |
|
|
|
|
|
energy_per_panel = irradiance * panel_area * panel_efficiency |
|
total_energy_output = num_panels * energy_per_panel * AVERAGE_SUNLIGHT_HOURS_PER_DAY |
|
total_energy_kwh = total_energy_output / 1000 |
|
|
|
|
|
cost_per_panel = panel_area * panel_info["cost_per_watt"] * 1000 |
|
total_cost_usd = num_panels * cost_per_panel |
|
|
|
|
|
total_cost_inr = total_cost_usd * USD_TO_INR_CONVERSION_RATE |
|
|
|
return num_panels, total_energy_kwh, total_cost_inr |
|
|
|
|
|
def estimate_savings(total_energy_kwh, electricity_rate): |
|
yearly_energy = total_energy_kwh * 365 |
|
savings = yearly_energy * electricity_rate |
|
return savings |
|
|
|
|
|
def forecast_solar_energy(historical_data): |
|
sequence = np.array(historical_data).reshape((1, len(historical_data), 1)) |
|
predicted_energy = model.predict(sequence) |
|
return predicted_energy[0][0] |
|
|
|
|
|
def visualize_roof_panels(roof_area, panel_length, panel_width, num_panels): |
|
panel_area = panel_length * panel_width |
|
rows = int(np.sqrt(roof_area / panel_area)) |
|
cols = num_panels // rows if rows > 0 else 1 |
|
|
|
fig = plt.figure(figsize=(8, 6)) |
|
ax = fig.add_subplot(111, projection='3d') |
|
ax.set_title("3D Visualization of Solar Panels") |
|
ax.set_xlabel("X") |
|
ax.set_ylabel("Y") |
|
ax.set_zlabel("Z") |
|
|
|
for i in range(rows): |
|
for j in range(cols): |
|
x = [i, i, i + panel_length, i + panel_length] |
|
y = [j, j + panel_width, j + panel_width, j] |
|
z = [0, 0, 0, 0] |
|
ax.plot_trisurf(x, y, z, color='orange', edgecolor='black') |
|
|
|
plt.show() |
|
return fig |
|
|
|
|
|
def process_image_and_forecast(image, min_area, pixel_area, clip_limit, tile_size, panel_type, panel_length, panel_width, irradiance, electricity_rate, historical_energy_data): |
|
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) |
|
|
|
|
|
try: |
|
historical_data = list(map(float, historical_energy_data.split(','))) |
|
predicted_energy = forecast_solar_energy(historical_data) |
|
forecast_text = f"Predicted Energy Output for Next Day: {predicted_energy:.2f} kWh" |
|
except Exception as e: |
|
forecast_text = f"Error in forecasting: {str(e)}" |
|
|
|
|
|
if roof_contour is not None: |
|
cv2.drawContours(image, [roof_contour], -1, (0, 255, 0), 2) |
|
|
|
|
|
fig = visualize_roof_panels(roof_area, panel_length, panel_width, num_panels) |
|
|
|
|
|
result_text = f"Roof Area: {roof_area:.2f} sq.m | Panels: {num_panels} | Energy Output: {total_energy_kwh:.2f} kWh | Cost: ₹{total_cost_inr:.2f} | Yearly Savings: ₹{yearly_savings:.2f}\n{forecast_text}" |
|
|
|
return image, result_text, fig |
|
|
|
|
|
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 (₹/kWh)"), |
|
gr.Textbox(label="Enter Historical Energy Production (last 7 days in kWh, separated by commas)", lines=2) |
|
], |
|
outputs=[ |
|
gr.Image(type="numpy", label="Processed Image with Contours"), |
|
gr.Textbox(label="Results: Roof Area, Panels, Energy, Cost, Savings, and Predictions"), |
|
gr.Plot(label="3D Visualization of Panels") |
|
], |
|
title="Advanced Solar Panel Placement Estimator with Energy Forecasting", |
|
description="Upload an image and adjust the parameters to estimate the roof area, panel placement, energy output, cost, and savings. Forecast future energy output using historical data." |
|
) |
|
|
|
if __name__ == '__main__': |
|
interface.launch() |
|
|