phyloforfun commited on
Commit
007b2fe
·
1 Parent(s): 5a0ce16
Files changed (1) hide show
  1. app.py +102 -124
app.py CHANGED
@@ -89,31 +89,76 @@ def get_points_from_contours(contours):
89
  return centroids
90
 
91
  # Function to display the image with the selected quadrilateral superimposed
92
- def display_image_with_quadrilateral(image, points):
93
- # Make a copy of the image to draw on
94
- overlay_image = image.copy()
95
 
96
- # Draw the quadrilateral
97
- cv2.polylines(overlay_image, [np.array(points)], isClosed=True, color=(0, 255, 0), thickness=3)
98
 
99
- # Display the image with the quadrilateral
100
- st.image(overlay_image, caption="Quadrilateral on Image", use_column_width='auto')
101
 
102
- # Function to update displayed quadrilateral based on selected index
103
- def update_displayed_quadrilateral(index, point_combinations, base_image_path):
104
- # Extract the four points of the current quadrilateral
105
- quad_points = get_points_from_contours(point_combinations[index])
106
 
107
- # Read the base image
108
- base_image = cv2.imread(base_image_path)
109
 
110
- # If the image is not found, handle the error appropriately
111
- if base_image is None:
112
- st.error("Failed to load image.")
113
- return
114
 
115
- # Display the image with the selected quadrilateral
116
- display_image_with_quadrilateral(base_image, quad_points)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
 
118
  def process_image(image_path, flag_lower, flag_upper, plant_lower, plant_upper, loc):
119
  with loc:
