| import cv2 |
| import numpy as np |
| import math |
| import os |
| import networkx as nx |
|
|
| def pixelwise_areas(flood_output_img_pth, graph, connect_img_dir, print_tag = False): |
| |
| image = cv2.imread(flood_output_img_pth) |
| if image is None: |
| raise ValueError(f"Image not found at path: {flood_output_img_pth}") |
|
|
| |
| image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) |
|
|
| |
| height, width, _ = image.shape |
| if print_tag: |
| print(f"\nImage dimensions: {width}x{height}") |
|
|
| |
| colors = { |
| "room_pixels": (255, 204, 102), |
| "outdoor_pixels": (255, 102, 204), |
| "corridor_pixels": (178, 255, 102), |
| "unmarked_pixels": (255, 255, 255), |
| "wall_pixels": (0, 0, 0), |
| } |
|
|
| |
| threshold = 10 |
|
|
| |
| image_array = np.array(image) |
|
|
| |
| def create_mask(color): |
| lower_bound = np.maximum(np.array(color) - threshold, 0) |
| upper_bound = np.minimum(np.array(color) + threshold, 255) |
| return np.all((image_array >= lower_bound) & (image_array <= upper_bound), axis=-1) |
|
|
| room_mask = create_mask(colors["room_pixels"]) |
| outdoor_mask = create_mask(colors["outdoor_pixels"]) |
| corridor_mask = create_mask(colors["corridor_pixels"]) |
| unmarked_mask = create_mask(colors["unmarked_pixels"]) |
| wall_mask = create_mask(colors["wall_pixels"]) |
|
|
| |
| room_pixels = np.argwhere(room_mask).tolist() |
| outdoor_pixels = np.argwhere(outdoor_mask).tolist() |
| corridor_pixels = np.argwhere(corridor_mask).tolist() |
| unmarked_pixels = np.argwhere(unmarked_mask).tolist() |
| wall_pixels = np.argwhere(wall_mask).tolist() |
|
|
| |
| if print_tag: |
| print(f"Number of room pixels: {len(room_pixels)}") |
| print(f"Number of outdoor pixels: {len(outdoor_pixels)}") |
| print(f"Number of corridor pixels: {len(corridor_pixels)}") |
| print(f"Number of unmarked pixels: {len(unmarked_pixels)}") |
| print(f"Number of wall pixels: {len(wall_pixels)}") |
|
|
| |
| recreated_image = np.zeros_like(image_array) |
|
|
| |
| for y, x in room_pixels: |
| recreated_image[y, x] = colors["room_pixels"] |
| for y, x in outdoor_pixels: |
| recreated_image[y, x] = colors["outdoor_pixels"] |
| for y, x in corridor_pixels: |
| recreated_image[y, x] = colors["corridor_pixels"] |
| for y, x in unmarked_pixels: |
| recreated_image[y, x] = colors["unmarked_pixels"] |
| for y, x in wall_pixels: |
| recreated_image[y, x] = colors["wall_pixels"] |
| |
| |
| output_path = connect_img_dir + "/recreated_image.png" |
| recreated_image_bgr = cv2.cvtColor(recreated_image, cv2.COLOR_RGB2BGR) |
| cv2.imwrite(output_path, recreated_image_bgr) |
| print(f"Recreated Thresholded image saved to: {output_path}") |
|
|
| return room_pixels, outdoor_pixels, corridor_pixels, unmarked_pixels, wall_pixels, output_path |
|
|
| def classify_doors(image_path, door_bboxes, output_dir, print_tag=False): |
| |
| image = cv2.imread(image_path) |
| if image is None: |
| raise ValueError(f"Image not found at path: {image_path}") |
|
|
| |
| image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) |
|
|
| |
| unique_colors = np.unique(image.reshape(-1, image.shape[2]), axis=0) |
| if len(unique_colors) != 5: |
| raise ValueError(f"The image must contain exactly 5 unique colors, but it has {len(unique_colors)}.") |
|
|
| |
| doors_image = image.copy() |
| annotated_image = image.copy() |
|
|
| |
| exit_doors_bboxes = [] |
| corridor2corridor_doors_bboxes = [] |
| room2corridor_doors_bboxes = [] |
| room2room_doors_bboxes = [] |
| wardrobe_doors_bboxes = [] |
|
|
| |
| all_doors_color = (128, 128, 128) |
| red = (255, 0, 0) |
| green = (0, 255, 0) |
| blue = (0, 0, 255) |
| purple = (128, 0, 128) |
| yellow = (255, 255, 0) |
|
|
| |
| processed_bboxes = set() |
|
|
| |
| for bbox in door_bboxes: |
| x1, y1, x2, y2 = bbox |
|
|
| |
| x1, y1 = max(0, x1), max(0, y1) |
| x2, y2 = min(image.shape[1], x2), min(image.shape[0], y2) |
|
|
| |
| roi = image[y1:y2, x1:x2] |
|
|
| |
| if np.any(np.all(roi == [255, 102, 204], axis=-1)): |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), red, thickness=2) |
| exit_doors_bboxes.append([x1, y1, x2, y2]) |
| processed_bboxes.add(tuple(bbox)) |
| |
| elif np.any(np.all(roi == [178, 255, 102], axis=-1)): |
| if np.any(np.all(roi == [255, 204, 102], axis=-1)): |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), blue, thickness=2) |
| room2corridor_doors_bboxes.append([x1, y1, x2, y2]) |
| else: |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), green, thickness=2) |
| corridor2corridor_doors_bboxes.append([x1, y1, x2, y2]) |
| processed_bboxes.add(tuple(bbox)) |
|
|
| |
| for bbox in door_bboxes: |
| if tuple(bbox) not in processed_bboxes: |
| x1, y1, x2, y2 = bbox |
| x1, y1 = max(0, x1), max(0, y1) |
| x2, y2 = min(image.shape[1], x2), min(image.shape[0], y2) |
| roi = image[y1:y2, x1:x2] |
|
|
| |
| if not np.any(np.all(roi == [255, 255, 255], axis=-1)): |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), purple, thickness=2) |
| room2room_doors_bboxes.append([x1, y1, x2, y2]) |
| else: |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), yellow, thickness=2) |
| wardrobe_doors_bboxes.append([x1, y1, x2, y2]) |
|
|
| |
| for bbox in door_bboxes: |
| x1, y1, x2, y2 = bbox |
| cv2.rectangle(doors_image, (x1, y1), (x2, y2), all_doors_color, thickness=2) |
|
|
| |
| doors_image = cv2.cvtColor(doors_image, cv2.COLOR_RGB2BGR) |
| annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_RGB2BGR) |
|
|
| |
| os.makedirs(output_dir, exist_ok=True) |
|
|
| |
| doors_path = os.path.join(output_dir, "original_doors.png") |
| annotated_path = os.path.join(output_dir, "annotated_doors.png") |
| cv2.imwrite(doors_path, doors_image) |
| cv2.imwrite(annotated_path, annotated_image) |
|
|
| |
| total_doors = len(exit_doors_bboxes) + len(corridor2corridor_doors_bboxes) + len(room2corridor_doors_bboxes) + len(room2room_doors_bboxes) + len(wardrobe_doors_bboxes) |
| assert total_doors == len(door_bboxes), "The classified doors do not match the total input doors." |
| if print_tag: |
| print(f"{len(exit_doors_bboxes)}-exit doors found") |
| print(f"{len(corridor2corridor_doors_bboxes)}-corridor-to-corridor doors found") |
| print(f"{len(room2corridor_doors_bboxes)}-room-to-corridor doors found") |
| print(f"{len(room2room_doors_bboxes)}-room-to-room doors found") |
| print(f"{len(wardrobe_doors_bboxes)}-wardrobe doors found") |
|
|
| print(f"Doors pre-classification saved at {doors_path}") |
| print(f"Annotated doors saved at {annotated_path}") |
| return exit_doors_bboxes, corridor2corridor_doors_bboxes, room2corridor_doors_bboxes, room2room_doors_bboxes, wardrobe_doors_bboxes |
| |
|
|
| def plot_graph_door(image_path, graph, exit_dbboxes, corridor2corridor_dbboxes, room2corridor_dbboxes, room2room_dbboxes, connect_img_dir): |
| |
| image = cv2.imread(image_path) |
| if image is None: |
| raise ValueError(f"Image not found at path: {image_path}") |
|
|
| |
| print("Graph contains:") |
| print(f"Number of rooms: {len(graph.node_types['room'])}") |
| print(f"Number of doors: {len(graph.node_types['door'])}") |
| print(f"Number of corridors: {len(graph.node_types['corridor'])}") |
| print(f"Number of outsides: {len(graph.node_types['outside'])}") |
| |
| |
| image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) |
|
|
| |
| annotated_image = image_rgb.copy() |
|
|
| |
| room_color = (255, 0, 0) |
| door_color = (255, 182, 193) |
| corridor_color = (255, 165, 0) |
| outside_color = (157,163,0) |
| |
| exit_color = (0, 0, 255) |
| corridor2corridor_color = (0, 255, 0) |
| room2corridor_color = (0, 255, 255) |
| room2room_color = (255, 0, 255) |
|
|
| |
| for bbox in exit_dbboxes: |
| x1, y1, x2, y2 = bbox |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), exit_color, thickness=2) |
|
|
| for bbox in corridor2corridor_dbboxes: |
| x1, y1, x2, y2 = bbox |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), corridor2corridor_color, thickness=2) |
|
|
| for bbox in room2corridor_dbboxes: |
| x1, y1, x2, y2 = bbox |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), room2corridor_color, thickness=2) |
|
|
| for bbox in room2room_dbboxes: |
| x1, y1, x2, y2 = bbox |
| cv2.rectangle(annotated_image, (x1, y1), (x2, y2), room2room_color, thickness=2) |
|
|
| |
| for node_id, node_data in graph.graph.nodes(data=True): |
| node_type = node_data['type'] |
| position = node_data.get('position') |
|
|
| |
| if not isinstance(position, tuple) or len(position) != 2: |
| print(f"Warning: Node {node_id} has an invalid position: {position}. Skipping.") |
| continue |
|
|
| |
| position = tuple(map(int, position)) |
|
|
| |
| if node_type == "room": |
| node_color = room_color |
| elif node_type == "door": |
| node_color = door_color |
| elif node_type == "corridor": |
| node_color = corridor_color |
| elif node_type == "outside": |
| node_color = outside_color |
| else: |
| continue |
|
|
| |
| cv2.circle(annotated_image, position, 5, node_color, -1) |
|
|
| |
| os.makedirs(connect_img_dir, exist_ok=True) |
|
|
| |
| output_path = os.path.join(connect_img_dir, "bbox_with_graph.png") |
| annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_RGB2BGR) |
| cv2.imwrite(output_path, annotated_image) |
|
|
| print(f"Image with bounding boxes and graph nodes saved to: {output_path}") |