Repository: albumentations-team/albumentations

Issue:
[Feature request] Add apply_to_images to ToFloat



Discussion:

Patch:
diff --git a/albumentations/augmentations/other/type_transform.py b/albumentations/augmentations/other/type_transform.py
index 7a3a14163..71b427c5e 100644
--- a/albumentations/augmentations/other/type_transform.py
+++ b/albumentations/augmentations/other/type_transform.py
@@ -12,7 +12,6 @@
 
 import numpy as np
 from albucore import (
-    clip,
     from_float,
     get_max_value,
     to_float,
@@ -116,6 +115,19 @@ def apply(self, img: np.ndarray, **params: Any) -> np.ndarray:
         """
         return to_float(img, self.max_value)
 
+    def apply_to_images(self, images: np.ndarray, **params: Any) -> np.ndarray:
+        """Apply the ToFloat transform to the input batch of images.
+
+        Args:
+            images (np.ndarray): The input batch of images to apply the ToFloat transform to.
+            **params (Any): Additional parameters (not used in this transform).
+
+        Returns:
+            np.ndarray: The batch of images with the applied ToFloat transform.
+
+        """
+        return to_float(images, self.max_value)
+
 
 class FromFloat(ImageOnlyTransform):
     """Convert an image from floating point representation to the specified data type.
@@ -200,7 +212,7 @@ def apply_to_images(self, images: np.ndarray, **params: Any) -> np.ndarray:
             **params (Any): Additional parameters (not used in this transform).
 
         """
-        return clip(np.rint(images * self.max_value), np.dtype(self.dtype), inplace=True)
+        return from_float(images, np.dtype(self.dtype), self.max_value)
 
     def apply_to_volume(self, volume: np.ndarray, **params: Any) -> np.ndarray:
         """Apply the FromFloat transform to the input volume.


Test patch:
diff --git a/tests/test_other.py b/tests/test_other.py
new file mode 100644
index 000000000..40f20f042
--- /dev/null
+++ b/tests/test_other.py
@@ -0,0 +1,50 @@
+import numpy as np
+import pytest
+from albucore.utils import get_max_value
+
+from albumentations.augmentations import FromFloat, ToFloat
+
+
+@pytest.mark.parametrize("dtype", ["uint8", "uint16", "float32", "float64"])
+@pytest.mark.parametrize(
+    "param, shape",
+    [
+        ("image", (8, 7, 6)),
+        ("image", (8, 7)),
+        ("images", (4, 8, 7, 6)),
+        ("images", (4, 8, 7)),
+    ]
+)
+def test_to_float(param, shape, dtype):
+    rng = np.random.default_rng()
+    data = rng.uniform(0, 10, size=shape).astype(dtype)
+
+    aug = ToFloat()
+    result = aug(**{param: data})[param]
+
+    assert result.dtype == np.float32
+    assert result.shape == data.shape
+    np.testing.assert_allclose(data, result * get_max_value(np.dtype(dtype)))
+
+
+@pytest.mark.parametrize("dtype", ["uint8", "uint16"])
+@pytest.mark.parametrize(
+    "param, shape",
+    [
+        ("image", (8, 7, 6)),
+        ("image", (8, 7)),
+        ("images", (4, 8, 7, 6)),
+        ("images", (4, 8, 7)),
+    ]
+)
+def test_from_float(param, shape, dtype):
+    rng = np.random.default_rng()
+    data = rng.random(size=shape, dtype=np.float32)
+
+    aug = FromFloat(dtype=dtype)
+    result = aug(**{param: data})[param]
+
+    assert result.dtype == np.dtype(dtype)
+    assert result.shape == data.shape
+    # Because FromFloat has to round to the nearest integer, we get an absolute difference up to 0.5
+    np.testing.assert_allclose(data * get_max_value(np.dtype(dtype)), result, atol=0.5)