Смотреть что такое "JPEG" в других словарях. Сжатие методом JPEG

«Реализация алгоритмов

JPEG и JPEG2000»

Выполнил:

студент группы 819

Угаров Дмитрий

Принципы работы алгоритмов JPEG и JPEG2000

1. Алгоритм JPEG

JPEG (англ. Joint Photographic Experts Group - объединённая группа экспертов в области фотографии) - является широко используемым методом сжатия фотоизображений. Формат файла, который содержит сжатые данные обычно также называют именем JPEG; наиболее распространённые расширения для таких файлов.jpeg, .jfif, .jpg, .JPG, или.JPE. Однако из них.jpg самое популярное расширение на всех платформах.

Алгоритм JPEG является алгоритмом сжатия с потерей качества .

Область применения

Формат является форматом сжатия с потерями, поэтому некорректно считать что JPEG хранит данные как 8 бит на канал (24 бит на пиксель). С другой стороны , так как данные, подвергающиеся компрессии по формату JPEG и декомпрессированные данные обычно представляются в формате 8 бит на канал, иногда используется эта терминология. Поддерживается также сжатие чёрно-белых полутоновых изображений.

При сохранении JPEG-файла можно указать степень качества, а значит и степень сжатия, которую обычно задают в некоторых условных единицах, например, от 1 до 100 или от 1 до 10. Большее число соответствует лучшему качеству, но при этом увеличивается размер файла. Обыкновенно, разница в качестве между 90 и 100 на глаз уже практически не воспринимается. Следует помнить , что побитно восстановленное изображение всегда отличается от оригинала. Распространённым заблуждением является мнение о том, что качество JPEG тождественно доле сохраняемой информации.

Этапы кодирования

Процесс сжатия по схеме JPEG включает ряд этапов:

1. Преобразование изображения в оптимальное цветовое пространство;

В случае применения цветового пространства яркость/цветность (YCbCr) достигается лучшая степень сжатия. На данном этапе кодирования с помощью соответствующих соотношений цветовая модель RGB преобразуется в YCbCr:

Y = 0.299*R + 0.587*G + 0.114*B

Cb = - 0.1687*R – 0.3313*G + 0.5*B

Cr = 0.5*R – 0.4187*G – 0.0813*B.
Во время декодирования можно использовать соответствующее обратное преобразование:
R = Y + 1.402*Cr

G = Y – 0.34414*Cb – 0.71414*Cr

B = Y + 1.772*Cb.
Примечание, связывающее Y,Cb,Cr в человеческой визуальной системе:

Глаз, особенно сетчатка, имеет как визуальные анализаторы два типа ячеек: ячейки для ночного видения, воспринимающие только оттенки серого (от ярко-белого до темно-черного) и ячейки дневного видения, которые воспринимают цветовой оттенок. Первые ячейки , дающие цвет RGB, обнаруживают уровень яркости, подобный величине Y. Другие ячейки, ответственные за восприятие цветового оттенка, - определяют величину, связанную с цветоразностью.


2. Субдискретизация компонентов цветности усреднением групп пикселей;

Большая часть визуальной информации, к которой наиболее чувствительный глаза человека , состоит из высокочастотных, полутоновых компонентов яркости (Y) цветового пространства YCbCr. Две другие составляющие цветности (Cb и Cr) содержат высокочастотную цветовую информацию, к которой глаз человека менее чувствителен. Поэтому определенная ее часть может быть отброшена и, тем самым, можно уменьшить количество учитываемых пикселей для каналов цветности.

1)тип 4:2:0 (когда изображение разбивается на квадраты 2х2 пикселей и в каждом из них все пиксели получают одинаковые значения каналов Cb и Cr, а яркость Y у остается у каждого своя)

2) тип 4:2:2 (объединение по компонентам цветности происходит только по горизонтали в группах по два пикселя).

3)тип 4: 4: 4 подразумевает, что каждому пикселю в каждой строке соответствует собственное уникальное значение компонентов Y, Cb и Cr. (рис.1 а)

4) тип 4:2:2. Выполнив субдискретизацию сигнала цветности с коэффициентом 2 по горизонтали, мы получим из потока 4: 4: 4 YCbCr поток 4: 2: 2 YCbCr. Запись «4: 2: 2» означает , что в отдельно взятой строке на 2 значения цветности приходятся 4 значения яркости (см. рис.1 б). Сигнал 4: 2: 2 YCbCr очень немного проигрывает по качеству изображения сигналу 4: 4: 4 YCbCr, зато требуемая ширина полосы сокращается на 33% от исходной.

3. Применение дискретных косинусных преобразований для уменьшения избыточности данных изображения;

Основным этапом работы алгоритма является дискретное косинусное преобразование (ДКП или DCT), представляющее собой разновидность преобразования Фурье. Оно применяется при работе с изображениями в различных целях, не только с целью сжатия. Переход к частотному представлению величин значений пикселей позволяет по-другому взглянуть на изображение, обработать его, ну, и, что интересно для нас, сжать. Более того , зная коэффициенты преобразования, мы всегда может произвести обратное действие - вернуть исходную картинку.

DCT непосредственно применяемый к блоку (в нашем случае 8х8 пикселей) изображения будет выглядеть так:

где х, y - пространственные координаты пикселя (0..7) ,

f(x,y) - значения пикселей исходного макроблока (допустим, яркость)

u,v - координаты пикселя в частотном представлении (0..7)

w(u) =1/SQRT(2) при u=0, в остальных случаях w(u)=1 (SQRT - квадратный корень)

w(v) =1/SQRT(2) при v=0, в остальных случаях w(v)=1

Или в матричной форме:

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

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


5. Этап Вторичного Сжатия

Заключительной стадией работы кодера JPEG является кодирование полученной матрицы.

5.1 Зигзагообразная перестановка 64 DCT коэффициентов

Так, после того, как мы выполнили DCT-преобразование над блоком величин 8x8, у нас есть новый блок 8x8. Затем, этот блок 8x8 просматривается по зигзагу подобно этому:

(Числа в блоке 8x8 указывают порядок , в котором мы просматриваем 2-мерную матрицу 8x8)

0, 1, 5, 6,14,15,27,28,

2, 4, 7,13,16,26,29,42,

3, 8,12,17,25,30,41,43,

9,11,18,24,31,40,44,53,

10,19,23,32,39,45,52,54,

20,22,33,38,46,51,55,60,

21,34,37,47,50,56,59,61,

35,36,48,49,57,58,62,63

Как Вы видите, сначала - верхний левый угол (0,0), затем величина в (0,1), затем (1,0), затем (2,0), (1,1), (0,2), (0,3), (1,2), (2,1), (3,0) и т.п.

После того, как мы прошли по зигзагу матрицу 8x8, мы имеем теперь вектор с 64 коэффициентами (0..63) Смысл этого зигзагообразного вектора – в том, что мы просматриваем коэффициенты 8x8 DCT в порядке повышения пространственных частот. Так, мы получаем вектор отсортированный критериями пространственной частоты: первая величина на векторе (индекс 0) соответствует самой низкой частоте в изображении – она обозначается термином DC. С увеличением индекса на векторе, мы получаем величины соответствующие высшим частотам (величина с индексом 63 соответствует амплитуде самой высокой частоте в блоке 8x8). Остальная часть коэффициентов DCT обозначается AC.

5.2 RunLength кодирование нулей (RLE)

Теперь у нас есть вектор с длинной последовательностью нулей. Мы можем использовать это, кодируя последовательные нули. ВАЖНО: Вы увидите позже почему, но здесь мы пропускаем кодировку первого коэффициента вектора (коэффициент DC), который закодирован по-другому. Рассмотрим исходный 64 вектор как 63 вектор (это - 64 вектор без первого коэффициента)

Допустим, мы имеем 57,45,0,0,0,0,23,0,-30,-16,0,0,1,0,0,0,0,0,0, только 0,...,0

Здесь - как RLC JPEG сжатие сделано для этого примера:

(0,57); (0,45); (4,23); (1,-30); (0,-16); (2,1); EOB

Как Вы видите, мы кодируем для каждой величины, отличающейся от 0 количество последовательных ПРЕДШЕСТВУЮЩИХ нулей перед величиной, затем мы добавляем величину. Другое примечание: EOB - короткая форма для Конца Блока , это - специальная кодированная величина (маркер). Если мы достигли в позиции на векторе, от которого мы имеем до конца только нули вектора, мы выделим эту позицию с EOB и завершим сжатие RLC квантованного вектора.

[Заметьте, что если квантованный вектор не оканчивается нулями (имеет последний элемент не 0), мы не будем иметь маркер EOB.]

(0,57); (0,45); (4,23); (1,-30); (0,-16); (2,1); (0,0)

Другая ОСНОВНАЯ вещь: Допустим, где-нибудь на квантованном векторе мы имеем:

57, восемнадцать нулей, 3, 0,0 ,0,0 2, тридцать-три нуля, 895, EOB

