Harsh-7300 commited on
Commit
b5c1c8a
·
verified ·
1 Parent(s): bb8e815

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -57
app.py CHANGED
@@ -1,13 +1,15 @@
 
1
  import cv2
2
  import numpy as np
 
3
 
4
- def process_rooftop_image(image_path, geographic_bounds):
5
  """
6
- Process the rooftop image to detect rooftops, exclude shadows,
7
  and calculate usable area for solar panels.
8
 
9
  Parameters:
10
- image_path (str): Path to the input image (PNG or JPG).
11
  geographic_bounds (dict): Geographic bounds with the following keys:
12
  - lat_min, lat_max, lon_min, lon_max (floats): Latitude and longitude bounds of the image.
13
 
@@ -15,45 +17,42 @@ def process_rooftop_image(image_path, geographic_bounds):
15
  final_image (numpy array): Image with predicted boundaries and excluded shadows.
16
  usable_area (float): Computed rooftop area usable for solar panels in square meters.
17
  """
18
- # Load the image
19
- image = cv2.imread(image_path)
20
- if image is None:
21
- raise FileNotFoundError("Image file not found. Please check the path.")
22
-
23
- # Step 1: Convert to grayscale for processing
24
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
25
 
26
- # Step 2: Apply Gaussian Blur to reduce noise
27
  blurred = cv2.GaussianBlur(gray, (5, 5), 0)
28
 
29
- # Step 3: Edge detection (Canny)
 
 
 
30
  edges = cv2.Canny(blurred, 50, 150)
31
 
32
- # Step 4: Morphological operations to close gaps in edges
33
  kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
34
  closed_edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
35
 
