def copy(self) -> Image: """Returns a deep copy of this Image.""" image = Image(self.__path) image.create(self.width, self.height) image.__pixels = np.copy(self.__pixels) image.__filled = np.copy(self.__filled) return image
def extract(self, center: Point, padding: int, mode: str = 'drop') -> Image: """ Extracts a window from this Image centred at the given Point with the specified padding. Args: center: The center of the window. padding: The padding of the window. mode: Approach to handling pixels that fall outside this Image. Supported modes include 'drop', 'reflect', and 'wrap'. Returns: Image object with the specified window. """ # Create a window using the padding dimensions. window = Image() window.create(2 * padding + 1, 2 * padding + 1) if mode == 'drop': # Find the corners of the window in this Image. min_corner = self.clamp( Point(center.x - padding, center.y - padding)) max_corner = self.clamp( Point(center.x + padding, center.y + padding)) # Find the corner in the window which corresponds to the minimum corner in this Image. offset = Point(padding - (center.x - min_corner.x), padding - (center.y - min_corner.y)) # Populate the window pixels and filled arrays. w, h = max_corner.x - min_corner.x + 1, max_corner.y - min_corner.y + 1 window.__pixels[offset.y:offset.y + h, offset.x:offset.x + w] = self.__pixels[min_corner.y:max_corner.y + 1, min_corner.x:max_corner.x + 1] window.__filled[offset.y:offset.y + h, offset.x:offset.x + w] = self.__filled[min_corner.y:max_corner.y + 1, min_corner.x:max_corner.x + 1] return window elif mode == 'reflect' or mode == 'wrap': padded_pixels = np.stack([ np.pad(self.__pixels[:, :, c], padding, mode=mode) for c in range(3) ], axis=2) padded_filled = np.pad(self.__filled, padding, mode=mode) # Adjust the window offset to accommodate the padding. offset = center + Point(padding, padding) # Populate the window pixels and filled arrays. window.__pixels = padded_pixels[offset.y - padding:offset.y + padding + 1, offset.x - padding:offset.x + padding + 1] window.__filled = padded_filled[offset.y - padding:offset.y + padding + 1, offset.x - padding:offset.x + padding + 1] return window else: raise NotImplementedError(f'Mode "{mode}" is not supported.')