File size: 6,747 Bytes
27f68f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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

# Load the pre-trained model
loaded_model = load_model('solar_irradiance_model.keras')

# Load the dataset for encoder and scaler setup
data = pd.read_csv('Solar_Irradiance.csv')
data['Latitude'] = data['Latitude'].str.rstrip('°').astype(float)
data['Longitude'] = data['Longitude'].str.rstrip('°').astype(float)

# Features and encoder/scaler setup
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)

# Shadow Removal Function
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

# Preprocess Image with Watershed Algorithm
def apply_watershed(image):
    # Step 1: Remove shadows
    shadow_free_image = remove_shadows(image)

    # Step 2: Denoise the shadow-free image
    denoised = cv2.fastNlMeansDenoisingColored(shadow_free_image, None, 10, 10, 7, 21)
    gray = cv2.cvtColor(denoised, cv2.COLOR_BGR2GRAY)

    # Step 3: Thresholding
    _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # Step 4: Morphological operations to get foreground and background
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    sure_bg = cv2.dilate(binary, kernel, iterations=3)
    sure_fg = cv2.erode(binary, kernel, iterations=3)
    unknown = cv2.subtract(sure_bg, sure_fg)

    # Step 5: Marker labelling
    _, markers = cv2.connectedComponents(sure_fg)
    markers = markers + 1
    markers[unknown == 255] = 0

    # Step 6: Apply Watershed
    markers = cv2.watershed(image, markers)
    segmented = np.zeros_like(image)
    segmented[markers > 1] = image[markers > 1]

    return segmented, markers

# Calculate Usable Roof Area
# Calculate Usable Roof Area
def find_usable_area(image, min_area, panel_area):
    segmented_image, markers = apply_watershed(image)
    gray = cv2.cvtColor(segmented_image, cv2.COLOR_BGR2GRAY)
    contours, _ = cv2.findContours(gray, 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
            # Mark usable area in green
            cv2.drawContours(output_image, [contour], -1, (0, 255, 0), 3)
        else:
            # Mark unusable area in red
            cv2.drawContours(output_image, [contour], -1, (0, 0, 255), 3)

    num_panels = usable_area // panel_area  # Number of panels that fit in the usable area
    return usable_area, int(num_panels), output_image


# Predict Irradiance
def predict_irradiance(month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature):
    encoded_month_hour = encoder.transform([[month, hour]])
    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)

# Main Function
def calculate_solar_energy(image, month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature):
    panel_area = 7 # m² per panel
    min_area = 1000  # Minimum contour area to consider for valid roof

    # Step 1: Find usable roof area from segmented image
    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

    # Step 2: Predict irradiance for the given environmental conditions
    irradiance = predict_irradiance(month, hour, latitude, longitude, panel_capacity, panel_efficiency, wind_speed, cloud_cover, temperature)

    # Step 3: Calculate potential energy and cost based on panels and irradiance
    potential_energy = num_panels * panel_area * irradiance * panel_efficiency  # in Watts
    potential_energy_kwh = potential_energy / 1000  # Convert to kWh
    cost_per_panel = 1000  # Rs. per panel
    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

# Gradio Interface function
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

# Gradio interface setup
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()