Сжатие изображений в градациях серого с использованием кодирования Хаффмана в MATLAB

Я пытаюсь сжать изображение в оттенках серого, используя кодирование Хаффмана в MATLAB, и пробовал следующий код.

Я использовал изображение в градациях серого размером 512x512 в формате tif. Моя проблема в том, что размер сжатого изображения (длина сжатого кодового слова) становится больше, чем размер несжатого изображения. Степень сжатия становится меньше 1.

clc;
clear all;
A1 = imread('fig1.tif');
[M N]=size(A1);
A = A1(:);
count = [0:1:255]; % Distinct data symbols appearing in sig
total=sum(count);
for i=1:1:size((count)');                  
    p(i)=count(i)/total;
end

[dict,avglen]=huffmandict(count,p) % build the Huffman dictionary
comp= huffmanenco(A,dict);         %encode your original image with the dictionary you just built
compression_ratio= (512*512*8)/length(comp)   %computing the compression ratio

%% DECODING
Im = huffmandeco(comp,dict); % Decode the code
I11=uint8(Im);

decomp=reshape(I11,M,N);
imshow(decomp);

person parvathy    schedule 22.09.2014    source источник


Ответы (1)


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

count = [0:1:255]; % Distinct data symbols appearing in sig
total=sum(count);
for i=1:1:size((count)');                  
    p(i)=count(i)/total;
end

total суммирует [0,255], что неверно. Вы должны вычислить вероятностное распределение вашего изображения. Вместо этого вам следует использовать imhist. Таким образом, вы должны сделать это вместо этого:

count = 0:255;
p = imhist(A1) / numel(A1);

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


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

Если разброс довольно большой, с очень небольшим количеством записей на ячейку, то Хаффман не даст вам никакой экономии на сжатии. Фактически, в результате вы можете получить больший размер. Имейте в виду, что стандарт сжатия TIFF использует Хаффмана только как часть алгоритма. Также выполняется некоторая предварительная и постобработка для дальнейшего уменьшения размера.

В качестве другого примера предположим, что у меня есть изображение, состоящее из [0, 1, 2, ... 255; 0, 1, 2, ..., 255; 0, 1, 2, ..., 255];, у меня есть 3 строки по [0,255], но на самом деле это может быть любое количество строк. Это означает, что вероятность встретить каждый символ равновероятна, или 1/255, что означает, что для каждого символа нам потребуется 8 бит на символ ... что, по сути, является необработанным значением пикселя в любом случае!

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

Если вы хотите, чтобы ваше изображение было сжато необработанным методом Хаффмана, распределение пикселей должно быть искажено. Например, если большая часть яркости на вашем изображении темная или светлая. Если ваше изображение имеет хороший контраст или если интенсивность пикселей равномерна по всему изображению, то Хаффман не даст вам никакой экономии на сжатии.

person rayryeng    schedule 22.09.2014
comment
Я пробовал запустить код. Однако, когда я бегу, как указано в вопросе, то есть count = [0: 1: 255]; % Отчетливые символы данных, появляющиеся в sig total = sum (count); для i = 1: 1: size ((count) '); p (i) = count (i) / total; конец код никогда не заканчивается. Пока я пытался запустить как предложенный в ответе, я получаю сообщение об ошибке: Ошибка при использовании huffmandict (строка 171). Исходные символы повторяются. Ошибка в Хаффмане (строка 10) [dict, avglen] = huffmandict (count, p) Единственный Разница в следующем: я беру изображение RGB и конвертирую его в оттенки серого. Не могли бы вы мне помочь? - person faith; 27.04.2018
comment
@faith count не вычисляется должным образом, когда вы ссылаетесь на исходный вопрос. Я специально указал на это в своем ответе и посоветовал OP использовать вместо этого imhist. Если у вас нет imhist, поскольку он является частью набора инструментов для обработки изображений, используйте accumarray: p = accumarray(double(A(:)) + 1, 1, [256 1]) / numel(A);. A - это входное изображение. - person rayryeng; 27.04.2018
comment
спасибо за быстрый ответ. Я уже пробовал запустить, как вы посоветовали. У меня тоже imhist. Однако я получил ошибку source symbols repeat. - person faith; 27.04.2018
comment
@faith что-то не так с вашей переменной count. Есть дубликаты. Дважды проверьте, правильно ли вы сгенерировали вектор от 0 до 255 с шагом 1 - person rayryeng; 28.04.2018
comment
ну, я думаю, я что-то упускаю. Вы посоветовали сгенерировать count переменную как count=imhist(A1) вместо count=[0:1:255]. Итак, где мне использовать вектор [0:255]? - person faith; 29.04.2018
comment
@faith Я ошибся. count следует оставить без изменений. Это p неверно, и я исправил его в своем посте. Пожалуйста, посмотрите правки. Удачи. - person rayryeng; 29.04.2018