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

# теория · шаг 2 из 7

ДКП: смена координат перед сжатием

Коротко

Дискретное косинусное преобразование, ДКП, описывает блок через веса простых колебаний. Постоянная составляющая называется DC, остальные AC описывают изменения внутри блока. В ортонормированной записи точное преобразование обратимо и сохраняет сумму квадратов. Число коэффициентов равно числу пикселов. Сжатие возникает позже: многие коэффициенты плавного изображения малы, поэтому их удобно квантовать и кодировать. Для шума или мелкой шахматной структуры такое сосредоточение величин может оказаться слабее.

Если объясняешь роль DC и AC, читаешь формулу преобразования и отличаешь её от квантования, переходи к «Теперь сам».

Как думаешь, один цвет требует 64 разных чисел

В блоке 8×8 все отсчёты после подготовки яркости равны 3. Можно хранить число 3 шестьдесят четыре раза. А можно сказать: «весь блок постоянный» и записать только величину постоянной составляющей. Для произвольного блока нужны ещё поправки, которые описывают полосы, края и мелкие изменения.

Преобразование не знает заранее, какие поправки понадобятся. Оно вычисляет весь набор из 64 коэффициентов. Если картинка гладкая, многие окажутся малыми; если в каждом соседнем пикселе резкое изменение, значимыми могут быть и высокие частоты. Название преобразования не гарантирует сжатия каждого входа.

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

Цвет краски можно описать количеством красного, зелёного и синего. Та же точка в пространстве описывается через другую тройку согласованных координат. ДКП делает похожую замену: вместо значения в каждой позиции сообщает, сколько каждого заранее известного узора надо сложить.

Чтобы восстановить блок, декодер должен знать те же узоры и нормировку. Если кодировщик умножил один узор на дополнительный коэффициент, а декодер этого не учёл, получит другой блок. Поэтому формулу нельзя сочетать с произвольно выбранным «обратным ДКП» из другого соглашения.

Механизм: веса косинусных узоров

Косинус угла можно представить как горизонтальную координату точки единичной окружности. Значения меняются плавно от 1 к −1 и обратно; выбор разных частот даёт узоры с разным числом смен знака. Для строки длины N зададим C[u,x]=α(u)·cos(π(2x+1)u/(2N)), где α(0)=√(1/N), а при u>0 α(u)=√(2/N). Индексы u и x идут от 0 до N−1.

Коэффициент строки равен F[u]=Σx C[u,x]·p[x]: умножаем отсчёты на веса узора и складываем. Узоры ортонормированы: сумма квадратов весов каждого равна 1, а сумма попарных произведений разных узоров равна 0. Поэтому коэффициенты не смешиваются: обратная формула p[x]=Σu C[u,x]·F[u] возвращает исходные отсчёты.

Для квадратного блока используем те же веса сначала по одной координате, затем по другой: F[u,v]=ΣxΣy C[u,x]·C[v,y]·p[x,y]. Частота u относится к первой координате, v ко второй. Коэффициент F[0,0] сопоставлен постоянному узору, поэтому называется DC; остальные называют AC. При N=8 каждый вес постоянного узора равен 1/√8, значит DC=сумма пикселов/8.

В обычной восьмибитной компоненте перед ДКП вычитают 128 из отсчётов. Это сдвиг диапазона к нулю, а не потеря информации: при восстановлении 128 прибавляют. Постоянный блок яркости 131 после этого имеет значение 3 и DC=24. Без указания сдвига одна цифра DC не определяет среднюю исходную яркость.

Правило

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

Для одного двумерного блока прямое вычисление четырёх вложенных сумм требует O(N⁴) арифметических действий. Два последовательных одномерных преобразования дают O(N³), а быстрые факторизации сокращают работу ещё сильнее. В JPEG размер N фиксирован 8; это сравнение объясняет устройство алгоритма, а не асимптотику по числу блоков картинки. По всей картинке число таких фиксированных блоков пропорционально числу пикселов.

Разбор: четыре коэффициента вместо знакомой ступеньки