Кодирование Хаффмана JPG делает ограничение, по которому число предшествующих нулей должно кодироваться как 4-битовая величина - не может превысить 15.

Так, предшествующий пример должен быть закодирован как:

(0,57); (15,0) (2,3); (4,2); (15,0) (15,0) (1,895), (0,0)

(15,0) - специальная кодированная величина, которая указывает , что там следует за 16 последовательными нулями.

5.3 Конечный шаг - кодирование Хаффмана

Сначала ВАЖНОЕ примечание: Вместо хранения фактической величины, JPEG стандарт определяет, что мы храним минимальный размер в битах, в котором мы можем держать эту величину (это названо категория этой величины) и затем битно кодированное представление этой величины подобно этому:

7,..,-4,4,..,7 3 000,001,010,011,100,101,110,111

15,..,-8,8,..,15 4 0000,..,0111,1000,..,1111

31,..,-16,16,..,31 5 00000,..,01111,10000,..,11111

63,..,-32,32,..,63 6 .

127,..,-64,64,..,127 7 .

255,..,-128,128,..,255 8 .

511,..,-256,256,..,511 9 .

1023,..,-512,512,..,1023 10 .

2047,..,-1024,1024,..,2047 11 .

4095,..,-2048,2048,..,4095 12 .

8191,..,-4096,4096,..,8191 13 .

16383,..,-8192,8192,..,16383 14 .

32767,..,-16384,16384,..,32767 15 .

Впоследствии для предшествующего примера:

(0,57); (0,45); (4,23); (1,-30); (0,-8); (2,1); (0,0)

давайте закодируем только правую величину этих пар, кроме пар, которые являются специальными маркерами подобно (0,0) или (если мы должны иметь) (15,0)

45, аналогично , будет закодирован как (6,101101)

30 -> (5,00001)

И теперь, мы напишем снова строку пар:

(0,6), 111001; (0,6), 101101; (4,5), 10111; (1,5), 00001; (0,4), 0111; (2,1), 1; (0,0)

Пары 2 величин, заключенные в скобки, могут быть представлены в байте, так как фактически каждая из 2 величин может быть представлена в 4-битном кусочке (счетчик предшествующих нулей - всегда меньше, чем 15 и также как и категория [числа закодированные в файле JPG - в области -32767..32767]). В этом байте, старший кусочек представляет число предшествующих нулей, а младший кусочек - категорию новой величины, отличной от 0.

Конечный шаг кодировки состоит в кодировании Хаффмана этого байта, и затем записи в файле JPG , как поток из битов, кода Хаффмана этого байта, сопровождающийся битовым представлением этого числа.

Например, для байта 6 (эквивалент (0,6)) у нас есть код Хаффмана = 111000;

21 = (1,5) - 11111110110

4 = (0,4) - 1011

33 = (2,1) - 11011

0 = EOB= (0,0) - 1010

Конечный поток битов записанных в файле JPG на диск для предшествующего примера 63 коэффициентов (запомните, что мы пропустили первый коэффициент) -

111000 111001 111000 101101 1111111110011001 10111 11111110110 00001

1011 0111 11011 1 1010
Достоинства и недостатки

К недостаткам формата следует отнести то, что при сильных степенях сжатия дает знать о себе блочная структура данных, изображение «дробится на квадратики» (каждый размером 8x8 пикселей). Этот эффект особенно заметен на областях с низкой пространственной частотой (плавные переходы изображения, например, чистое небо). В областях с высокой пространственной частотой (например, контрастные границы изображения), возникают характерные «артефакты» - иррегулярная структура пикселей искаженного цвета и/или яркости. Кроме того, из изображения пропадают мелкие цветные детали. Не стоит также забывать и о том, что данный формат не поддерживает прозрачность.

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

2. Алгоритм JPEG2000

Алгоритм JPEG-2000 разработан той же группой экспертов в области фотографии, что и JPEG. Формирование JPEG как международного стандарта было закончено в 1992 году. В 1997 стало ясно, что необходим новый, более гибкий и мощный стандарт, который и был доработан к зиме 2000 года.

Основные отличия алгоритма в JPEG 2000 от алгоритма в JPEG заключаются в следующем:

1)Лучшее качество изображения при сильной степени сжатия. Или, что то же самое , большая степень сжатия при том же качестве для высоких степеней сжатия. Фактически это означает заметное уменьшение размеров графики "Web-качества", используемой большинством сайтов.

2)Поддержка кодирования отдельных областей с лучшим качеством. Известно, что отдельные области изображения критичны для восприятия человеком (например, глаза на фотографии), в то время как качеством других можно пожертвовать (например, задний план). При "ручной" оптимизации увеличение степени сжатия проводится до тех пор, пока не будет потеряно качество в какой-то важной части изображения. Сейчас появляется возможность задать качество в критичных областях, сжав остальные области сильнее, т.е. мы получаем еще большую окончательную степень сжатия при субъективно равном качестве изображения.

3)Основной алгоритм сжатия заменен на wavelet. Помимо указанного повышения степени сжатия это позволило избавиться от 8-пиксельной блочности, возникающей при повышении степени сжатия. Кроме того, плавное проявление изображения теперь изначально заложено в стандарт (Progressive JPEG, активно применяемый в Интернет, появился много позднее JPEG).

4)Для повышения степени сжатия в алгоритме используется арифметическое сжатие. Изначально в стандарте JPEG также было заложено арифметическое сжатие, однако позднее оно было заменено менее эффективным сжатием по Хаффману, поскольку арифметическое сжатие было защищено патентами. Сейчас срок действия основного патента истек , и появилась возможность улучшить алгоритм.

5)Поддержка сжатия без потерь. Помимо привычного сжатия с потерями новый JPEG теперь будет поддерживать и сжатие без потерь. Таким образом, становится возможным использование JPEG для сжатия медицинских изображений, в полиграфии, при сохранении текста под распознавание OCR системами и т.д.

6)Поддержка сжатия однобитных (2-цветных) изображений. Для сохранения однобитных изображений (рисунки тушью, отсканированный текст и т.п.) ранее повсеместно рекомендовался формат GIF, поскольку сжатие с использованием ДКП весьма неэффективно к изображениям с резкими переходами цветов. В JPEG при сжатии 1-битная картинка приводилась к 8-битной, т.е. увеличивалась в 8 раз, после чего делалась попытка сжимать, нередко менее чем в 8 раз. Сейчас можно рекомендовать JPEG 2000 как универсальный алгоритм.

7)На уровне формата поддерживается прозрачность. Плавно накладывать фон при создании WWW страниц теперь можно будет не только в GIF, но и в JPEG 2000. Кроме того, поддерживается не только 1 бит прозрачности (пиксель прозрачен/непрозрачен), а отдельный канал , что позволит задавать плавный переход от непрозрачного изображения к прозрачному фону.

Кроме того, на уровне формата поддерживаются включение в изображение информации о копирайте, поддержка устойчивости к битовым ошибкам при передаче и широковещании, можно запрашивать для декомпрессии или обработки внешние средства (plug-ins), можно включать в изображение его описание, информацию для поиска и т.д.

Этапы кодирования

Процесс сжатия по схеме JPEG2000 включает ряд этапов:

1. Преобразование изображения в оптимальное цветовое пространство.
На данном этапе кодирования с помощью соответствующих соотношений цветовая модель RGB преобразуется в YUV:

При декомпрессии применяется соответствующее обратное преобразование:

2. Дискретное вейвлет преобразование.

Дискретное wavelet преобразование (DWT) также может быть двух видов - для случая сжатия с потерями и для сжатия без потерь.

Это преобразование в одномерном случае представляет собой скалярное произведение соответствующих коэффициентов на строку значений. Но т.к. многие коэффициенты нулевые, то прямое и обратное вейвлет преобразование можно записать следующими формулами (для преобразования крайних элементов строки используется ее расширение на 2 пикселя в каждую сторону, значения которых симметричны с значениями элементов строки относительно ее крайних пикселей):
y(2*n + 1) = x(2*n + 1) - (int)(x(2*n) + x(2*n + 2)) / 2

y(2*n) = x(2*n) + (int)(y(2*n - 1) + y(2*n + 1) + 2) / 4

и обратное

x(2*n) = y(2*n) - (int)(y(2*n - 1) + y(2*n + 1) + 2) / 4

x(2*n + 1) = y(2*n + 1) + (int)(x(2*n) + x(2*n + 2)) / 2.

3. Квантование коэффициентов.

Так же как и в алгоритме JPEG , при кодировании изображения в формат JPEG2000 используется квантование. Дискретное вейвлет преобразование, так же как и его аналог, сортирует коэффициенты по частотности. Но, в отличие от JPEG, в новом формате матрица квантования одна на все изображение.


4. Этап Вторичного Сжатия

. Как и в JPEG, в новом формате последним этапом алгоритма сжатия является кодирование без потерь. Но, в отличие от предыдущего формата, в JPEG2000 используется алгоритм арифметического сжатия.

