Bases: IntensityTransform
Change image contrast by raising values to the power \(\gamma\).
The exponent is computed as \(\gamma = e^{\beta}\), where \(\beta\) is
sampled from the specified range. Positive \(\beta\) increases
contrast (gamma expansion), negative \(\beta\) decreases it (gamma
compression). See the
Gamma correction
Wikipedia entry for more information.
Note
Fractional exponentiation of negative values is not
well-defined for non-complex numbers. If negative values are
found in the input image \(I\), the applied transform is
\(\text{sign}(I) \cdot |I|^{\gamma}\) instead of the usual
\(I^{\gamma}\). Use Normalize to ensure
all values are positive if needed.
Parameters:
| Name |
Type |
Description |
Default |
log_gamma
|
float | tuple[float, float]
|
Range for \(\beta\) in \(\gamma = e^{\beta}\).
A scalar \(x\) means \(\beta = x\) (deterministic).
A 2-tuple \((a, b)\) means \(\beta \sim \mathcal{U}(a, b)\).
A Choice or Distribution may also be passed.
The default log_gamma=0 is a no-op (and warns).
|
0.0
|
**kwargs
|
Any
|
|
{}
|
Examples:
>>> import torchio as tio
>>> transform = tio.Gamma(log_gamma=0.5)
>>> transform = tio.Gamma(log_gamma=(-0.3, 0.3))
Source code in src/torchio/transforms/intensity/gamma.py
| class Gamma(IntensityTransform):
r"""Change image contrast by raising values to the power $\gamma$.
The exponent is computed as $\gamma = e^{\beta}$, where $\beta$ is
sampled from the specified range. Positive $\beta$ increases
contrast (gamma expansion), negative $\beta$ decreases it (gamma
compression). See the
[Gamma correction](https://en.wikipedia.org/wiki/Gamma_correction)
Wikipedia entry for more information.
Note:
Fractional exponentiation of negative values is not
well-defined for non-complex numbers. If negative values are
found in the input image $I$, the applied transform is
$\text{sign}(I) \cdot |I|^{\gamma}$ instead of the usual
$I^{\gamma}$. Use [`Normalize`][torchio.Normalize] to ensure
all values are positive if needed.
Args:
log_gamma: Range for $\beta$ in $\gamma = e^{\beta}$.
A scalar $x$ means $\beta = x$ (deterministic).
A 2-tuple $(a, b)$ means $\beta \sim \mathcal{U}(a, b)$.
A `Choice` or `Distribution` may also be passed.
The default `log_gamma=0` is a no-op (and warns).
**kwargs: See [`Transform`][torchio.Transform].
Examples:
>>> import torchio as tio
>>> transform = tio.Gamma(log_gamma=0.5)
>>> transform = tio.Gamma(log_gamma=(-0.3, 0.3))
"""
def __init__(
self,
*,
log_gamma: float | tuple[float, float] = 0.0,
**kwargs: Any,
) -> None:
super().__init__(**kwargs)
self.log_gamma = to_range(log_gamma)
self._warn_if_noop(
is_noop=self.log_gamma.is_constant(0.0),
hint="log_gamma=(-0.3, 0.3)",
)
def make_params(self, batch: SubjectsBatch) -> dict[str, Any]:
"""Sample the log-gamma value."""
return {"log_gamma": self.log_gamma.sample_1d()}
def apply_transform(
self,
batch: SubjectsBatch,
params: dict[str, Any],
) -> SubjectsBatch:
"""Raise each intensity image to the power gamma."""
gamma = math.exp(params["log_gamma"])
for _name, img_batch in self._get_images(batch).items():
data = img_batch.data
img_batch.data = data.sign() * data.abs().pow(gamma)
return batch
@property
def invertible(self) -> bool:
"""Whether this transform can be inverted."""
return True
def inverse(self, params: dict[str, Any]) -> _GammaInverse:
"""Invert by applying 1/gamma."""
return _GammaInverse(log_gamma=params["log_gamma"], copy=False)
|
invertible
property
Whether this transform can be inverted.
forward(data)
forward(data: Subject) -> Subject
forward(data: Image) -> Image
forward(data: Tensor) -> Tensor
forward(data: np.ndarray) -> np.ndarray
forward(data: sitk.Image) -> sitk.Image
forward(data: nib.Nifti1Image) -> nib.Nifti1Image
forward(data: dict) -> dict
forward(data: ImagesBatch) -> ImagesBatch
forward(data: SubjectsBatch) -> SubjectsBatch
Apply the transform.
The output type always matches the input type.
Parameters:
| Name |
Type |
Description |
Default |
data
|
Any
|
|
required
|
Source code in src/torchio/transforms/transform.py
| def forward(self, data: Any) -> Any:
"""Apply the transform.
The output type always matches the input type.
Args:
data: Input data to transform.
"""
if self.copy:
data = _copy.deepcopy(data)
batch, unwrap = self._wrap(data)
if torch.rand(1).item() > self.p:
return unwrap(batch)
params = self.make_params(batch)
batch = self.apply_transform(batch, params)
# Record history on the batch
trace = AppliedTransform(name=type(self).__name__, params=params)
if not hasattr(batch, "applied_transforms"):
batch.applied_transforms = []
batch.applied_transforms.append(trace)
result = unwrap(batch)
# Propagate history to outputs that can carry it
if (
hasattr(batch, "applied_transforms")
and not isinstance(result, (SubjectsBatch, Tensor, np.ndarray))
and not isinstance(result, dict)
):
with contextlib.suppress(AttributeError):
result.applied_transforms = list(batch.applied_transforms)
return result
|
to_hydra()
Export as a Hydra-compatible config dict.
Returns a dict with _target_ set to the fully qualified
class name and only non-default field values included.
Returns:
| Type |
Description |
dict[str, Any]
|
Dict suitable for hydra.utils.instantiate().
|
Source code in src/torchio/transforms/transform.py
| def to_hydra(self) -> dict[str, Any]:
"""Export as a Hydra-compatible config dict.
Returns a dict with `_target_` set to the fully qualified
class name and only non-default field values included.
Returns:
Dict suitable for `hydra.utils.instantiate()`.
"""
from .parameter_range import _ParameterRange
cls = type(self)
target = f"torchio.{cls.__qualname__}"
cfg: dict[str, Any] = {"_target_": target}
for name, default in _collect_init_params(cls).items():
value = getattr(self, name, default)
if isinstance(value, _ParameterRange):
if value._original == default:
continue
value = _hydra_value(value._original)
elif value == default:
continue
else:
value = _hydra_value(value)
cfg[name] = value
return cfg
|
make_params(batch)
Sample the log-gamma value.
Source code in src/torchio/transforms/intensity/gamma.py
| def make_params(self, batch: SubjectsBatch) -> dict[str, Any]:
"""Sample the log-gamma value."""
return {"log_gamma": self.log_gamma.sample_1d()}
|
Raise each intensity image to the power gamma.
Source code in src/torchio/transforms/intensity/gamma.py
| def apply_transform(
self,
batch: SubjectsBatch,
params: dict[str, Any],
) -> SubjectsBatch:
"""Raise each intensity image to the power gamma."""
gamma = math.exp(params["log_gamma"])
for _name, img_batch in self._get_images(batch).items():
data = img_batch.data
img_batch.data = data.sign() * data.abs().pow(gamma)
return batch
|
inverse(params)
Invert by applying 1/gamma.
Source code in src/torchio/transforms/intensity/gamma.py
| def inverse(self, params: dict[str, Any]) -> _GammaInverse:
"""Invert by applying 1/gamma."""
return _GammaInverse(log_gamma=params["log_gamma"], copy=False)
|