def compute_importance_map( patch_size: Tuple[int, ...], mode: Union[BlendMode, str] = BlendMode.CONSTANT, sigma_scale: Union[Sequence[float], float] = 0.125, device: Union[torch.device, int, str] = "cpu", ) -> torch.Tensor: """Get importance map for different weight modes. Args: patch_size: Size of the required importance map. This should be either H, W [,D]. mode: {``"constant"``, ``"gaussian"``} How to blend output of overlapping windows. Defaults to ``"constant"``. - ``"constant``": gives equal weight to all predictions. - ``"gaussian``": gives less weight to predictions on edges of windows. sigma_scale: Sigma_scale to calculate sigma for each dimension (sigma = sigma_scale * dim_size). Used for gaussian mode only. device: Device to put importance map on. Raises: ValueError: When ``mode`` is not one of ["constant", "gaussian"]. Returns: Tensor of size patch_size. """ mode = BlendMode(mode) device = torch.device(device) # type: ignore[arg-type] if mode == BlendMode.CONSTANT: importance_map = torch.ones(patch_size, device=device).float() elif mode == BlendMode.GAUSSIAN: center_coords = [i // 2 for i in patch_size] sigma_scale = ensure_tuple_rep(sigma_scale, len(patch_size)) sigmas = [i * sigma_s for i, sigma_s in zip(patch_size, sigma_scale)] importance_map = torch.zeros(patch_size) #, device=device) importance_map[tuple(center_coords)] = 1 importance_map = importance_map.to(device) pt_gaussian = GaussianFilter(len(patch_size), sigmas).to(device=device, dtype=torch.float) importance_map = pt_gaussian(importance_map.unsqueeze(0).unsqueeze(0)) importance_map = importance_map.squeeze(0).squeeze(0) importance_map = importance_map / torch.max(importance_map) importance_map = importance_map.float() # importance_map cannot be 0, otherwise we may end up with nans! min_non_zero = importance_map[importance_map != 0].min().item() importance_map = torch.clamp(importance_map, min=min_non_zero) else: raise ValueError( f"Unsupported mode: {mode}, available options are [{BlendMode.CONSTANT}, {BlendMode.CONSTANT}]." ) return importance_map
def __init__(self, roi_size, sw_batch_size: int = 1, overlap: float = 0.25, mode: Union[BlendMode, str] = BlendMode.CONSTANT): Inferer.__init__(self) self.roi_size = roi_size self.sw_batch_size = sw_batch_size self.overlap = overlap self.mode: BlendMode = BlendMode(mode)
def compute_importance_map( patch_size: Tuple[int, ...], mode: Union[BlendMode, str] = BlendMode.CONSTANT, sigma_scale: float = 0.125, device: Optional[torch.device] = None, ): """Get importance map for different weight modes. Args: patch_size: Size of the required importance map. This should be either H, W [,D]. mode: {``"constant"``, ``"gaussian"``} How to blend output of overlapping windows. Defaults to ``"constant"``. - ``"constant``": gives equal weight to all predictions. - ``"gaussian``": gives less weight to predictions on edges of windows. sigma_scale: Sigma_scale to calculate sigma for each dimension (sigma = sigma_scale * dim_size). Used for gaussian mode only. device: Device to put importance map on. Raises: ValueError: When ``mode`` is not one of ["constant", "gaussian"]. Returns: Tensor of size patch_size. """ mode = BlendMode(mode) if mode == BlendMode.CONSTANT: importance_map = torch.ones(patch_size, device=device).float() elif mode == BlendMode.GAUSSIAN: center_coords = [i // 2 for i in patch_size] sigmas = [i * sigma_scale for i in patch_size] importance_map = torch.zeros(patch_size, device=device) importance_map[tuple(center_coords)] = 1 pt_gaussian = GaussianFilter(len(patch_size), sigmas).to(device=device, dtype=torch.float) importance_map = pt_gaussian(importance_map.unsqueeze(0).unsqueeze(0)) importance_map = importance_map.squeeze(0).squeeze(0) importance_map = importance_map / torch.max(importance_map) importance_map = importance_map.float() # importance_map cannot be 0, otherwise we may end up with nans! importance_map[importance_map == 0] = torch.min( importance_map[importance_map != 0]) else: raise ValueError( f'Unsupported mode: {mode}, available options are ["constant", "gaussian"].' ) return importance_map
def __init__( self, roi_size: Union[Sequence[int], int], sw_batch_size: int = 1, overlap: float = 0.25, mode: Union[BlendMode, str] = BlendMode.CONSTANT, output_internel_results: Optional[bool] = False ) -> None: Inferer.__init__(self) self.roi_size = roi_size self.sw_batch_size = sw_batch_size self.overlap = overlap self.mode: BlendMode = BlendMode(mode) self.output_internel_results = output_internel_results
def __init__( self, roi_size: Union[Sequence[int], int], sw_batch_size: int = 1, overlap: float = 0.25, mode: Union[BlendMode, str] = BlendMode.CONSTANT, sigma_scale: Union[Sequence[float], float] = 0.125, padding_mode: Union[PytorchPadMode, str] = PytorchPadMode.CONSTANT, cval: float = 0.0, sw_device: Union[torch.device, str, None] = None, device: Union[torch.device, str, None] = None, progress: bool = False, cache_roi_weight_map: bool = False, ) -> None: Inferer.__init__(self) self.roi_size = roi_size self.sw_batch_size = sw_batch_size self.overlap = overlap self.mode: BlendMode = BlendMode(mode) self.sigma_scale = sigma_scale self.padding_mode = padding_mode self.cval = cval self.sw_device = sw_device self.device = device self.progress = progress # compute_importance_map takes long time when computing on cpu. We thus # compute it once if it's static and then save it for future usage self.roi_weight_map = None try: if cache_roi_weight_map and isinstance( roi_size, Sequence) and min(roi_size) > 0: # non-dynamic roi size if device is None: device = "cpu" self.roi_weight_map = compute_importance_map( ensure_tuple(self.roi_size), mode=mode, sigma_scale=sigma_scale, device=device) if cache_roi_weight_map and self.roi_weight_map is None: warnings.warn( "cache_roi_weight_map=True, but cache is not created. (dynamic roi_size?)" ) except BaseException as e: raise RuntimeError( "Seems to be OOM. Please try smaller roi_size, or use mode='constant' instead of mode='gaussian'. " ) from e
def __init__( self, roi_size: Union[Sequence[int], int], sw_batch_size: int = 1, overlap: float = 0.25, mode: Union[BlendMode, str] = BlendMode.CONSTANT, sigma_scale: Union[Sequence[float], float] = 0.125, padding_mode: Union[PytorchPadMode, str] = PytorchPadMode.CONSTANT, cval: float = 0.0, ) -> None: Inferer.__init__(self) self.roi_size = roi_size self.sw_batch_size = sw_batch_size self.overlap = overlap self.mode: BlendMode = BlendMode(mode) self.sigma_scale = sigma_scale self.padding_mode = padding_mode self.cval = cval