(
tensor: Union[torch.Tensor, List[torch.Tensor]],
nrow: int = 8,
padding: int = 2,
normalize: bool = False,
value_range: Optional[Tuple[int, int]] = None,
scale_each: bool = False,
pad_value: int = 0,
**kwargs
)
| 73 | |
| 74 | @torch.no_grad() |
| 75 | def make_grid( |
| 76 | tensor: Union[torch.Tensor, List[torch.Tensor]], |
| 77 | nrow: int = 8, |
| 78 | padding: int = 2, |
| 79 | normalize: bool = False, |
| 80 | value_range: Optional[Tuple[int, int]] = None, |
| 81 | scale_each: bool = False, |
| 82 | pad_value: int = 0, |
| 83 | **kwargs |
| 84 | ) -> torch.Tensor: |
| 85 | if not (torch.is_tensor(tensor) or |
| 86 | (isinstance(tensor, list) and all(torch.is_tensor(t) for t in tensor))): |
| 87 | raise TypeError(f'tensor or list of tensors expected, got {type(tensor)}') |
| 88 | |
| 89 | if "range" in kwargs.keys(): |
| 90 | warning = "range will be deprecated, please use value_range instead." |
| 91 | warnings.warn(warning) |
| 92 | value_range = kwargs["range"] |
| 93 | |
| 94 | # if list of tensors, convert to a 4D mini-batch Tensor |
| 95 | if isinstance(tensor, list): |
| 96 | tensor = torch.stack(tensor, dim=0) |
| 97 | |
| 98 | if tensor.dim() == 2: # single image H x W |
| 99 | tensor = tensor.unsqueeze(0) |
| 100 | if tensor.dim() == 3: # single image |
| 101 | if tensor.size(0) == 1: # if single-channel, convert to 3-channel |
| 102 | tensor = torch.cat((tensor, tensor, tensor), 0) |
| 103 | tensor = tensor.unsqueeze(0) |
| 104 | |
| 105 | if tensor.dim() == 4 and tensor.size(1) == 1: # single-channel images |
| 106 | tensor = torch.cat((tensor, tensor, tensor), 1) |
| 107 | |
| 108 | if normalize is True: |
| 109 | tensor = tensor.clone() # avoid modifying tensor in-place |
| 110 | if value_range is not None: |
| 111 | assert isinstance(value_range, tuple), \ |
| 112 | "value_range has to be a tuple (min, max) if specified. min and max are numbers" |
| 113 | |
| 114 | def norm_ip(img, low, high): |
| 115 | img.clamp(min=low, max=high) |
| 116 | img.sub_(low).div_(max(high - low, 1e-5)) |
| 117 | |
| 118 | def norm_range(t, value_range): |
| 119 | if value_range is not None: |
| 120 | norm_ip(t, value_range[0], value_range[1]) |
| 121 | else: |
| 122 | norm_ip(t, float(t.min()), float(t.max())) |
| 123 | |
| 124 | if scale_each is True: |
| 125 | for t in tensor: # loop over mini-batch dimension |
| 126 | norm_range(t, value_range) |
| 127 | else: |
| 128 | norm_range(tensor, value_range) |
| 129 | |
| 130 | if tensor.size(0) == 1: |
| 131 | return tensor.squeeze(0) |
| 132 |
no test coverage detected