Spaces:
Runtime error
Runtime error
| import random | |
| from typing import List, Optional, Tuple | |
| import cv2 | |
| import numpy as np | |
| from skimage.draw import polygon | |
| class RoomDropoutStrategy: | |
| """ | |
| Strategy for randomly dropping rooms from a density map using ground truth coordinates. | |
| Density map: grayscale image where foreground (rooms) are white points and background is black | |
| GT room coordinates: list of 2D points defining each room's boundary | |
| """ | |
| def __init__(self, density_map: np.ndarray, room_coordinates: List[List[Tuple[int, int]]]): | |
| """ | |
| Initialize the dropout strategy. | |
| Args: | |
| density_map: Grayscale image (H, W) where white pixels represent rooms | |
| room_coordinates: List of rooms, each room is a list of (x, y) coordinate tuples | |
| """ | |
| self.original_density_map = density_map.copy() | |
| self.room_coordinates = room_coordinates | |
| self.num_rooms = len(room_coordinates) | |
| def create_room_masks(self) -> List[np.ndarray]: | |
| """ | |
| Create binary masks for each room using their GT coordinates. | |
| Returns: | |
| List of binary masks, one for each room | |
| """ | |
| h, w = self.original_density_map.shape | |
| room_masks = [] | |
| for room_coords in self.room_coordinates: | |
| mask = np.zeros((h, w), dtype=np.uint8) | |
| if len(room_coords) >= 3: # Need at least 3 points for a polygon | |
| # Convert coordinates to numpy array | |
| coords = np.array(room_coords) | |
| x_coords = coords[:, 0] | |
| y_coords = coords[:, 1] | |
| # Create polygon mask using skimage | |
| rr, cc = polygon(y_coords, x_coords, shape=(h, w)) | |
| mask[rr, cc] = 1 | |
| room_masks.append(mask) | |
| return room_masks | |
| def drop_rooms_random(self, dropout_rate: float = 0.3, seed: Optional[int] = None) -> Tuple[np.ndarray, List[int]]: | |
| """ | |
| Randomly drop rooms from the density map. | |
| Args: | |
| dropout_rate: Fraction of rooms to drop (0.0 to 1.0) | |
| seed: Random seed for reproducibility | |
| Returns: | |
| Tuple of (modified_density_map, list_of_dropped_room_indices) | |
| """ | |
| if seed is not None: | |
| random.seed(seed) | |
| np.random.seed(seed) | |
| # Determine number of rooms to drop | |
| num_to_drop = int(self.num_rooms * dropout_rate) | |
| # Randomly select room indices to drop | |
| room_indices = list(range(self.num_rooms)) | |
| dropped_indices = random.sample(room_indices, num_to_drop) | |
| return self._apply_dropout(dropped_indices), dropped_indices | |
| def drop_rooms_by_indices(self, room_indices: List[int]) -> np.ndarray: | |
| """ | |
| Drop specific rooms by their indices. | |
| Args: | |
| room_indices: List of room indices to drop | |
| Returns: | |
| Modified density map with specified rooms removed | |
| """ | |
| return self._apply_dropout(room_indices) | |
| def drop_rooms_by_area( | |
| self, min_area: Optional[int] = None, max_area: Optional[int] = None | |
| ) -> Tuple[np.ndarray, List[int]]: | |
| """ | |
| Drop rooms based on their area constraints. | |
| Args: | |
| min_area: Minimum area threshold (drop rooms smaller than this) | |
| max_area: Maximum area threshold (drop rooms larger than this) | |
| Returns: | |
| Tuple of (modified_density_map, list_of_dropped_room_indices) | |
| """ | |
| room_masks = self.create_room_masks() | |
| dropped_indices = [] | |
| for i, mask in enumerate(room_masks): | |
| area = np.sum(mask) | |
| should_drop = False | |
| if min_area is not None and area < min_area: | |
| should_drop = True | |
| if max_area is not None and area > max_area: | |
| should_drop = True | |
| if should_drop: | |
| dropped_indices.append(i) | |
| return self._apply_dropout(dropped_indices), dropped_indices | |
| def _apply_dropout(self, room_indices_to_drop: List[int]) -> np.ndarray: | |
| """ | |
| Apply dropout by removing specified rooms from the density map. | |
| Args: | |
| room_indices_to_drop: List of room indices to remove | |
| Returns: | |
| Modified density map with rooms removed | |
| """ | |
| modified_map = self.original_density_map.copy() | |
| room_masks = self.create_room_masks() | |
| # Remove each specified room | |
| for room_idx in room_indices_to_drop: | |
| if 0 <= room_idx < len(room_masks): | |
| mask = room_masks[room_idx] | |
| # Set pixels in the room area to background (black/0) | |
| modified_map[mask == 1] = 0 | |
| return modified_map | |
| def visualize_dropout( | |
| self, original_map: np.ndarray, modified_map: np.ndarray, dropped_indices: List[int] | |
| ) -> np.ndarray: | |
| """ | |
| Create a visualization showing the dropout effect. | |
| Args: | |
| original_map: Original density map | |
| modified_map: Modified density map after dropout | |
| dropped_indices: Indices of dropped rooms | |
| Returns: | |
| Visualization image with original and modified maps side by side | |
| """ | |
| h, w = original_map.shape | |
| # Create side-by-side comparison | |
| vis = np.zeros((h, w * 2), dtype=np.uint8) | |
| vis[:, :w] = original_map | |
| vis[:, w:] = modified_map | |
| # Highlight dropped rooms in red on the original map | |
| if len(dropped_indices) > 0: | |
| room_masks = self.create_room_masks() | |
| vis_color = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR) | |
| for idx in dropped_indices: | |
| if 0 <= idx < len(room_masks): | |
| mask = room_masks[idx] | |
| # Highlight in red on the left (original) side | |
| vis_color[mask == 1, 0] = 0 # Blue channel | |
| vis_color[mask == 1, 1] = 0 # Green channel | |
| vis_color[mask == 1, 2] = 255 # Red channel | |
| return vis_color | |
| return cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR) | |
| # Example usage and testing | |
| def example_usage(): | |
| """ | |
| Example of how to use the RoomDropoutStrategy class. | |
| """ | |
| # Create a sample density map (200x200 image) | |
| density_map = np.zeros((200, 200), dtype=np.uint8) | |
| # Create some sample room coordinates (rectangles and polygons) | |
| room_coordinates = [ | |
| # Room 1: Rectangle | |
| [(20, 20), (80, 20), (80, 60), (20, 60)], | |
| # Room 2: Another rectangle | |
| [(100, 30), (180, 30), (180, 80), (100, 80)], | |
| # Room 3: L-shaped room | |
| [(30, 100), (90, 100), (90, 130), (60, 130), (60, 160), (30, 160)], | |
| # Room 4: Triangle | |
| [(120, 120), (160, 120), (140, 160)], | |
| # Room 5: Pentagon | |
| [(50, 180), (70, 170), (90, 180), (80, 195), (40, 195)], | |
| ] | |
| # Fill the density map with white pixels for each room | |
| for room_coords in room_coordinates: | |
| coords = np.array(room_coords) | |
| x_coords = coords[:, 0] | |
| y_coords = coords[:, 1] | |
| from skimage.draw import polygon | |
| rr, cc = polygon(y_coords, x_coords, shape=density_map.shape) | |
| density_map[rr, cc] = 255 # White pixels for rooms | |
| # Initialize the dropout strategy | |
| dropout_strategy = RoomDropoutStrategy(density_map, room_coordinates) | |
| # Example 1: Random dropout | |
| print("Example 1: Random dropout (30% of rooms)") | |
| modified_map1, dropped_indices1 = dropout_strategy.drop_rooms_random(dropout_rate=0.3, seed=42) | |
| print(f"Dropped rooms: {dropped_indices1}") | |
| # Example 2: Drop specific rooms | |
| print("\nExample 2: Drop specific rooms (indices 0 and 2)") | |
| modified_map2 = dropout_strategy.drop_rooms_by_indices([0, 2]) | |
| # Example 3: Drop rooms by area | |
| print("\nExample 3: Drop rooms with area > 3000 pixels") | |
| modified_map3, dropped_indices3 = dropout_strategy.drop_rooms_by_area(max_area=3000) | |
| print(f"Dropped rooms by area: {dropped_indices3}") | |
| return density_map, modified_map1, modified_map2, modified_map3 | |
| if __name__ == "__main__": | |
| example_usage() | |