@@ -158,16 +203,15 @@ def process_image(image_path, flag_lower, flag_upper, plant_lower, plant_upper,
158
  significant_contours = [cnt for cnt in sorted_contours if cv2.contourArea(cnt) > MIN_AREA]
159
 
160
  # Logic to handle cases where there are more than 4 significant contours
161
- centroids = []
162
  if len(significant_contours) < 4:
 
163
  return None, None, None, None, None, None, None, None, None, None
164
  elif len(significant_contours) > 4:
165
  # Create all possible combinations of four points
166
  point_combinations = list(itertools.combinations(significant_contours, 4))
167
-
168
- # Placeholder for quadrilateral indices
169
- selected_quad_index = 0
170
-
171
  # Function to update displayed quadrilateral based on selected index
172
  def update_displayed_quadrilateral(index):
173
  # Extract the four points of the current quadrilateral
@@ -188,110 +232,44 @@ def process_image(image_path, flag_lower, flag_upper, plant_lower, plant_upper,
188
  if st.button('Next'):
189
  selected_quad_index = min(selected_quad_index + 1, len(point_combinations) - 1)
190
  centroids = update_displayed_quadrilateral(selected_quad_index)
191
- #############
192
- # Compute the centroid of the centroids
193
- centroid_x = sum(x for x, y in centroids) / 4
194
- centroid_y = sum(y for x, y in centroids) / 4
195
-
196
- # Sort the centroids
197
- centroids.sort(key=lambda point: (-math.atan2(point[1] - centroid_y, point[0] - centroid_x)) % (2 * np.pi))
198
-
199
- # Create a polygon mask using the sorted centroids
200
- poly_mask = np.zeros_like(flag_mask)
201
- cv2.fillPoly(poly_mask, [np.array(centroids)], 255)
202
-
203
- # Mask the plant_mask with poly_mask
204
- mask_plant_plot = cv2.bitwise_and(plant_mask, plant_mask, mask=poly_mask)
205
-
206
- # Count the number of black pixels inside the quadrilateral
207
- total_pixels_in_quad = np.prod(poly_mask.shape)
208
- white_pixels_in_quad = np.sum(poly_mask == 255)
209
- black_pixels_in_quad = total_pixels_in_quad - white_pixels_in_quad
210
-
211
- # Extract the RGB pixels from the original image using the mask_plant_plot
212
- plant_rgb = cv2.bitwise_and(img, img, mask=mask_plant_plot)
213
-
214
- # Draw the bounding quadrilateral
215
- plot_rgb = plant_rgb.copy()
216
- for i in range(4):
217
- cv2.line(plot_rgb, centroids[i], centroids[(i+1)%4], (0, 0, 255), 3)
218
-
219
- # Convert the masks to RGB for visualization
220
- flag_mask_rgb = cv2.cvtColor(flag_mask, cv2.COLOR_GRAY2RGB)
221
- orange_color = [255, 165, 0] # RGB value for orange
222
- flag_mask_rgb[np.any(flag_mask_rgb != [0, 0, 0], axis=-1)] = orange_color
223
-
224
- plant_mask_rgb = cv2.cvtColor(plant_mask, cv2.COLOR_GRAY2RGB)
225
- mask_plant_plot_rgb = cv2.cvtColor(mask_plant_plot, cv2.COLOR_GRAY2RGB)
226
- bright_green_color = [0, 255, 0]
227
- plant_mask_rgb[np.any(plant_mask_rgb != [0, 0, 0], axis=-1)] = bright_green_color
228
- mask_plant_plot_rgb[np.any(mask_plant_plot_rgb != [0, 0, 0], axis=-1)] = bright_green_color
229
-
230
- # Warp the images
231
- plant_rgb_warp = warp_image(plant_rgb, centroids)
232
- plant_mask_warp = warp_image(mask_plant_plot_rgb, centroids)
233
 
234
- return flag_mask_rgb, pla
235
 
236
- # If there are exactly 4 largest contours, proceed with existing logic
237
- elif len(significant_contours) == 4:
238
- # Create a new mask with only the largest 4 contours
239
- largest_4_flag_mask = np.zeros_like(flag_mask)
240
- cv2.drawContours(largest_4_flag_mask, sorted_contours, -1, (255), thickness=cv2.FILLED)
241
-
242
- # Compute the centroid for each contour
243
- for contour in sorted_contours:
244
- M = cv2.moments(contour)
245
- if M["m00"] != 0:
246
- cx = int(M["m10"] / M["m00"])
247
- cy = int(M["m01"] / M["m00"])
248
- else:
249
- cx, cy = 0, 0
250
- centroids.append((cx, cy))
251
- ########################
252
- # Compute the centroid of the centroids
253
- centroid_x = sum(x for x, y in centroids) / 4
254
- centroid_y = sum(y for x, y in centroids) / 4
255
-
256
- # Sort the centroids
257
- centroids.sort(key=lambda point: (-math.atan2(point[1] - centroid_y, point[0] - centroid_x)) % (2 * np.pi))
258
-
259
- # Create a polygon mask using the sorted centroids
260
- poly_mask = np.zeros_like(flag_mask)
261
- cv2.fillPoly(poly_mask, [np.array(centroids)], 255)
262
-
263
- # Mask the plant_mask with poly_mask
264
- mask_plant_plot = cv2.bitwise_and(plant_mask, plant_mask, mask=poly_mask)
265
 
266
- # Count the number of black pixels inside the quadrilateral
267
- total_pixels_in_quad = np.prod(poly_mask.shape)
268
- white_pixels_in_quad = np.sum(poly_mask == 255)
269
- black_pixels_in_quad = total_pixels_in_quad - white_pixels_in_quad
270
-
271
- # Extract the RGB pixels from the original image using the mask_plant_plot
272
- plant_rgb = cv2.bitwise_and(img, img, mask=mask_plant_plot)
273
-
274
- # Draw the bounding quadrilateral
275
- plot_rgb = plant_rgb.copy()
276
- for i in range(4):
277
- cv2.line(plot_rgb, centroids[i], centroids[(i+1)%4], (0, 0, 255), 3)
278
-
279
- # Convert the masks to RGB for visualization
280
- flag_mask_rgb = cv2.cvtColor(flag_mask, cv2.COLOR_GRAY2RGB)
281
- orange_color = [255, 165, 0] # RGB value for orange
282
- flag_mask_rgb[np.any(flag_mask_rgb != [0, 0, 0], axis=-1)] = orange_color
283
-
284
- plant_mask_rgb = cv2.cvtColor(plant_mask, cv2.COLOR_GRAY2RGB)
285
- mask_plant_plot_rgb = cv2.cvtColor(mask_plant_plot, cv2.COLOR_GRAY2RGB)
286
- bright_green_color = [0, 255, 0]
287
- plant_mask_rgb[np.any(plant_mask_rgb != [0, 0, 0], axis=-1)] = bright_green_color
288
- mask_plant_plot_rgb[np.any(mask_plant_plot_rgb != [0, 0, 0], axis=-1)] = bright_green_color
289
-
290
- # Warp the images
291
- plant_rgb_warp = warp_image(plant_rgb, centroids)
292
- plant_mask_warp = warp_image(mask_plant_plot_rgb, centroids)
293
 
294
- return flag_mask_rgb, plant_mask_rgb, mask_plant_plot_rgb, plant_rgb, plot_rgb, plant_rgb_warp, plant_mask_warp, plant_mask, mask_plant_plot, black_pixels_in_quad
295
 
296
  def calculate_coverage(mask_plant_plot, plant_mask_warp, black_pixels_in_quad):
297
  # Calculate the percentage of white pixels for mask_plant_plot
 
89
  return centroids
90
 
91
  # Function to display the image with the selected quadrilateral superimposed
92
+ # def display_image_with_quadrilateral(image, points):
93
+ # # Make a copy of the image to draw on
94
+ # overlay_image = image.copy()
95
 
96
+ # # Draw the quadrilateral
97
+ # cv2.polylines(overlay_image, [np.array(points)], isClosed=True, color=(0, 255, 0), thickness=3)
98
 
99
+ # # Display the image with the quadrilateral
100
+ # st.image(overlay_image, caption="Quadrilateral on Image", use_column_width='auto')
101
 
102
+ # # Function to update displayed quadrilateral based on selected index
103
+ # def update_displayed_quadrilateral(index, point_combinations, base_image_path):
104
+ # # Extract the four points of the current quadrilateral
105
+ # quad_points = get_points_from_contours(point_combinations[index])
106
 
107
+ # # Read the base image
108
+ # base_image = cv2.imread(base_image_path)
109
 
110
+ # # If the image is not found, handle the error appropriately
111
+ # if base_image is None:
112
+ # st.error("Failed to load image.")
113
+ # return
114
 
115
+ # # Display the image with the selected quadrilateral
116
+ # display_image_with_quadrilateral(base_image, quad_points)
117
+
118
+ def get_centroid(contour):
119
+ # Compute the centroid for the contour
120
+ M = cv2.moments(contour)
121
+ if M["m00"] != 0:
122
+ return (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
123
+ return None
124
+
125
+ def get_points_from_contours(contours):
126
+ centroids = [get_centroid(contour) for contour in contours if get_centroid(contour) is not None]
127
+ return centroids
128
+
129
+ def sort_points_clockwise(centroids):
130
+ # Compute the centroid of the centroids
131
+ centroid_x = sum(x for x, y in centroids) / len(centroids)
132
+ centroid_y = sum(y for x, y in centroids) / len(centroids)
133
+ # Sort the centroids
134
+ centroids.sort(key=lambda point: (-math.atan2(point[1] - centroid_y, point[0] - centroid_x)) % (2 * np.pi))
135
+ return centroids
136
+
137
+ def create_polygon_mask(centroids, flag_mask_shape):
138
+ # Create a polygon mask using the sorted centroids
139
+ poly_mask = np.zeros(flag_mask_shape, dtype=np.uint8)
140
+ cv2.fillPoly(poly_mask, [np.array(centroids)], 255)
141
+ return poly_mask
142
+
143
+ def warp_and_display_images(img, centroids, base_name, flag_mask_rgb, plant_mask_rgb, mask_plant_plot_rgb):
144
+ # Warp the images
145
+ plant_rgb_warp = warp_image(img, centroids)
146
+ plant_mask_warp = warp_image(mask_plant_plot_rgb, centroids)
147
+
148
+ # Extract the RGB pixels from the original image using the mask_plant_plot
149
+ plant_rgb = cv2.bitwise_and(img, img, mask=create_polygon_mask(centroids, img.shape[:2]))
150
+
151
+ # Draw the bounding quadrilateral
152
+ plot_rgb = plant_rgb.copy()
153
+ for i in range(4):
154
+ cv2.line(plot_rgb, centroids[i], centroids[(i+1)%4], (0, 0, 255), 3)
155
+
156
+ # Display the images
157
+ st.image([flag_mask_rgb, plant_mask_rgb, mask_plant_plot_rgb, plot_rgb, plant_rgb_warp, plant_mask_warp],
158
+ caption=["Flag Mask", "Plant Mask", "Mask Plant Plot", "Plot RGB", "Plant RGB Warp", "Plant Mask Warp"],
159
+ use_column_width=True)
160
+
161
+ return plant_rgb, plot_rgb, plant_rgb_warp, plant_mask_warp
162
 
163
  def process_image(image_path, flag_lower, flag_upper, plant_lower, plant_upper, loc):
164
  with loc:
 
203
  significant_contours = [cnt for cnt in sorted_contours if cv2.contourArea(cnt) > MIN_AREA]
204
 
205
  # Logic to handle cases where there are more than 4 significant contours
 
206
  if len(significant_contours) < 4:
207
+ st.error("Not enough points to form a quadrilateral.")
208
  return None, None, None, None, None, None, None, None, None, None
209
  elif len(significant_contours) > 4:
210
  # Create all possible combinations of four points
211
  point_combinations = list(itertools.combinations(significant_contours, 4))
212
+ selected_quad_index = 0 # Placeholder for quadrilateral indices
213
+ centroids = get_points_from_contours(point_combinations[selected_quad_index])
214
+ centroids = sort_points_clockwise(centroids)
 
215
  # Function to update displayed quadrilateral based on selected index
216
  def update_displayed_quadrilateral(index):
217
  # Extract the four points of the current quadrilateral
 
232
  if st.button('Next'):
233
  selected_quad_index = min(selected_quad_index + 1, len(point_combinations) - 1)
234
  centroids = update_displayed_quadrilateral(selected_quad_index)
235
+ else:
236
+ centroids = get_points_from_contours(significant_contours)
237
+ centroids = sort_points_clockwise(centroids)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
 
239
+ poly_mask = create_polygon_mask(centroids, flag_mask.shape)
240
 
241
+ # Mask the plant_mask with poly_mask
242
+ mask_plant_plot = cv2.bitwise_and(plant_mask, plant_mask, mask=poly_mask)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
+ # Count the number of black pixels inside the quadrilateral
245
+ total_pixels_in_quad = np.prod(poly_mask.shape)
246
+ white_pixels_in_quad = np.sum(poly_mask == 255)
247
+ black_pixels_in_quad = total_pixels_in_quad - white_pixels_in_quad
248
+
249
+ # Extract the RGB pixels from the original image using the mask_plant_plot
250
+ plant_rgb = cv2.bitwise_and(img, img, mask=mask_plant_plot)
251
+
252
+ # Draw the bounding quadrilateral
253
+ plot_rgb = plant_rgb.copy()
254
+ for i in range(4):
255
+ cv2.line(plot_rgb, centroids[i], centroids[(i+1)%4], (0, 0, 255), 3)
256
+
257
+ # Convert the masks to RGB for visualization
258
+ flag_mask_rgb = cv2.cvtColor(flag_mask, cv2.COLOR_GRAY2RGB)
259
+ orange_color = [255, 165, 0] # RGB value for orange
260
+ flag_mask_rgb[np.any(flag_mask_rgb != [0, 0, 0], axis=-1)] = orange_color
261
+
262
+ plant_mask_rgb = cv2.cvtColor(plant_mask, cv2.COLOR_GRAY2RGB)
263
+ mask_plant_plot_rgb = cv2.cvtColor(mask_plant_plot, cv2.COLOR_GRAY2RGB)
264
+ bright_green_color = [0, 255, 0]
265
+ plant_mask_rgb[np.any(plant_mask_rgb != [0, 0, 0], axis=-1)] = bright_green_color
266
+ mask_plant_plot_rgb[np.any(mask_plant_plot_rgb != [0, 0, 0], axis=-1)] = bright_green_color
267
+
268
+ # Warp the images
269
+ plant_rgb_warp = warp_image(plant_rgb, centroids)
270
+ plant_mask_warp = warp_image(mask_plant_plot_rgb, centroids)
271
 
272
+ return flag_mask_rgb, plant_mask_rgb, mask_plant_plot_rgb, plant_rgb, plot_rgb, plant_rgb_warp, plant_mask_warp, plant_mask, mask_plant_plot, black_pixels_in_quad
273
 
274
  def calculate_coverage(mask_plant_plot, plant_mask_warp, black_pixels_in_quad):
275
  # Calculate the percentage of white pixels for mask_plant_plot