Программная реализация

В данной работе реализованы алгоритмы JPEG и JPEG2000. В обоих алгоритмах реализовано прямое и обратное кодирование (отсутствует последний этап вторичного сжатия). Расчет JPEG происходит довольно долго (порядка 30 секунд) в связи «прямым» высчитыванием DCT. Если потребуется увеличить скорость работы , следует изначально вычислить матрицу DCT(изменения производить в классе DCT).

Перейдем к рассмотрению программы:


  1. После запуска выводится окно, где

и сможете его сохранить , нажав кнопку (2) и введя желаемое название в диалоговом окне.

  • При достаточно большом Quality Factor изображение сильно измениться. Если это JPEG алгоритм то будут ярко выражены блоки размера 8x8.(в случае алгоритма JPEG2000, блочного деления не будет)
  • До:

    После:



    Голосование: 22, 4

    Введение

    На сегодняшний день качественная, высокопроизводительная компьютерная графика является одной из важнейших задач разработчиков программного обеспечения. Огромные средства вкладываются в разработку эффективного оборудования для различных графических и мультимедийных систем. В последние годы появились компьютеры способные в реальном времени воспроизводить сложнейшие визуальные образы, давно превзошедшие по качеству телевизионные или полиграфические. Это способствовало появлению огромного количества программ, использующих эти возможности: компьютерные игры, видео-приложения, 3d-анимация и т.д. Но у всех этих программ есть одна отличительная особенность: графические данные, с которыми они работают, занимают очень много места.

    В то время уже были достаточно распространены среди пользователей персональных компьютеров такие графические форматы, как BMP, PCX, GIF. Но даже уменьшение объема графической информации в два раза оказалось недостаточным для современных графических систем. В связи с этим с конца 80х годов две крупнейшие в мире организации стандартов CCITT и ISO объединили свои усилия для выработки единого стандарта формата графического файла, сжатого с потерями. Новый стандарт получил свое название JPEG по имени группы разработчиков Joint Photographic Experts Group.

    Сделаем небольшое замечание: JPEG прежде всего является методом сжатия. Его нельзя рассматривать в качестве полноценного стандарта представления изображений. Поэтому в нем не задаются такие специфические параметры изображения, как геометрический размер пикселя, пространство цветов или чередование битовых строк. То же можно сказать и о JPEG2000, и о JPEG-LS — это методы сжатия, а не полноценные стандарты.

    1. JPEG

    Рассмотрим алгоритм работы простейшего кодера JPEG с потерями. Весь процесс состоит из следующих основных этапов:


    Рис. 1.
    • Препроцессинг — этап, на котором выполняется предварительная обработка изображения, приводящая его к удобному для последующего кодирования виду.
    • Дискретное косинусное преобразование (ДКП) используется кодером JPEG для преобразования изображения от его пространственного представления к спектральному.
    • Округление (квантование) — этап, на котором происходит основная потеря информации за счет округления несущественных, высокочастотных ДКП-коэффициентов.
    • Сжатие — кодирование полученных данных стандартными методами (кодирование повторов, арифметическое кодирование и т.д.)

    Если изображение содержит более одной компоненты, то они кодируются по отдельности. В связи с этим, на данном этапе выполняется перевод графического изображения из его компонентного представления в цветоразностное, яркостное представление (ICT — Irreversible Color Transform). В связи с тем, что человеческий глаз более восприимчив к яркостному сигналу, чем к цветовому, это преобразование позволит добиться больших результатов сжатия при меньших визуальных потерях. Далее будет рассматриваться кодирование одной отдельной компоненты.

    Рис. 2.

    Рис. 3.

    Помимо ICT преобразования, на данном этапе исходное изображение разбивается на малые квадратные блоки и выполняется сдвиг основания значений цвета относительно нуля для корректного пространственного представления изображения: -> [-2 p-1 , 2 p-1 - 1] . Эти шаги важны для эффективной работы кодера на следующем этапе.

    1.2. ДКП

    Являясь ключевым шагом алгоритма сжатия, дискретное косинусное преобразование (далее ДКП) представляет собой разновидность преобразования Фурье и, также как и последнее, имеет обратное преобразование (ОДКП). Если рассматривать изображение как совокупность пространственных волн, где оси X и Y соответствуют ширине и высоте картинки, а по оси Z откладываются значения цвета соответствующих пикселей, то можно перейти от пространственного представления картинки к ее спектральному представлению и обратно. ДКП преобразует матрицу пикселей размера N x N в матрицу частотных коэффициентов соответствующего размера.



    Рис. 4.

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

    Из формул (рис. 4) видно, что вычисление одного элемента результирующей матрицы требует O(N 2) времени, поэтому почти невозможно выполнить преобразование всей матрицы целиком. Группа разработчиков JPEG предложила оптимальный вариант решения этой проблемы: разбивать исходную матрицу на квадраты стандартного размера 8x8 и выполнять преобразование каждого из них. Использование блоков большего размера позволит улучшить качество сжатия, но не до бесконечности, так как слишком мала вероятность того, что сильно отдаленные точки похожи друг на друга.

    Стоит отметить, что в ходе вычислений используется только 32 заранее вычисленных значения косинусов, что позволяет заметно увеличить скорость работы преобразования. Это уже, несомненно, приводит к частичной потери информации, но ее объемы относительно несущественны.

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

    1.3. Округление

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

    Округлением называется процесс уменьшения объема информации, необходимого для хранения матрицы ДКП, с частичной потерей точности. По стандарту JPEG для этого используется матрица округления (МО). Каждому элементу исходной матрицы ДКП соответствует элемент МО. Результирующая матрица получается делением исходной матрица на МО. При этом низкочастотным значениям в матрице ДКП соответствуют меньшие коэффициенты МО, что позволяет оставлять более значимую, низкочастотную информацию и отбрасывать менее важную высокочастотную. В связи с тем, что низкочастотные компоненты сосредоточены в левом верхнем углу матрицы ДКП, значения МО растут слева направо и сверху вниз.


    3 5 7 9 11 13 15 17
    5 7 9 11 13 15 17 19
    7 9 11 13 15 17 19 21
    9 11 13 15 17 19 21 23
    11 13 15 17 19 21 23 25
    13 15 17 19 21 23 25 27
    15 17 19 21 23 25 27 29
    17 19 21 23 25 27 29 31

    Пример матрицы округления с фактором качества равным 2.

    Результаты округления и качества восстановленного изображения напрямую зависят от выбранной матрицы округления. Стандарт JPEG позволяет использовать любую МО, однако ISO в ходе долгих экспериментальных тестирований разработала набор матриц, позволяющих добиться оптимальных результатов.

    1.4. Сжатие

    Последний этап работы алгоритма кодирования JPEG — это сжатие. После обработки матрицы ДКП с помощью МО, в результирующей матрице появляется большое количество нулей, особенно в высокочастотной области (правый нижний угол).

    Первым шагом значение в левом верхнем углу результирующей матрицы заменяется на относительное. Так как соседние блоки изображения похожи друг на друга, то кодирование очередного элемента (0,0) через разницу с предыдущим будет более эффективным. Вторым шагом является непосредственно применение алгоритма кодирования повторов (LZW), для обработки большого количества подряд идущих нулей. Экспериментальные тестирования показали, что наилучших результатов можно добиться, если обходить матрицу зигзагом, как показано на рисунке ниже.

    Рис. 5.

    Наконец, на третьем и заключительном шаге полученный результат сжимается, как обычные данные с помощью алгоритма Хаффмана или арифметического кодирования в зависимости от реализации. Этот этап носит название «кодирование энтропии» (в терминологии JPEG).

    1.5. Декодирование

    Так как ДКП является преобразованием Фурье, к нему существует обратное дискретное косинусное преобразование (ОДКП). Алгоритм декодирования повторяет алгоритм кодирования в обратном порядке.

    2. JPEG2000

    Изначально новый стандарт разрабатывался как база для будущего стандарта сжатия без потерь JPEG-LS, но позднее был отвергнут в связи с появлением более эффективных алгоритмов. В связи с развитием технологий стандарт JPEG постепенно терял свою актуальность. Разработчики JPEG2000 надеялись создать стандарт, который исправил бы многие ошибки уже существующих стандартов. Среди их задач были:

    • Устранение неэффективного сжатия в области низких частот . Существующие алгоритмы неплохо справлялись со сжатием среднечастотных и высокочастотных областей, но в области низких частот они показывали плохие результаты.
    • Сжатие с потерями и без потерь . На момент разработки не существовало стандарта, позволяющего сжимать с потерями и без потерь в едином сжимающем потоке.
    • Обработка больших изображений . Существующие алгоритмы не позволяли эффективно сжимать изображения размером более 64Kx64K без разбиения на тайлы.
    • Единая структура алгоритма сжатия . Текущая реализация JPEG поддерживала 44 модификации, большая часть которых была специфичной для некоторых приложений и не поддерживалась большей частью декодеров.
    • Помехоустойчивость . Во время разработки JPEG сетевые технологии не были еще достаточно развиты, и проектировщики JPEG не задумывались над помехоустойчивостью при передаче изображений по небезопасным каналам и возможностью восстановления изображения в случае его повреждения в результате передачи.
    • Компьютерно-сгенерированные изображения . Исходные алгоритмы неплохо работали на цифровых фотографиях и изображениях, полученных с помощью цифровой фотокамеры или сканера, но неэффективно обрабатывали изображения, созданные на компьютере, например, с помощью графических редакторов.
    • Сложные документы . JPEG показывал очень плохие результаты при обработке сложных двумерных изображений (в частности изображений текста).

    На следующей диаграмме представлены основные шаги работы кодера JPEG2000.


    Рис. 6.


    Рис. 7.

    В отличие от JPEG кодер JPEG2000 не требует разбиения изображения на малые квадратные блоки, так как используемое в ходе работы алгоритма ДВП (дискретное вейвлетное преобразование) работает на фрагментах любого размера. С другой стороны иногда, в случае, если объем памяти, доступный кодеру для работы, меньше, чем объем памяти, необходимый для кодирования всего изображения, выполняется разбиение изображения на квадратные тайлы, которые кодируются независимо друг от друга. Далее будет рассматриваться кодирование одного тайла. Остальные шаги аналогичны JPEG.

    Рис. 8.

    2.2. ДВП

    JPEG2000 использует дискретное вейвлетное преобразование (Discrete Wavelet Transformation), для разбиения изображения на высокочастотные и низкочастотные области. ДВП обрабатывает каждую строку и столбец исходного изображения с помощью частотного фильтра.

    Рис. 9.

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

    • LL – низкие частоты по строкам и столбцам
    • HL – высокие частоты по строкам и низкие по столбцам
    • LH – низкие частоты по строкам и высокие по столбцам
    • HH – высокие частоты по строкам и столбцам

    По стандарту количество этапов может быть от 0 до 32. Для обычного изображения используют от 4-х до 8-ми этапов. На каждом следующем этапе обрабатывается только низкочастотная область (LL), так как в высокочастотных областях обычно не содержится важной информации.


    Рис. 10.

    Рис. 11.

    2.3. Округление

    Для округления коэффициентов ДВП используется постоянный квантователь с мертвой зоной. (рис. 14) Для каждого фрагмента используется постоянное значение шага округления для всех коэффициентов этого фрагмента. Формула вычисления округленных значений представлена на рисунке 12. Здесь y - исходное значение коэффициента, sign(y) определяет знак коэффициента, а Δb - значение шага округления. Мертвая зона квантователя - это интервал диапазоном 2Δb около нуля, она дает большее количество нулей на выходе.

    2.4. Кодирование

    Кодирование полученных округленных коэффициентов выполняется поблочно. По стандарту JPEG2000 непосредственно перед кодированием фрагменты разбиваются на достаточно малые блоки (например, размером 32x32 или 64x64) так, чтобы все блоки одного фрагмента были одинакового размера. Разбиение на блоки выполняется для того, чтобы осуществить более гибкую организацию сжатой информации для повышения помехоустойчивости и так далее.


    Рис. 16.

    В JPEG2000 каждый блок кодируется по отдельности. Алгоритм кодирования обходит матрицу коэффициентов округления каждого блока полосами, как показано на рисунке 17. Блоки разбиваются на блоки с номинальной высотой 4. Далее полосы сканируются сверху вниз, а колонки в каждой полосе обходятся слева направо.


    Рис. 17.

    В процессе кодирования коэффициенты в блоке виртуально представляются в виде битовых плоскостей. Одну из таких плоскостей составляют знаки коэффициентов; остальные плоскости соответствуют различным разрядам величин коэффициентов (положение бита в плоскости соответствует положению коэффициента в блоке). Кодирование осуществляется по плоскостям: сначала кодируется плоскость, соответствующая старшему разряду коэффициентов, затем следующая по убыванию, и т.д. Может случиться так, что N наиболее приоритетных битовых плоскостей (НПБ-плоскостей), не будут содержать единиц. В этом случае НПБ-плоскостью становится первая по порядку плоскость, содержащая хотя бы одну единицу. Предшествующие ей пустые плоскости опускаются при кодировании, а информация о их количестве заносится в заголовок блока.

    Арифметическое кодирование основано на контекстно-зависимой модели. Контекст формируется как функция от значений битов, окружающих кодируемый бит. Каждая битовая плоскость, кроме НБП, обычно кодируется в три прохода. Во время первого кодового прохода осуществляется распространение информации о значимости коэффициентов. Во время кодирования каждому коэффициенту в кодируемом блоке ставится в соответствие параметр значимость. Коэффициент называется значимым, если в уже закодированных на дынный момент битовых плоскостях, присутствует хотя бы один ненулевой разряд данного коэффициента.

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

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

    Во время третьего, заключительного прохода выполняется обработка тех битов, которые не были обработаны во время первого и второго проходов. Во время этого заключительного этапа арифметическое кодирование применяется совместно с групповым кодированием.

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

    2.5. Организация данных

    Важным преимуществом рассматриваемого стандарта является возможность доступа к отдельным элементам изображения без полного декодирования его представления. Обеспечивается такая возможность, во-первых, разбиением исходного изображения на непересекающиеся области (тайлы), которые кодируются как отдельные изображения, а во-вторых, представлением кода отдельного тайла в виде частей (слоев), каждая из которых является суммарным кодом коэффициентов, соответствующих некоторой его (тайла) области. Слои в свою очередь делятся на так называемые пакеты, содержащие код блоков коэффициентов на разных уровнях декомпозиции. Для того, чтобы декодировать какую-либо область изображения, достаточно определить, каким тайлам она принадлежит, и какие слои, относящиеся к этим тайлам, содержат код блоков коэффициентов, необходимых для восстановления требуемой области.



    Рис. 20.

    Безусловно, «удобное» представление изображения не может быть выгодным с точки зрения эффективности сжатия. Действительно, с уменьшением размера структурных элементов (тайлов, областей тайлов, образующих слои и др.) эффективность сжатия несколько снижается. Стандарт в данном случае оставляет нам выбор: с одной стороны, мы имеем возможность получать информационные представления, позволяющие достаточно быстро извлекать и редактировать части изображения, с другой стороны, стандарт не препятствует созданию информационных представлений, эффективных по объему.

    Для обеспечения помехоустойчивости и удобства доступа к информации в стандарте JPEG2000 предусмотрена система маркеров и маркерных сегментов. Маркерные сегменты содержат в себе параметры фрагментов информации ограниченных маркерами. Данные, начинающиеся с маркера, могут быть корректно проинтерпретированы без какой-либо дополнительной информации (это не означает возможность восстановления целого по фрагментам), что обеспечивает возможность частичного восстановления изображения, представление которого было повреждено. Введение элементов помехоустойчивости дает зеленый свет использованию стандарта во всевозможных телекоммуникационных приложениях.

    Достижение высокого качества сжатия, безусловно, было одной из главных задач при создании стандарта, и здесь разработчики добились явного прогресса. Стандарт JPEG2000 превосходит по эффективности стандарт JPEG примерно в 2 раза при сжатии с потерями и на 5-20% при сжатии без потерь. Конечно, эффективность при сжатии без потерь в данном случае оказывается не такой высокой, как, скажем, у стандарта JPEG-LS, однако она вполне приемлема. Что же касается эффективности сжатия с потерями, здесь стандарт позволяет получать результаты, близкие к наилучшим на сегодняшний день результатам для подобного рода методов.

    3. JPEG-LS

    Формат JPEG-LS был основан на формате LOCO-I (Low Complexity Lossless Compression for Images). Алгоритм сжатия без потерь LOCO-I, принятый за основу при разработке стандарта JPEG-LS, впервые предусматривал не только lossless, но и near lossless режим (сжатие с ограниченными, задаваемыми пользователем потерями). В отличие от JPEG2000 lossless mode, JPEG-LS получился по-настоящему удачным: при большей эффективности сжатия новый стандарт обеспечивает высокую скорость компрессии/декомпрессии и не слишком требователен к ресурсам компьютера.

    Важно понимать, что формат JPEG-LS:

    • не является расширением или модификацией метода JPEG;
    • не использует ни DCT (ДКП), ни арифметическое кодирование;
    • использует слабое квантование только в моде «почти без потерь»

    3.1. Введение основных понятий и принципов работы

    Сжатие данных без потерь состоит из двух отдельных независимых частей: моделирования (modeling) и кодирования (coding). Определим некоторые термины, которые будем активно использовать в дальнейшем:

    Кодер (Encoder) «отвечает» за процесс кодирования, а именно: получает на вход исходное изображение в цифровом формате и все необходимые параметры, определенные стандартом, и с помощью специального набора процедур создает набор данных, содержащих сжатое изображение Декодер (Decoder) «отвечает» за процесс декодирования и преобразование фрагментов, а именно: получая на вход данные со сжатым изображением и все необходимые параметры, выводит реконструированное изображение

    Декодер JPEG-LS мало отличается от кодера, поэтому этот алгоритм сжатия можно назвать почти симметричным. Приведем упрощенную схему, показывающую принципы кодирования:



    Рис. 21.

    Немного информации об исходном изображении : как ниже показано на схеме (рис. 22), исходное изображение может состоять из Nf компонент. Каждая компонента Ci содержит двумерный массив пикселей (samples) из x i столбцов и y i строк. Размеры компонент зависят от двух параметров: X и Y, где X - максимум среди x i значений, а Y - максимум среди y i значений всех компонент. (В стандарте JPEG-LS целая глава посвящена отличиям в работе с мультикомпонентными изображениями по сравнению с однокомпонентными, однако в этой статье мы остановимся лишь на работе однокомпонентными изображениями).



    Рис. 22.

    На рисунке отмечена ориентация каждой компоненты: top (верх), bottom (низ), left (лево), и right (право). Порядок, в котором пиксели подаются на обработку процедурам кодирования, определен так: left-to-right (слева направо) и top-to-bottom (сверху вниз) по компоненте.

    Для прогнозирования текущего пикселя x используются пиксели контекста a, b, c, d. В зависимости от контекста кодер выбирает моду: серийную (run mode) или регулярную (regular mode) . Серийная мода выбирается, если y и z скорее всего будут совпадать, регулярная – в противном случае. Сделаем тут замечание, связанное с наличием опции «почти без потерь» : при включении этой опции серийная мода будет выбрана, если y и z будут почти совпадать в соответствии с параметром допустимого отклонения NEAR.

    В случае использования серийной моды мы начинаем просмотр текущей строки с пикселя x и находим наибольшую длину серии пикселей, совпадающих с контекстным пикселем a. Таким образом, в пределах текущей строки мы получаем серию одинаковых пикселей, совпадающих по значению с известным нам пикселем a. Осталось только закодировать длину серии. (Это делается с помощью массива J из 32 элементов). Вы уже могли догадаться, что при включенной опции «почти без потерь» выбирается серия пикселей, близких к a с помощью параметра NEAR.

    Теперь рассмотрим наши действия в случае использования регулярной моды. Для вычисления прогноза пикселя x (Px) используются величины пикселей a, b и c. Затем вычисляется так называемая ошибка прогноза (Errval). Ее значение равно разности значения x и Px. Errval корректируется некоторым членом, зависящим от контекста, а затем кодируется с помощью кодов Голомба. Код Голомба зависит от a, b, c, d и Errval этих же пикселей, которые хранятся в специальных массивах A и N. При включении опции «почти без потерь» перед кодированием ошибка прогноза ещё дополнительно квантуется.


    Рис. 23.

    3.2. Кодер

    В основном JPEG-LS используется как метод сжатия информации без потерь, следовательно, восстановленный файл изображения обычно идентичен исходному файлу. В моде почти без потерь исходный и реконструированный образ могут отличаться. Будем обозначать реконструированный пиксель Rp, а исходный пиксель - p.

    На стадии инициализации кодер выполняет следующие операции:

    • Вычисляются параметры RANGE = floor((MAXVAL + 2 * NEAR) / (2 * NEAR + 1)) + 1, qbpp = ceil(log RANGE), bpp = max(2, ceil(log(MAXVAL + 1))), LIMIT = 2 * (bpp + max(8, bpp)) . (В случае кодирования без потерь NEAR = 0, RANGE = MAXVAL + 1 . Если включена мода «почти без потерь», NEAR > 0). MAXVAL и NEAR - параметры, задаваемые приложением, реализующим алгоритм.
    • Инициализируются индексные массивы N , A , B и C . Поясним их предназначение: N используется для хранения частоты вхождения каждого контекста, A — для накопления величины ошибки предсказания, B — для вычисления систематического отклонения, C — для хранения величин корректирования ошибки прогноза.
    • Инициализируются переменные для серийной моды (run mode) RUNindex=0 и J = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9,10,11,12,13,14,15} .
    • Инициализируются две вспомогательные переменные Nn , Nn=0 для кодирования пикселя прерывания серии.

    Введем некоторые функции и переменные, которые будут использоваться в дальнейшем:

    GetNextSample() Функция: получает информацию о следующем пикселе исходного изображения и устанавливает соответствующие значения переменных x, a, b, c, d, Ix, Ra, Rb, Rc, Rd . Если считанный пиксель лежит в конце строки, то GetNextSample() устанавливает EOLine = 1 . Во всех остальных случаях EOLine = 0 . Значения Ra, Rb, Rc, Rd наследуют свои значения от вычисленного прежде значения Rx . EOLine Глобальная переменная: устанавливается функцией GetNextSample(): равна 1, если текущий пиксель - последний в строке, равна 0 - в противном случае. AppendToBitStream(a,b) Функция: добавляет неотрицательное число в двоичной форме в поток из закодированных битов, используя b бит. Наиболее значимые биты добавляются первыми. Quantize(a) Функция: используется для квантования ошибки предсказания в режиме «почти без потерь». ComputeRx() Функция: возвращает реконструированное значение Rx для текущего пикселя (использует квантованную «ошибку предсказания»).

    Из приведенного изображения (рис. 23) ясно, что немалую роль в кодировании пикселя x играют пиксели a, b, c и d. Попробуем разобраться, что происходит, когда эти пиксели отсутствуют. Так при кодировании верхней строки контекстные пиксели с, b и d отсутствуют, поэтому их значения считаются нулевыми. Если текущий пиксель находится в начале или конце строки, то пиксели a, с или d не определены. В этом случае для a и d используется реконструированное значение Rb пикселя b (или нуль для верхней строки), а для c используется реконструированное значение a при кодировании первого символа предыдущей строки. Таким образом, кодер должен выполнить часть работы декодера, реконструируя некоторые пиксели.

    Кодер начинает работу со следующих трех шагов:

    После установления контекста Q, кодер прогнозирует пиксель х. Сначала производится вычисление прогноза Рх с помощью так называемого «правила края» (edge-detecting predictor):

    if (Rc > = max(Ra, Rb)) Px = min(Ra, Rb);
    else {
    if (Rc <= min(Ra, Rb))
    Px= max(Ra, Rb);
    else
    Px = Ra + Rb - Rc;
    }

    Поясним суть «правила края». Для этого рассмотрим случай b < а. При этом условии «правило края» выбирает b в качестве прогноза х во многих случаях, когда вертикальный край изображения находится непосредственно слева от х. Аналогично, пиксель а выбирается в качестве прогноза х во многих случаях, когда горизонтальный край находится непосредственно над х. Если край не обнаруживается, то «правило края» вычисляет прогноз в виде а + b - с, что имеет простую геометрическую интерпретацию. Если каждый пиксель является точкой трехмерного пространства, то прогноз а + b - с помещает Рх на ту же плоскость, что и точки а, b и с.

    Следующий шаг — корректировка прогноза (prediction correction from the bias) с помощью числа SIGN (зависящего от трех зонных чисел Qi), корректирующих величин C(Q) (выводимых из систематических смещений, и здесь не обсуждаемых) и параметра MAXVAL.

    if (SIGN == +1)
    Px = Px + C(Q);
    else
    Px = Px - C(Q);

    If (Px > MAXVAL)
    Px = MAXVAL;
    else if (Px < 0)
    Px = 0;

    После того, как прогноз Рх найден, кодер вычисляет ошибку прогноза Errval в виде разности х - Рх, но меняет знак, если величина SIGN отрицательная.

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

    if (Errval > 0)
    Errval = (Errval + NEAR) / (2 * NEAR + 1);
    else
    Errval = - (Errval - NEAR) / (2 * NEAR + 1);

    При этом используется параметр NEAR, однако имеются некоторые детали, которые здесь не приводятся. Основной шаг реконструкции состоит в нахождении Rx = Px + SIGN * Errval * (2 * NEAR + 1) .

    Ошибка прогноза (после возможного квантования) претерпевает сокращение области (modulo reduction). (После этого она готова для главного этапа кодирования).

    if (Errval < 0)
    Errval = Errval + RANGE;
    if (Errval >= ((RANGE + 1) / 2))
    Errval = Errval - RANGE;

    Коды Голомба (основной параметр был обозначен через b). В JPEG-LS этот параметр обозначается m. Если число m уже выбрано, то код Голомба неотрицательного целого числа n состоит из двух частей: унарного кода целой части числа n/m и двоичного представления n mod m . Этот код является идеальным для целых чисел, имеющих геометрическое распределение (то есть, когда вероятность числа n равна (1 - r) * r n , 0 < r < 1) . Для каждого геометрического распределения найдется такое число m, что код Голомба, построенный по m, имеет наименьшую возможную среднюю длину. Простейший случай, когда m равно степени 2 (m = 2 k), приводит к простым операциям кодирования/декодирования. Код числа n состоит в этом случае из k младших разрядов числа n, перед которыми стоит унарный код числа, составленного из остальных старших разрядов числа n. Этот специальный код Голомба обозначается через G(k) .

    Для примера вычислим код G(2) числа n = 19 = 10011 2 . Поскольку k = 2, то m = 4. Начнем с двух младших разрядов, 11 2 , числа n. Они равны 3, что то же самое, что n mod m (3 = 19 mod 4) . Оставшиеся старшие разряды, 100 2 дадут число 4, которое равно целой части n/m (19/4 = 4.75). Унарный код 4 равен 00001, значит код G(2) числа n = 19 равен 00001|11.

    На практике всегда имеется конечное число неотрицательных целых чисел. Обозначим наибольшее число через I. Наибольшая длина G(0) равна I + 1, а поскольку I может быть велико, желательно лимитировать размер кода Голомба. Это делается с помощью специального кода Голомба LG(k, glimit) , который зависит от двух параметров k и glimit. Сначала следует сформировать число q из самых старших разрядов числа n. Если q < glimit- - 1 , то код LG(k, glimit) совпадает с кодом LG(k]. В противном случае, приготавливается унарный код числа glimit - ceil(log I) - 1 (то есть, glimit - ceil(log I) - 1 нулей, за которыми стоит единственная 1). Это действует как код esc, после которого стоит двоичный код n - 1 из ceil(log I) бит.

    Ошибки прогнозов не обязательно являются положительными числами. Они равны некоторым разностям, которые могут быть нулевыми или отрицательными. Однако коды Голомба были построены для положительных чисел. Поэтому перед кодированием отрицательные значения ошибок следует отразить на множество неотрицательных чисел. Для этого используется отображение:
    MErrval =
    2 * Errval если Errval >= 0,
    2 * |Errval| если Errval < 0.

    Это отображение перемежает отрицательные и положительные величины в виде последовательности 0, -1, +1, -2, +2, -3,... .

    В нижеприведенной таблице перечислены некоторые ошибки прогноза, отображенные значения и их коды LG(2, 32) при условии, что алфавит имеет размер 256 (то есть, I = 255 и ceil(log I) = 8).

    Таблица: ошибки прогнозов, отображения и коды LG(2, 32)

    Ошибка прогноза Отображенное значение Код
    0 0 1 00
    -1 1 1 01
    1 2 1 10
    -2 3 1 11
    2 4 01 00
    -3 5 01 01
    3 6 01 10
    -4 7 01 11
    4 8 001 00
    -5 9 001 01
    5 10 001 10
    -6 11 001 11
    6 12 0001 00
    ...
    50 100 000000000000
    000000000001
    01100011

    Теперь необходимо обсудить выбор параметра k для кодов Голомба. Это делается адаптивно. Параметр k зависит от контекста, и его значение обновляется каждый раз, когда обнаруживается пиксель с этим контекстом. Вычисление k можно выразить простой строкой:
    for (k=0; (N[Q]< где А и N - массивы индексов от 0 до 364. В этой формуле используется контекст Q в качестве индекса двух массивов. В начале k инициализируется нулем, а затем совершается цикл. На каждой итерации цикла элемент массива N[Q] сдвигается влево на k разрядов и сравнивается с A[Q]. Если сдвинутое значение N[Q] больше или равно A[Q], то выбирается текущее значение k. В противном случае, k увеличивается на 1, и тест повторяется.

    После нахождения числа k, ошибка прогноза Errval преобразуется с помощью в число MErrval, которое кодируется с помощью кода LG(k, LIMIT). Число LIMIT является параметром. Обновление массивов А и N (вместе со вспомогательным массивом B) иллюстрирует следующий фрагмент кода (параметр RESET устанавливается приложением):

    B[Q] = B[Q] + Errval * (2 * NEAR + 1);
    A[Q] = A[Q] + abs(Errval);
    if (N[Q] == RESET) {
    A[Q] = A[Q]>>1;
    B[Q] = B[Q]>>1;
    N[Q] = N[Q]>>1;
    }
    N[Q] = N[Q] + 1;

    Теперь поговорим о просчитывании систематического отклонения прогноза. Значение C[Q], корректирующее прогноз, должно быть обновлено в конце кодирования пикселя x. Для этого необходимы две переменные — B[Q] и N[Q]. N[Q] — это количество вхождений контекста Q с момента инициализации. B[Q] — систематическое отклонение, позволяющее обновлять значение C[Q] как максимум один раз за итерацию. Итак, прогнозирующее значение C[Q] вычисляется в соответствии со следующим кодом:

    if (B[Q] <= -N[Q]) {
    B[Q] = B[Q] + N[Q];
    if (C[Q] > MIN_C)
    C[Q] = C[Q] - 1;
    if (B[Q] <= -N[Q])
    B[Q] = -N[Q] + 1;
    }
    else if (B[Q] > 0) {
    B[Q] = B[Q] - N[Q];
    if (C[Q] < MAX_C)
    C[Q] = C[Q] + 1;
    if (B[Q] > 0)
    B[Q] = 0;
    }

    Константы MIN_C и MAX_C — это минимальное и максимальное возможное значение индексного массива C, равные соответственно -128 и 127.

    Кодирование в серийной моде делается иначе. Напомним, что кодер выбирает эту моду, когда обнаруживает последовательные пиксели x, чьи значения Ix совпадают и равны восстановленной величине Ra контекстного пикселя a. Для опции «почти без потерь» пиксели в серии должны иметь значения Ix, которые удовлетворяют неравенству |Ix - Ra| <= NEAR . Серия не должна выходить за пределы текущей строки. Длина серии кодируется (сам пиксель кодировать не нужно, поскольку он равен Ra), и если конец серии находится раньше конца строки, то после ее закодированной длины будет сразу записан код следующего пикселя (который прерывает серию). Две основные задачи кодера в этой моде состоят

    1. в отслеживании серии и кодировании ее длины;
    2. в кодировании пикселя, прервавшего серию.

    Отслеживание серии можно проводить следующим образом:

    RUNval = Ra;
    RUNcnt = 0;
    while (abs(Ix - RUNval) <= NEAR) {
    RUNcnt = RUNcnt + 1;
    Rx = RUNval;
    if (EOLine == 1)
    break;
    else
    GetNextSample();
    }

    Поясним некоторые введенные величины: RUNcnt — это счетчик повторяющихся пикселей (для серийной моды), а RUNval - текущее значение реконструированного повторяющегося пикселя.

    Опишем процесс кодирования серий. Первый фрагмент кода описывает кодирование для сегментов серий длины rm:

    while (RUNcnt >= (1< AppendToBitStream(1, 1);
    RUNcnt = RUNcnt - (1< if (RUNindex < 31))
    RUNindex = RUNindex + 1;
    }

    Следующий же код иллюстрирует кодирование для сегментов серий длины меньше, чем rm:

    if (EOLine == 0) {
    AppendToBitStream(0, 1);
    AppendToBitStream(RUNcnt, J);
    if (RUNindex > 0)) {
    RUNindex = RUNindex - 1;
    }
    else if (RUNcnt > 0)
    AppendToBitStream(1, 1);

    Здесь кодер использует таблицу J, состоящую из 32 записей, обозначаемых rk. J инициализируется величинами
    0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15 .

    Для каждого значения rk обозначим rm = 2 rk . Числа rm (их всего 32) называются порядком кода. Первые 4 величины rk имеют rm = 2 0 = 1. Для второй четверки rm = 2 1 = 2, а для следующей четверки rm = 2 2 = 4. Для последнего числа rm = 2 15 = 32768. Кодер выполняет процедуру, описанную , для нахождения длины серии, которая сохраняется в переменной RUNlen . Затем эта переменная кодируется разбиением на слагаемые, величины которых равны последовательным числам rm. Например, если RUNlen=6 , то его представляют в виде 6 = 1 + 1 + 1 + 1 + 2 с помощью первых пяти чисел rm. Оно кодируется с помощью 5 бит. Запись производится инструкцией AppendToBitStream(l,l) . Каждый раз, когда пишется 1, соответствующая величина rm вычитается из RUNlen . Если RUNlen было равно в начале 6, то она последовательно уменьшается до 5, 4, 3, 2 и 0.

    Может случиться, что длина RUNlen серии не равна целой сумме чисел rm. Например, RUNlen = 7 . В этом случае в качестве кода записывается пять битов 1, за которыми следует префиксный бит и остаток от RUNlen (в нашем примере это 1), который запишется в файл в виде числа из rk бит (текущее значение rk из нашего примера равно 2). Эта последняя операция выполняется вызовом процедуры AppendToBitStream (RUNcnt, J) . Префиксным битом служит 0, если серия прерывается в строке другим пикселем. Если же серия идет до конца строки, то префиксный бит равен 1.

    Вторая основная задача кодера, состоящая в кодировании пикселя прерывания серии, делается аналогично кодированию текущего пикселя. Обсудим детали её реализации.

    Рассмотрим ситуацию, когда ход кодирования прерван концом строки пикселей: как будет кодироваться новый пиксель, вызывающий прерывание? Этот вопрос решается кодированием разницы между значением Ix в текущей позиции x и реконструированным значением пикселей a или b (напомним, что это соседние пиксели по отношению к x - см. рис. 23). В этом случае рассматриваются две различные ситуации: первая, когда abs(Ra - Rb) <= NEAR , вторая - в противном случае. По сути кодирование пикселя прерывания серии происходит теми же методами, что и кодирование нового пикселя в регулярной моде с тем лишь дополнением, что Ix должно отличаться от Ra на величину большую NEAR, иначе ход кодирования будет продолжен. Опишем операции, которые должны быть выполнены:

    if (abs(Ra - Rb) <= NEAR)
    RItype = 1;
    else
    RItype = 0;
    if (RItype == 1)
    Px = Ra;
    else
    Px = Rb;
    Errval = Ix - Rb;

    Фрагмент кода выше определяет индекс RItype и ошибку предсказания для пикселя x. Затем следует в случае необходимости изменить знак Errval, а для опции «почти без потерь» также провести квантование ошибки предсказания:

    if ((RItype == 0) && (Ra > Rb)) {
    Errval = -Errval;
    SIGN = -1;
    else
    SIGN = 1;
    if (NEAR > 0) {
    Errval = Quantize(Errval);
    Rx = ComputeRx();
    }
    else
    Rx = Ix;
    Errval = ModRange(Errval, RANGE);

    Теперь вычислим вспомогательную переменную TEMP, которая будет использоваться для вычисления параметра k в кодах Голомба.

    if (RItype == 0)
    TEMP = A;
    else
    TEMP = A + (N>>1);

    Установим Q = RItype + 365 . Параметр k для кодов Голомба будем вычислять следующим образом: for (k=0; (N[Q]<

    if (Errval < 0) {
    Nn[Q] = Nn[Q] + 1;
    A[Q] = A[Q] + ((EMErrval + 1 -RItype)>>1);
    if (N[Q] == RESET) {
    A[Q] = A[Q]>>1;
    N[Q] = N[Q]>>1;
    Nn[Q] = Nn[Q]>>1;
    }
    N[Q] = N[Q] + 1;

    На этом и завершим описание кодера JPEG-LS. Отметим, что оно, безусловно, неполное, но мы и не ставили перед собой цели — скопировать стандарт этого метода. Все опущенные детали вы сможете найти в стандарте. Сейчас же перейдем к краткому описанию принципов работы декодера.

    3.3. Декодер

    Как упоминалось ранее, метод JPEG-LS почти симметричный, поэтому копировать с небольшими изменениями описание кодера мы не будем — эту информацию можно прочитать и в стандарте. Остановимся лишь на том, как происходит декодирование в серийной моде. После того, как вычислены все величины для текущего пикселя, считывается новый бит R из потока битов. Если он равен 1, то:

    1. Изображение дополняется 2 J|RUNindex| пикселями со значением Ra.
    2. Если на предыдущем шаге изображение уже было дополнено 2 J|RUNindex| пикселями и RUNindex < 31, то RUNindex увеличивается на 1. Если последний пиксель в строке ещё не декодирован, то мы снова считываем биты, в противном случае переходим к вычислению всех требуемых величин.

    Если же бит равен 0, то:

    1. Считывается J|RUNindex| бит из битового потока и преобразовывается в число, а изображение дополняется пикселями со значениями Ra в количестве, соответствующем вычисленному числу.
    2. Если RUNindex > 0, то RUNindex уменьшается на 1.
    3. Декодируется пиксель прерывания серии и снова начинается вычисление всех необходимых величин.

    3.4. Формат файла

    Сжатый файл состоит:

    • из сегментов данных, содержащих коды Голомба и длины серий;
    • из сегментов маркеров (информация необходимая декодеру);
    • из сегмента «остальных» маркеров (некоторые зарезервированные маркеры JPEG).

    Маркером здесь мы называем байт из единиц, за которым следует специальный код, сигнализирующий о начале нового сегмента. Если за маркером следует байт, у которого старший бит равен 1, то этот байт является началом сегмента маркеров. В противном случае, начинается сегмент данных.

    3.5. Коды Голомба

    Мы уже не раз упоминали коды Голомба. Что же это такое? Код Голомба неотрицательного целого числа «может быть эффективным кодом Хаффмана». Он зависит от выбора некоторого параметра b. Принцип кодирования таков:

    • вычисляются две величины
      q = floor((n - 1) / b) и
      r = n - qb - 1 ;
    • происходит построение кода из двух частей: первая часть — q в унарном коде, вторая часть — двоичное выражение для r , состоящее из floor(log 2 b) бит для малых остатков и из ceil(log 2 b) бит для больших.

    Мы не приводим математическое обоснование использования кодов Голомба в JPEG-LS, отметим лишь, что, если входной поток данных состоит из целых чисел, причем вероятность числа n равна P(n) = (1 - p) n - 1 p (0 <= p <= 1) , то коды Голомба будут оптимальными кодами для этого потока данных, если выбрать параметр b следующим образом:
    (1 - p) b + (1 - p) b + 1 <= 1 <= (1 - p) b - 1 + (1 - p) b .

    3.6. Заключение

    Формат JPEG-LS разрабатывался, прежде всего, для хранения изображений в медицинских целях, то есть для тех случаев, когда важно иметь большое изображение без малейших потерь качества. Как уже говорилось, за основу был взят формат LOCO-I, разработанный в стенах «HP Labs». Затем он был доработан совместными усилиями «HP» и «Mitsubishi». Обе компании разрешили использовать их патенты на этот формат без оплаты лицензии, поэтому JPEG-LS можно встретить и в обычных программах для PC.

    Поясню на собственном примере. Может быть и поможете мне в понимании некоторых вещей. Задача поставленная передо мной самим собой следующая. Передать кадр (по команде) из WEB камеры в память сотового телефона с последующей передачей на другой сотовый. Из Вашей статьи не понятно, на какой формат следует забазироваться, доступность алгоритма. Далее - сосинусное преобразование - только поверхностное толкование, а где посмотреть детальный алгоритм с конкретным примером (скажете учи мат. анализ, но и там почти нет конкретных примеров, а если есть, то пропущены целые куски расчетов. Может есть конкретная методичка, так сошлитесь. Структуру организации файла вообще выкинули и даже ссылок не указали. "В получаемой матрице низкочастотные компоненты расположены ближе к левому верхнему углу, а более высокочастотные смещаются вправо вниз", мне кажется, что она так делается, а не получается (может ошибаюсь!).

    Вопрос: как из JPG кадра отловить например только нужную информацию для дальнейшего декодирования в разрешении экрана телефона, не применяя PC, используя МК. Достаточно черно-белого варианта кадра. На какие FFxx надо обратить внимание и записать только ту информацию. Где взять структуру кадра WEB камеры. Я понимаю, что вопрос сложен, многопланов. Что например на МК не сделать расшифровку кадра и сжать затем с нужным разрешением, но вот вырезать хотя-бы верхний угол с нужным форматом это наверное можно.

    Буду благодарен за информацию.

    Что умею = программировать на VB, МК. Самостоятельная действующая интерактивная разработка управлением по сот.телефону несколькими реле, аудиоконтроль с использованием сотового телефона.

    >> Вторым шагом является непосредственно применение >>алгоритма кодирования повторов (LZW)

    может, RLE?

    Разумеется, на этом шаге JPEG (см. контект), — RLE. Спасибо за обнаружение погрешности.

    Область применения

    Формат является форматом сжатия с потерями, поэтому некорректно считать что JPEG хранит данные как 8 бит на канал (24 бит на пиксел). С другой стороны, так как данные, подвергающиеся компрессии по формату JPEG и декомпрессированые данные обычно представляются в формате 8 бит на канал, иногда используется эта терминология. Поддерживается также сжатие чёрно-белых полутоновых изображений.

    При сохранении JPEG-файла можно указать степень качества, а значит и степень сжатия, которую обычно задают в некоторых условных единицах, например, от 1 до 100 или от 1 до 10. Большее число соответствует лучшему качеству, но при этом увеличивается размер файла. Обыкновенно, разница в качестве между 90 и 100 на глаз уже практически не воспринимается. Следует помнить, что восстановленное из формата JPEG изображение не является точной копией оригинала. Распространённым заблуждением является мнение о том, что качество JPEG тождественно доле сохраняемой информации.

    Широкая поддержка формата JPEG разнообразным ПО нередко приводит к кодированию в JPEG изображений, для того не предназначенных - безо всякого выигрыша по степени сжатия в сравнении с правильно сделанными PNG или GIF, но с прискорбными последствиями для качества. Например, попытка записать в JPEG изображение, содержащее мелкие контрастные детали (особенно, цветные) приведёт к появлению характерных хорошо заметных артефактов даже при высокой «степени качества».

    Сжатие

    При сжатии изображение преобразуется из цветового пространства RGB в YCbCr (YUV). Следует отметить, что стандарт JPEG (ISO/IEC 10918-1) никак не регламентирует выбор именно YCbCr, допуская и другие виды преобразования (например, с числом компонентов, отличным от трёх), и сжатие без преобразования (непосредственно в RGB), однако спецификация JFIF (JPEG File Interchange Format, предложенная в 1991 году специалистами компании C-Cube Microsystems, и ставшая в настоящее время стандартом де-факто) предполагает использование преобразования RGB->YCbCr.

    После преобразования RGB->YCbCr для каналов изображения Cb и Cr, отвечающих за цвет, может выполняться "прореживание" (subsampling, которое заключается в том, что каждому блоку из 4 пикселов (2х2) яркостного канала Y ставятся в соответствие усреднённые значения Cb и Cr (схема прореживания "4:2:0". При этом для каждого блока 2х2 вместо 12 значений (4 Y, 4 Cb и 4 Cr) используется всего 6 (4 Y и по одному усреднённому Cb и Cr). Если к качеству восстановленного после сжатия изображения предъявляются повышенные требования, прореживание может выполняться лишь в каком-то одном направлении — по вертикали (схема "4:4:0") или по горизонтали ("4:2:2"), или не выполняться вовсе ("4:4:4").

    Стандарт допускает также прореживание с усреднением Cb и Cr не для блока 2х2, а для четырёх расположенных последовательно (по вертикали или по горизонтали) пикселов, то есть для блоков 1х4 или 4х1 (схема "4:1:1"). Допускается также использование различных типов прореживания для Cb и Cr, но на практике такие схемы встречаются исключительно редко.

    Далее, яркостный компонент Y и отвечающие за цвет компоненты Cb и Cr разбиваются на блоки 8х8 пикселов. Каждый такой блок подвергается дискретному косинусному преобразованию (ДКП). Полученные коэффициенты ДКП квантуются (для Y, Cb и Cr в общем случае используются разные матрицы квантования) и пакуются с использованием кодов Хаффмана. Стандарт JPEG допускает также использование значительно более эффективного арифметического кодирования, однако, из-за патентных ограничений (патент на описанный в стандарте JPEG арифметический QM-кодер принадлежит IBM) на практике оно не используется.

    Матрицы, используемые для квантования коэффициентов ДКП, хранятся в заголовочной части JPEG-файла. Обычно они строятся так, что высокочастотные коэффициенты подвергаются более сильному квантованию, чем низкочастотные. Это приводит к огрублению мелких деталей на изображении. Чем выше степень сжатия, тем более сильному квантованию подвергаются все коэффициенты.

    Разновидности схем сжатия JPEG

    Стандарт JPEG предусматривает два основных способа представления кодируемых данных.

    Наиболее распространённым, поддерживаемым большинством доступных кодеков, является последовательное (sequential JPEG) представление данных, предполагающее последовательный обход кодируемого изображения поблочно слева направо, сверху вниз. Над каждым кодируемым блоком изображения осуществляются описанные выше операции, а результаты кодирования последовательно помещаются в выходной поток в виде единственного «скана» (массива кодированных данных). Основной или «базовый» (baseline) режим кодирования допускает только такое представление. Расширенный (extended) режим наряду с последовательным допускает также прогрессивное (progressive JPEG) представление данных.

    В случае progressive JPEG сжатые данные записываются в выходной поток в виде набора сканов, каждый из которых описывает изображение полностью с всё большей степенью детализации. Это достигается либо путём записи в каждый скан не полного набора коэффициентов ДКП, а лишь какой-то их части: сначала — низкочастотных, в следующих сканах — высокочастотных (метод «spectral selection» т.е. спектральных выборок), либо путём последовательного, от скана к скану, уточнения коэффициентов ДКП (метод «successive approximation», т.е. последовательных приближений). Такое прогрессивное представление данных оказывается особенно полезным при передаче сжатых изображений с использованием низкоскоростных каналов связи, поскольку позволяет получить представление обо всём изображении уже после передачи незначительной части JPEG-файла.

    Обе описанные схемы (и sequential, и progressive JPEG) базируются на ДКП и принципиально не позволяют получить восстановленное изображение абсолютно идентичным исходному. Однако, стандарт допускает также сжатие, не использующее ДКП, а построенное на основе линейного предсказателя (lossless, т.е. «без потерь», JPEG), гарантирующее полное, бит-в-бит, совпадение исходного и восстановленного изображений. При этом коэффициент сжатия для фотографических изображений редко достигает 2, но гарантированное отсутствие искажений в некоторых случаях оказывается востребованным. Заметно большие степени сжатия могут быть получены при использовании не имеющего, несмотря на сходство в названиях, непосредственного отношения к стандарту JPEG ISO/IEC 10918-1 (ITU T.81 Recommendation) метода сжатия JPEG-LS, описываемого стандартом ISO/IEC 14495-1 (ITU T.87 Recommendation).

    Синтаксис и структура

    Файл JPEG содержит последовательность маркеров, каждый из которых начинается с байта 0xFF, свидетельствующего о начале маркера, и байта — идентификатора. Некоторые маркеры состоят только из этой пары байтов, другие же содержат дополнительный данные, состоящие из двухбайтового поля с длиной информационной части маркера (включая длину этого поля, но за вычетом двух байтов начала маркера т.е. 0xFF и идентификатора) и собственно данных.

    Основные маркеры JPEG
    Маркер Байты Длина Назначение

    После вычисления всех коэффициентов DCT их необходимо проквантовать. На этом шаге происходит отбрасывание части информации (небольшие потери происходят и на предыдущем шаге из-за конечной точности вычислений на компьютере). Каждое число из матриц коэффициентов DCT делится на специальное число из «таблицы квантования», а результат округляется до ближайшего целого. Как уже отмечалось, необходимо иметь три такие таблицы для каждой цветовой компоненты. Стандарт JPEG допускает использование четырех таблиц, и пользователь может выбрать любую из этих таблиц для квантования компонентов цвета. Все 64 числа из таблицы квантования являются параметрами JPEG. В принципе, пользователь может поменять любой коэффициент для достижения большей степени сжатия. На практике весьма сложно экспериментировать с таким большим числом параметров, поэтому программное обеспечение JPEG использует два подхода:

    1. Таблица квантования, принятая по умолчанию. Две такие таблицы, одна для компоненты светимости (и для градации серого цвета), а другая для хроматических компонент, являются результатом продолжительного исследования со множеством экспериментов, проделанных комитетом JPEG. Они являются частью стандарта JPEG и воспроизведены в табл. 3.50. Видно, как коэффициенты QC таблиц растут при движении из левого верхнего угла в правый нижний угол. В этом отражается сокращение коэффициентов DCT, соответствующих высоким пространственным частотам.

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

    Светимость

    Если квантование сделано правильно, то в блоке коэффициентов DCT останется всего несколько ненулевых коэффициентов, которые будут сконцентрированы в левом верхнем углу матрицы. Эти числа являются выходом алгоритма JPEG, но их следует еще сжать перед записью в выходной файл. В литературе по JPEG это сжатие называется «энтропийным кодированием», детали которого будут разбираться в § 3.7.5. Три технических приема используется при энтропийном кодировании для сжатия целочисленных матриц 8x8.

    3. 64 числа выстраиваются одно за другим как при сканировании зигзагом (см. рис. 3.5а). В начале стоят ненулевые числа, за которыми обычно следует длинный хвост из одних нулей. В файл выводятся только ненулевые числа (после надлежащего кодирования) за которыми следует специальный код ЕОВ (end-of-block, конец блока). Нет необходимости записывать весь хвост нулей (можно также сказать, что ЕОВ кодирует длинную серию нулей).

    Пример : В табл. 3.51 приведен список гипотетических коэффициентов DCT, из которых только 4 не равны нулю. При зигзагообразном упорядочении этих чисел получается последовательность коэффициентов:

    Табл. 3.51. Квантованные коэффициенты.

    А как написать подпрограмму для считывания элементов матрицы по зигзагу? Простейший способ состоит в ручном прослеживании этого пути и в записи результата в массив структур zz, в котором каждая структура состоит из пары координат клеток, через которые проходит зигзагообразный путь (см. рис. 3.52).

    Если компоненты структуры zz обозначить zz.r и zz.с, то путь по зигзагу можно совершить с помощью следующего цикла

    4. Ненулевые коэффициенты преобразования сжимаются по методу Хаффмана (см. § 3.7.5).

    5. Первое из этих чисел (коэффициент DC, см. стр. 145) обрабатывается отдельно от других чисел (коэффициентов АС).

    Рис. 3.52. Координаты зигзагообразного пути.



    
    Top