При обработке изображений встаёт вопрос: как правильно конвертировать целые пиксели (0–255) в float и обратно. В Python с NumPy есть два подхода. Первый — стандартное деление на 255.0: чёрный (0) превращается в 0.0, белый (255) — в 1.0. Так делают GPU. Второй — альтернативный: к каждому значению добавляется 0.5, а делитель меняется на 256.0. Чёрный получается 0.5/256 ≈ 0.00195, что неудобно — код начинает зависеть от 8-битного диапазона.
Зачем вообще кто-то выбирает второй вариант? У стандартного деления есть пара визуальных недостатков. Если нарисовать числовую прямую, крайние значения (близкие к 0 и 255) оказываются как бы «зажатыми» — их бины (диапазоны округления) торчат за границы [0, 1]. Из-за этого при обратном преобразовании из равномерного шума в [0,1] крайние целые коды 0 и 255 встречаются в два раза реже остальных. На практике это почти никогда не критично — изображение всё равно восстановится без потерь (uint8 → float → uint8), а выход за 0.0 или 1.0 просто срежется к правильному бину.
Следующий аргумент противников — неточность. 128/255.0 ≈ 0.501961, а не ровно 0.5. Но ошибка меньше 2⁻²³, то есть ничтожна. Вопрос тут скорее эстетический.
С точки зрения теории квантования, стандартный подход — это mid-riser квантователь с L=255, а альтернатива — mid-tread с L=256. Для unsigned входов mid-riser странен и даёт чуть большую ошибку реконструкции: средняя абсолютная ошибка 1/1020 против 1/1024 у деления на 256. Однако это актуально только если вы контролируете и кодирование, и декодирование. Если вы просто грузите чужие изображения, которые наверняка закодированы делением на 255, то использование альтернативы лишь добавит ошибку.
Вывод: для загрузки случайных картинок берите 255. Это надёжно, чёрный — ноль, и никаких сюрпризов. Если вы пишете свой формат и можете гарантировать одинаковый пайплайн на чтение и запись, 256 даст теоретически чуть более точный результат. Но коллеги всё равно могут загрузить ваши файлы со стандартным делением — и ваша «мастерская точность» пропадёт.