Randomly shift intensity with randomly picked offset.
| 259 | |
| 260 | |
| 261 | class RandShiftIntensity(RandomizableTransform): |
| 262 | """ |
| 263 | Randomly shift intensity with randomly picked offset. |
| 264 | """ |
| 265 | |
| 266 | backend = [TransformBackends.TORCH, TransformBackends.NUMPY] |
| 267 | |
| 268 | def __init__( |
| 269 | self, offsets: tuple[float, float] | float, safe: bool = False, prob: float = 0.1, channel_wise: bool = False |
| 270 | ) -> None: |
| 271 | """ |
| 272 | Args: |
| 273 | offsets: offset range to randomly shift. |
| 274 | if single number, offset value is picked from (-offsets, offsets). |
| 275 | safe: if `True`, then do safe dtype convert when intensity overflow. default to `False`. |
| 276 | E.g., `[256, -12]` -> `[array(0), array(244)]`. If `True`, then `[256, -12]` -> `[array(255), array(0)]`. |
| 277 | prob: probability of shift. |
| 278 | channel_wise: if True, shift intensity on each channel separately. For each channel, a random offset will be chosen. |
| 279 | Please ensure that the first dimension represents the channel of the image if True. |
| 280 | """ |
| 281 | RandomizableTransform.__init__(self, prob) |
| 282 | if isinstance(offsets, (int, float)): |
| 283 | self.offsets = (min(-offsets, offsets), max(-offsets, offsets)) |
| 284 | elif len(offsets) != 2: |
| 285 | raise ValueError(f"offsets should be a number or pair of numbers, got {offsets}.") |
| 286 | else: |
| 287 | self.offsets = (min(offsets), max(offsets)) |
| 288 | self._offset = self.offsets[0] |
| 289 | self.channel_wise = channel_wise |
| 290 | self._shifter = ShiftIntensity(self._offset, safe) |
| 291 | |
| 292 | def randomize(self, data: Any | None = None) -> None: |
| 293 | super().randomize(None) |
| 294 | if not self._do_transform: |
| 295 | return None |
| 296 | if self.channel_wise: |
| 297 | self._offset = [self.R.uniform(low=self.offsets[0], high=self.offsets[1]) for _ in range(data.shape[0])] # type: ignore |
| 298 | else: |
| 299 | self._offset = self.R.uniform(low=self.offsets[0], high=self.offsets[1]) |
| 300 | |
| 301 | def __call__(self, img: NdarrayOrTensor, factor: float | None = None, randomize: bool = True) -> NdarrayOrTensor: |
| 302 | """ |
| 303 | Apply the transform to `img`. |
| 304 | |
| 305 | Args: |
| 306 | img: input image to shift intensity. |
| 307 | factor: a factor to multiply the random offset, then shift. |
| 308 | can be some image specific value at runtime, like: max(img), etc. |
| 309 | |
| 310 | """ |
| 311 | img = convert_to_tensor(img, track_meta=get_track_meta()) |
| 312 | if randomize: |
| 313 | self.randomize(img) |
| 314 | |
| 315 | if not self._do_transform: |
| 316 | return img |
| 317 | |
| 318 | ret: NdarrayOrTensor |
no outgoing calls
searching dependent graphs…