36
- # Step 5: Find contours of the rooftop
37
  contours, _ = cv2.findContours(closed_edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
38
 
39
- # Create a blank mask for shadow removal
40
- mask = np.zeros_like(gray)
41
 
42
  for contour in contours:
43
  # Approximate the contour and filter out unwanted small areas
44
  approx = cv2.approxPolyDP(contour, 0.02 * cv2.arcLength(contour, True), True)
45
  area = cv2.contourArea(approx)
46
  if area > 500: # Minimum area threshold to remove noise
47
- cv2.drawContours(mask, [approx], -1, 255, -1)
48
 
49
- # Step 6: Exclude shadows (thresholding)
50
- shadow_removed = cv2.bitwise_and(gray, gray, mask=mask)
51
- _, thresholded = cv2.threshold(shadow_removed, 120, 255, cv2.THRESH_BINARY)
52
 
53
- # Step 7: Calculate the area in pixels
54
- pixel_area = np.sum(thresholded > 0)
55
 
56
- # Step 8: Convert pixels to real-world area
57
  lat_min, lat_max, lon_min, lon_max = (
58
  geographic_bounds['lat_min'],
59
  geographic_bounds['lat_max'],
@@ -72,44 +71,45 @@ def process_rooftop_image(image_path, geographic_bounds):
72
  conversion_factor = (lat_conversion * lon_conversion) / (image.shape[0] * image.shape[1])
73
  usable_area = pixel_area * conversion_factor # in square meters
74
 
75
- # Step 9: Overlay contours on the original image
76
  final_image = image.copy()
77
  cv2.drawContours(final_image, contours, -1, (0, 255, 0), 2)
78
 
79
  return final_image, usable_area
80
 
81
 
82
- if __name__ == "__main__":
83
- # Prompt user for inputs
84
- image_path = input("Enter the path to the rooftop image (PNG or JPG): ")
85
- print("Enter the geographic bounds of the image:")
86
- lat_min = float(input("Latitude Min: "))
87
- lat_max = float(input("Latitude Max: "))
88
- lon_min = float(input("Longitude Min: "))
89
- lon_max = float(input("Longitude Max: "))
90
-
91
- geographic_bounds = {
92
- 'lat_min': lat_min,
93
- 'lat_max': lat_max,
94
- 'lon_min': lon_min,
95
- 'lon_max': lon_max,
96
- }
97
-
98
- try:
99
- # Process the image and calculate the usable area
100
- final_image, calculated_area = process_rooftop_image(image_path, geographic_bounds)
101
-
102
- # Save and display results
103
- output_path = "output_rooftop_with_boundaries.jpg"
104
- cv2.imwrite(output_path, final_image)
105
-
106
- print(f"Usable Rooftop Area for Solar Panels: {calculated_area:.2f} square meters")
107
- print(f"Processed image saved to: {output_path}")
108
-
109
- # Display the final image with detected boundaries
110
- cv2.imshow("Processed Rooftop", final_image)
111
- cv2.waitKey(0)
112
- cv2.destroyAllWindows()
113
-
114
- except Exception as e:
115
- print(f"Error: {e}")
 
 
1
+ import streamlit as st
2
  import cv2
3
  import numpy as np
4
+ from PIL import Image
5
 
6
+ def process_rooftop_image(image, geographic_bounds):
7
  """
8
+ Process the rooftop image to detect rooftops, exclude shadows and waste areas,
9
  and calculate usable area for solar panels.
10
 
11
  Parameters:
12
+ image (numpy array): Input image as a NumPy array.
13
  geographic_bounds (dict): Geographic bounds with the following keys:
14
  - lat_min, lat_max, lon_min, lon_max (floats): Latitude and longitude bounds of the image.
15
 
 
17
  final_image (numpy array): Image with predicted boundaries and excluded shadows.
18
  usable_area (float): Computed rooftop area usable for solar panels in square meters.
19
  """
20
+ # Convert the image to grayscale
 
 
 
 
 
21
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
22
 
23
+ # Apply Gaussian Blur to reduce noise
24
  blurred = cv2.GaussianBlur(gray, (5, 5), 0)
25
 
26
+ # Shadow detection (thresholding for dark regions)
27
+ _, shadow_mask = cv2.threshold(blurred, 80, 255, cv2.THRESH_BINARY_INV)
28
+
29
+ # Edge detection (Canny)
30
  edges = cv2.Canny(blurred, 50, 150)
31
 
32
+ # Morphological operations to close gaps in edges
33
  kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
34
  closed_edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
35
 
36
+ # Find contours of the rooftop
37
  contours, _ = cv2.findContours(closed_edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
38
 
39
+ # Create a blank mask for the rooftop area
40
+ rooftop_mask = np.zeros_like(gray)
41
 
42
  for contour in contours:
43
  # Approximate the contour and filter out unwanted small areas
44
  approx = cv2.approxPolyDP(contour, 0.02 * cv2.arcLength(contour, True), True)
45
  area = cv2.contourArea(approx)
46
  if area > 500: # Minimum area threshold to remove noise
47
+ cv2.drawContours(rooftop_mask, [approx], -1, 255, -1)
48
 
49
+ # Exclude shadows from the rooftop mask
50
+ final_mask = cv2.bitwise_and(rooftop_mask, cv2.bitwise_not(shadow_mask))
 
51
 
52
+ # Calculate the area in pixels
53
+ pixel_area = np.sum(final_mask > 0)
54
 
55
+ # Convert pixels to real-world area
56
  lat_min, lat_max, lon_min, lon_max = (
57
  geographic_bounds['lat_min'],
58
  geographic_bounds['lat_max'],
 
71
  conversion_factor = (lat_conversion * lon_conversion) / (image.shape[0] * image.shape[1])
72
  usable_area = pixel_area * conversion_factor # in square meters
73
 
74
+ # Overlay contours on the original image
75
  final_image = image.copy()
76
  cv2.drawContours(final_image, contours, -1, (0, 255, 0), 2)
77
 
78
  return final_image, usable_area
79
 
80
 
81
+ # Streamlit Interface
82
+ st.title("Rooftop Usable Area for Solar Panels")
83
+ st.write("Upload a rooftop image and provide geographic bounds to calculate the usable area for solar panels.")
84
+
85
+ # File uploader for the image
86
+ uploaded_file = st.file_uploader("Upload an image (PNG or JPG)", type=["png", "jpg", "jpeg"])
87
+
88
+ # Input fields for geographic bounds
89
+ lat_min = st.number_input("Latitude Min", value=0.0, step=0.0001)
90
+ lat_max = st.number_input("Latitude Max", value=0.0, step=0.0001)
91
+ lon_min = st.number_input("Longitude Min", value=0.0, step=0.0001)
92
+ lon_max = st.number_input("Longitude Max", value=0.0, step=0.0001)
93
+
94
+ # Button to process the image
95
+ if st.button("Calculate Usable Area"):
96
+ if uploaded_file is not None:
97
+ # Read the uploaded image
98
+ image = np.array(Image.open(uploaded_file).convert("RGB")) # Convert PIL image to NumPy array
99
+ image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) # Convert RGB to BGR for OpenCV
100
+
101
+ geographic_bounds = {
102
+ 'lat_min': lat_min,
103
+ 'lat_max': lat_max,
104
+ 'lon_min': lon_min,
105
+ 'lon_max': lon_max,
106
+ }
107
+
108
+ # Process the image
109
+ final_image, usable_area = process_rooftop_image(image, geographic_bounds)
110
+
111
+ # Display results
112
+ st.image(cv2.cvtColor(final_image, cv2.COLOR_BGR2RGB), caption="Processed Image with Boundaries")
113
+ st.write(f"Usable Rooftop Area for Solar Panels (excluding shadows): **{usable_area:.2f} square meters**")
114
+ else:
115
+ st.error("Please upload an image to proceed.")