From d2136aae98bb927f3633275bb5f9e511ec0bcd21 Mon Sep 17 00:00:00 2001 From: "immich-push-o-matic[bot]" <179150890+immich-push-o-matic[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2026 23:09:03 +0000 Subject: [PATCH] fix(ml): widen empty half-precision arrays (#31962) fix(ml): widen empty half-precision arrays (#31950) (cherry picked from commit b11e400a36a40fd588364ebf31fd671f97cdf446) Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com> --- machine-learning/immich_ml/models/transforms.py | 4 ++-- machine-learning/test_main.py | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/machine-learning/immich_ml/models/transforms.py b/machine-learning/immich_ml/models/transforms.py index 7d473a90a..debaf03c6 100644 --- a/machine-learning/immich_ml/models/transforms.py +++ b/machine-learning/immich_ml/models/transforms.py @@ -74,8 +74,8 @@ def serialize_np_array(arr: NDArray[np.float32]) -> str: def widen(array: NDArray[Any]) -> NDArray[Any]: """Single precision from half through OpenCV, as numpy converts one value at a time without native half support.""" - if array.dtype != np.float16: - return array + if array.dtype != np.float16 or array.size == 0: + return array.astype(np.float32, copy=False) return cv2.convertFp16(array.reshape(-1, array.shape[-1]).view(np.int16)).reshape(array.shape) # int16 carries half diff --git a/machine-learning/test_main.py b/machine-learning/test_main.py index b0e31ec3c..50319d530 100644 --- a/machine-learning/test_main.py +++ b/machine-learning/test_main.py @@ -1801,6 +1801,15 @@ class TestOcr: assert indices.tolist() == [[2, 1, 1, 0]] assert np.allclose(confidence, [[1 / (1 + 2 * np.exp(-10)), 1 / (1 + np.exp(-1) + np.exp(-2)), 0, 0]]) + def test_rec_decodes_half_precision_logits_that_are_all_blank(self) -> None: + raw = np.full((2, 3, 1, 3), -5.0, dtype=np.float16) + raw[..., 0] = 5.0 # every step reads as the blank, so no character is kept + + indices, confidence = logits(raw) + + assert indices.tolist() == [[0, 0, 0], [0, 0, 0]] + assert confidence.dtype == np.float32 and not confidence.any() + def test_set_rec_set_default_max_batch_size( self, ort_session: mock.Mock, path: mock.Mock, mocker: MockerFixture ) -> None: