1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6

# теория · шаг 1 из 6

RCT: обратимый цвет с целочисленным округлением

Коротко

RCT переводит три целых компоненты цвета в среднюю составляющую и две разности. Округление вниз здесь совместимо с точным обратным ходом: разности сохраняют сведения, по которым можно восстановить исходную зелёную компоненту, затем красную и синюю. Для этого прямой и обратный ход используют одинаковые формулы и целочисленное деление. Отрицательные промежуточные значения допустимы. Обратимость цветового шага ещё не доказывает обратимость всего файла: вейвлеты, квантование и полнота потока проверяются отдельно.

Если выводишь обратные формулы RCT и различаешь деление вниз и к нулю, переходи к «Теперь сам».

Как думаешь, округление обязательно уничтожит цвет

У пиксела RGB=(17,10,4) взвешенная сумма R+2G+B равна 41. Деление на четыре даёт 10,25. Если оставить только целое 10, кажется, что четверть уже потеряна. Но цветовое преобразование передаёт ещё два целых числа: насколько синяя и красная компоненты отличаются от зелёной. Может ли эта дополнительная информация вернуть все три исходных числа?

Такая задача встречается при точном хранении медицинских изображений, рисунков и промежуточных результатов обработки. «Похоже на исходный цвет» здесь слабее нужного условия. После полного обратимого декодирования должен совпасть каждый отсчёт. Это проверяется сравнением целых значений, а не взглядом на экран и не малой средней ошибкой.

На что это похоже

Ты записал три суммы расходов за день. Вместо каждой суммы отдельно можно хранить одну опорную сумму и две поправки к ней. Поправки способны быть отрицательными, хотя сами расходы неотрицательны. Запретить отрицательные поправки означало бы изменить описание данных.

В RCT опорная величина устроена немного хитрее среднего: она даёт больший вес зелёной компоненте. Остальные два числа - точные разности. Это смена способа описания того же пиксела. Преобразование не обещает, что каждое новое число станет меньше или что три числа превратятся в два. Оно рассчитывает на статистическую связь компонент: у близких R,G,B разности часто меньше исходных значений и удобнее для дальнейшего кодирования.

Механизм: выразить неизвестное через сохранённые разности

Зафиксируем соглашение о названиях:

Y = (R + 2G + B) // 4
U = B - G
V = R - G

Оператор // означает округление результата вниз, к меньшему целому. Например, −11//4=−3. Это отличается от отбрасывания дробной части к нулю, которое дало бы −2. У другой записи RCT имена двух разностей могут быть переставлены. Поэтому полезно передавать или проверять именно формулы, а не угадывать порядок по буквам U,V.

Из разностей следует R=G+V и B=G+U. Подставим в формулу Y: Y=(4G+U+V)//4. Поскольку G целое, оно точно выходит из округления: Y=G+(U+V)//4. Отсюда получаем обратный ход:

G = Y - (U+V)//4
R = V + G
B = U + G

Это и объясняет, почему отдельная дробная часть Y не нужна. Разности несут ровно ту информацию, которая позволяет согласованно отменить целочисленный шаг. Мы не пытаемся восстановить любое вещественное число из его округления. Мы обращаем всю тройку взаимосвязанных целых чисел.

Правило

В выбранном RCT сохраняй Y=(R+2G+B)//4, U=B−G, V=R−G. Восстанавливай сначала G=Y−(U+V)//4, затем R и B прибавлением разностей. Используй деление вниз с обеих сторон. Не обрезай отрицательные разности и не ограничивай промежуточные значения диапазоном исходного пиксела.

Если данные беззнаковые и имеют p битов на компоненту, перед последующими преобразованиями возможен отдельный сдвиг уровня на половину диапазона, 2^(p−1). Его обратный шаг - прибавление того же числа. Знак и разрядность входа должны быть известны; величина сдвига не выбирается произвольно для каждого пиксела. RCT можно применить к уже сдвинутым целым компонентам: доказательство от знака не зависит.

Разбор: четверть не потребовалась

Для (17,10,4) получаем Y=41//4=10, U=−6, V=7. Обратный ход: (U+V)//4=1//4=0, поэтому G=10−0=10. Далее R=7+10=17 и B=−6+10=4. Восстановлены все три компоненты. Хотя при вычислении Y возникло округление, тройка не потеряла информации.

Для другого пиксела (3,8,1) сумма равна 20, Y=5, U=−7, V=−5. Теперь (U+V)//4=−12//4=−3, G=5−(−3)=8, R=−5+8=3, B=−7+8=1. Отрицательное деление относится к обратному ходу даже при неотрицательных исходных компонентах. Это нормальная часть алгоритма.

rct_picture.py
def rct(rgb):
    r, g, b = rgb
    return ((r + 2*g + b)//4, b-g, r-g)


def inverse(yuv):
    y, u, v = yuv
    g = y - (u+v)//4
    return (v+g, g, u+g)


for rgb in [(17, 10, 4), (3, 8, 1), (-2, -7, 4)]:
    code = rct(rgb)
    print("RGB", rgb, "RCT", code, "обратно", inverse(code))
    assert inverse(code) == rgb
code = rct((3, 8, 2))
y, u, v = code
print("отрицательная сумма:", u+v, "G верное:", y-(u+v)//4,
      "G при округлении к нулю:", y-int((u+v)/4))
count = 0
for r in range(-4, 5):
    for g in range(-4, 5):
        for b in range(-4, 5):
            assert inverse(rct((r, g, b))) == (r, g, b)
            count += 1
print("точных проверок:", count)
↳  выводpython3 rct_picture.py
RGB (17, 10, 4) RCT (10, -6, 7) обратно (17, 10, 4)
RGB (3, 8, 1) RCT (5, -7, -5) обратно (3, 8, 1)
RGB (-2, -7, 4) RCT (-3, 11, 5) обратно (-2, -7, 4)
отрицательная сумма: -11 G верное: 8 G при округлении к нулю: 7
точных проверок: 729

Программа также проверяет все 729 троек из диапазона −4..4. Это полезная проверка реализации на отрицательных значениях и остатках деления. Само доказательство обратимости находится выше: полный перебор малого диапазона не заменяет алгебраическое объяснение для произвольных целых чисел.

Разбор: одна замена округления портит сразу три компоненты

Возьмём (3,8,2). Прямой ход даёт Y=21//4=5, U=−6, V=−5. Правильный обратный ход использует −11//4=−3 и получает G=8. Если декодер делит к нулю, то берёт −2 и получает G=7. После прибавления разностей он восстановит (2,7,1), а не (3,8,2). Все три компоненты изменились на единицу из-за одного правила.

Другая ошибка - ограничить U до нуля, потому что «цвет не бывает отрицательным». Тогда исходная разность −6 исчезнет и восстановление уже не сможет узнать, насколько синяя компонента меньше зелёной. Ограничивать к диапазону вывода можно лишь в предусмотренной точке алгоритма; это отдельная потенциально необратимая операция, а не безобидное исправление промежуточных чисел.

Что ломается без этого

Сравнивают только Y и решают, что метод уже без потерь. Или записывают отрицательные разности в беззнаковый байт без согласованного представления и получают переполнение. Для промежуточных сумм требуется достаточная разрядность: у восьмибитных компонент выражение R+2G+B может быть больше 255. Python автоматически увеличивает целые числа; фиксированная машинная арифметика требует отдельного расчёта диапазона.

Ещё одна ловушка - спутать RCT с обычным вещественным преобразованием YCbCr. Оба метода уменьшают связь цветовых компонент, но имеют разные коэффициенты, округления и назначение. Подмена одной матрицы другой без изменения обратного хода приводит к неверным цветам даже при идеально сохранённом кодовом потоке.

Зачем это в работе

Ты проверяешь обещание «JPEG 2000 без потерь». Сначала выполни отдельный круговой проход RGB→RCT→RGB, затем подключи целочисленный 5/3, затем кодирование полного набора коэффициентов. Такое разделение показывает, на каком этапе появился первый несовпавший отсчёт. Если цветовой шаг уже неточен, исправление энтропийного кодера не вернёт потерянные значения.

Для серого изображения с одной компонентой цветовой шаг вообще не нужен. А для трёх несвязанных измерительных каналов удобство цветовых разностей может отсутствовать. Статистическая польза преобразования зависит от данных, его целочисленная обратимость - от формул и выполнения условий.

Теперь сам

Декодеру передали Y=−3,U=11,V=5. Найди RGB. Затем объясни, почему точный RCT не спасёт изображение, если после 5/3 удалить детали.

Ответ. (11+5)//4=4, G=−3−4=−7, R=5−7=−2, B=11−7=4. Получили (−2,−7,4). Удалённые детали нужны обратному вейвлетному ходу. Цветовое преобразование обратимо, но оно не восстанавливает информацию, потерянную другой стадией.

Главное

Округление в одном выражении не определяет потери всего преобразования. RCT обратимо благодаря совместному хранению целого среднего и точных разностей; проверяй всю тройку и согласованность обратного хода.

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.