From 3b277cfcaed3efbc68074994eba273fa6849a10d Mon Sep 17 00:00:00 2001 From: Bartok9 Date: Fri, 10 Jul 2026 18:57:33 -0400 Subject: [PATCH] fix(client): clip float images before convert_to_uint8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Out-of-range float pixels previously wrapped when cast to uint8 (e.g. 1.5 → 127 after 255*x truncate). Clip to [0, 1] first. --- .../openpi-client/src/openpi_client/image_tools.py | 5 ++++- .../src/openpi_client/image_tools_test.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/openpi-client/src/openpi_client/image_tools.py b/packages/openpi-client/src/openpi_client/image_tools.py index 7a971b9d5f..fa2790e5f9 100644 --- a/packages/openpi-client/src/openpi_client/image_tools.py +++ b/packages/openpi-client/src/openpi_client/image_tools.py @@ -6,9 +6,12 @@ def convert_to_uint8(img: np.ndarray) -> np.ndarray: """Converts an image to uint8 if it is a float image. This is important for reducing the size of the image when sending it over the network. + + Float inputs are assumed to be in approximately the [0, 1] range. Values are + clipped before scaling so out-of-range pixels do not wrap under `astype(uint8)`. """ if np.issubdtype(img.dtype, np.floating): - img = (255 * img).astype(np.uint8) + img = (255 * np.clip(img, 0.0, 1.0)).astype(np.uint8) return img diff --git a/packages/openpi-client/src/openpi_client/image_tools_test.py b/packages/openpi-client/src/openpi_client/image_tools_test.py index 8d4b4b9203..75b27e7741 100644 --- a/packages/openpi-client/src/openpi_client/image_tools_test.py +++ b/packages/openpi-client/src/openpi_client/image_tools_test.py @@ -35,3 +35,17 @@ def test_resize_with_pad_shapes(): resized_images = image_tools.resize_with_pad(images, height, width) assert resized_images.shape == (1, height, width, 3) assert np.all(resized_images == 0) + + +def test_convert_to_uint8_clips_out_of_range_floats(): + img = np.array([[[-0.5, 0.0, 1.5]]], dtype=np.float32) + out = image_tools.convert_to_uint8(img) + assert out.dtype == np.uint8 + assert out.tolist() == [[[0, 0, 255]]] + + +def test_convert_to_uint8_passes_through_uint8(): + img = np.array([[[10, 20, 30]]], dtype=np.uint8) + out = image_tools.convert_to_uint8(img) + assert out.dtype == np.uint8 + assert np.array_equal(out, img)