В программе блок 4×4 содержит одинаковые строки [10,10,14,14]. Среднее равно 12, поэтому DC=4·12=48. Изменений между строками нет, а вдоль строки есть ступенька; ненулевые AC остаются только в первой строке матрицы коэффициентов. Код использует меньший блок ради читаемости чисел; нормативный базовый JPEG применяет ДКП 8×8.

dct_picture.py
from math import cos, pi, sqrt


def transform(block, inverse=False):
    n = len(block)
    basis = []
    for u in range(n):
        scale = sqrt(1 / n) if u == 0 else sqrt(2 / n)
        basis.append([scale * cos(pi * (2 * x + 1) * u / (2 * n))
                      for x in range(n)])
    result = [[0.0] * n for _ in range(n)]
    for i in range(n):
        for j in range(n):
            for a in range(n):
                for b in range(n):
                    if inverse:
                        factor = basis[a][i] * basis[b][j]
                    else:
                        factor = basis[i][a] * basis[j][b]
                    result[i][j] += block[a][b] * factor
    return result


def show(row):
    return [0 if abs(x) < 1e-9 else round(x, 6) for x in row]


block = [[10, 10, 14, 14] for _ in range(4)]
coeff = transform(block)
for row in coeff:
    print(show(row))
restored = transform(coeff, inverse=True)
error = max(abs(block[i][j] - restored[i][j])
            for i in range(4) for j in range(4))
energy = sum(x * x for row in block for x in row)
energy_coeff = sum(x * x for row in coeff for x in row)
print("энергия:", energy, round(energy_coeff))
print("ошибка обратного преобразования:", f"{error:.9f}")
constant = transform([[3] * 8 for _ in range(8)])
print("DC постоянного блока 8x8:", round(constant[0][0]))
↳  выводpython3 dct_picture.py
[48.0, -7.391036, 0, 3.061467]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
энергия: 2368 2368
ошибка обратного преобразования: 0.000000000
DC постоянного блока 8x8: 24

Матрица содержит DC 48, горизонтальные коэффициенты около −7,391 и 3,061, остальные нули с учётом точности вывода. Энергия, то есть сумма квадратов, совпала: 2368. Последний ноль в выводе ошибки означает округление показателя до девяти знаков, а не доказательство абсолютно точной арифметики float. Для постоянного блока 8×8 отдельно получен DC=24.

Разбор: зачем сохраняется сумма квадратов

Для двух отсчётов ортонормированная пара имеет вид a=(x+y)/√2, d=(x−y)/√2. Раскрой квадраты: a²+d²=((x+y)²+(x−y)²)/2=x²+y². Перекрёстные слагаемые уничтожились. В ДКП тот же эффект обеспечивается нулевыми попарными произведениями разных узоров и единичной длиной каждого.

Если ошибка двух коэффициентов равна 3 и 4, её сумма квадратов 25. После точного обратного ортонормированного преобразования сумма квадратов ошибок пикселов тоже 25. Но затем пикселы обычно округляют до целых и ограничивают диапазоном 0…255. После этих дополнительных шагов равенство нужно проверять заново; оно относится именно к линейному преобразованию.

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

Говорят, что ДКП «удалило высокие частоты», хотя программа лишь вычислила их веса. Само по себе оно ничего не удаляет. Или отождествляют «низкую частоту» с «малым коэффициентом»: большой край может дать существенную высокочастотную компоненту. Размер коэффициента определяется изображением, номер частоты - выбранным узором.

Ещё одна ошибка - использовать формулу DC=среднее для нашей нормировки 8×8. Здесь DC=8·среднее подготовленного блока. В других реализациях масштаб могут перенести в таблицу квантования, но кодировщик и декодер должны делать это согласованно.

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

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

Теперь сам

Все 64 подготовленных отсчёта блока 8×8 равны −2. Каковы DC и остальные коэффициенты? Если сохранить только DC, потеряется ли информация именно на таком блоке?

Ответ. DC=8·(−2)=−16, все AC равны нулю. Сохранение точного DC достаточно для этого постоянного блока. Это свойство конкретного входа; на произвольном блоке удаление ненулевых AC меняет изображение.

Главное

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

Комментарии

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

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

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