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()