
Нормалізувати RGB-значення на 255 чи на 256?
Програміст графіки Пекка Вяяненен розібрав два поширені способи перетворення 8-бітних RGB-значень у числа з рухомою комою і назад, пояснивши, коли правильним є ділення на 255, а коли можна обґрунтувати ділення на 256.
Перетворення 8-бітних значень кольору в числа з рухомою комою і назад — одне з перших рішень у будь-якій програмі для обробки зображень, і тут існують два підходи. Програміст графіки Пекка Вяяненен опублікував на своєму блозі 30fps.net аналіз цього питання, порівнюючи стандартне ділення на 255 з альтернативою, яка додає зсув 0,5 і ділить на 256.
Дві формули
Стандартний підхід перетворює пікселі за допомогою img / 255.0, а записує назад через trunc(result * 255 + 0.5): ціле 0 стає 0.0, а 255 — 1.0, тобто так само, як це роблять графічні процесори для беззнакових нормалізованих форматів. Альтернатива використовує (img + 0.5) / 256.0 для перетворення і trunc(result * 256) для запису, завдяки чому кожне значення з рухомою комою опиняється рівно посередині між двома цілими.
Практична ціна альтернативи в тому, що чорний більше не дорівнює 0.0: ціле 0 декодується як 0.001953125, тож код, який хоче розпізнавати чорні пікселі, мусить знати цю константу й прив'язується до 8-бітного діапазону. Автор зауважує, що зі стандартною формулою зображення повертається без втрат, а її неточність — 128/255 приблизно дорівнює 0.501961 — залишається в молодшому розряді, з відносною похибкою близько 0.00001 відсотка.
Удвічі вужчі комірки на краях
Слабкість стандартної формули проявляється на краях. Оскільки її діапазон трохи ширший за [0, 1], комірки, що округлюються до 0 і до 255, мають удвічі меншу ширину, тому рівномірно розподілений шум дає крайні значення вдвічі рідше. Пост демонструє це гістограмою з мільйона випадкових значень і далі доводить, що це рідко має значення: значення трохи за межами діапазону все одно округлюються до правильного цілого, а віднімання 0.005 від чорного в обох схемах дає 0.
Мовою теорії квантування ці два варіанти — це mid-riser квантувач на 255 рівнів і mid-tread квантувач на 256. Похибка реконструкції трохи менша при діленні на 256 — середня абсолютна похибка 1/1024 проти 1/1020 — але лише тоді, коли той самий код керує і кодуванням, і декодуванням. Завантаження чужих зображень з альтернативним масштабом теоретично є неправильним декодуванням і змішує два квантувачі.
Що робити
Висновок навмисно практичний: якщо ви обробляєте зображення, яких не створювали, нормалізуйте за 255. Ділення на 256 виправдане, коли ви контролюєте і збереження, і завантаження, не потребуєте відображення нуля в нуль і згодні прив'язати код обробки до 8-бітного діапазону. У пості також розглянуто пізніший «найкращий метод» Кріса Ломонта, який декодує через k/255.0 і кодує через clamp(floor(x * 256), 0, 255), зберігаючи повний діапазон і рівні комірки ціною приблизно вдвічі більшої похибки квантування, що сягає піку на краях.
SiTech — веброзробка з підтримкою AI
Створюємо швидкі та сучасні сайти й інтегруємо AI у бізнес-процеси. Маєте проєкт чи запитання? Із задоволенням допоможемо.