Прогнозирующее кодирование на C # для сжатия изображений

#c# #image-processing #encoding

#c# #обработка изображений #кодирование

Вопрос:

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

Насколько я понимаю, в стандарте JPEG без потерь каждый пиксель прогнозируется как средневзвешенное значение соседних 4 пикселей, уже встречающихся в растровом порядке (три выше и один слева). например, попытка предсказать значение пикселя a на основе предыдущих пикселей, x, слева, а также над a :

 x x x
x a 
  

Затем вычислите и закодируйте остаток (разницу между прогнозируемым и фактическим значением).

Но чего я не понимаю, так это того, что если средние 4 соседних пикселя не кратны 4, вы получите дробь, верно? Следует ли игнорировать эту долю? Если да, будет ли правильное кодирование 8-битного изображения (сохраненного в byte[] ) чем-то вроде:

 public static void Encode(byte[] buffer, int width, int height)
{
    var tempBuff = new byte[buffer.Length];

    for (int i = 0; i < buffer.Length; i  )
    {
        tempBuff[i] = buffer[i];
    }

    for (int i = 1; i < height; i  )
    {
        for (int j = 1; j < width - 1; j  )
        {
            int offsetUp = ((i - 1) * width)   (j - 1);
            int offset = (i * width)   (j - 1);

            int a = tempBuff[offsetUp];
            int b = tempBuff[offsetUp   1];
            int c = tempBuff[offsetUp   2];
            int d = tempBuff[offset];
            int pixel = tempBuff[offset   1];

            var ave = (a   b   c   d) / 4;
            var val = (byte)(ave - pixel);
            buffer[offset   1] = val;
        }
    }
}

public static void Decode(byte[] buffer, int width, int height)
{
    for (int i = 1; i < height; i  )
    {
        for (int j = 1; j < width - 1; j  )
        {
            int offsetUp = ((i - 1) * width)   (j - 1);
            int offset = (i * width)   (j - 1);

            int a = buffer[offsetUp];
            int b = buffer[offsetUp   1];
            int c = buffer[offsetUp   2];
            int d = buffer[offset];
            int pixel = buffer[offset   1];

            var ave = (a   b   c   d) / 4;
            var val = (byte)(ave - pixel);
            buffer[offset   1] = val;
        }
    }
}
  

Я не понимаю, как это действительно уменьшит энтропию? Как это поможет еще больше сжать мои изображения без потерь?

Спасибо за любое разъяснение

Редактировать:

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

введите описание изображения здесь

Ответ №1:

Да, просто усеките. Не имеет значения, потому что вы сохраняете разницу. Это уменьшает энтропию, потому что вы сохраняете только небольшие значения, многие из них будут равны -1, 0 или 1. Кстати, в вашем фрагменте есть пара отдельных ошибок.

Комментарии:

1. Неужели? не могли бы вы указать, какие части являются отдельными? Это было бы превосходно 🙂 Кроме того, говоря о значениях -1, как бы я обработал отрицательные значения? Просто пусть они зацикливаются на 255?

2. Хорошо, теперь я понимаю, вы избегаете границы. Да, пусть переполняется.

3. Хорошо, я быстро сравнил гистограммы и понимаю, о чем вы говорите! Я опубликую картинку того, как это выглядит. Спасибо за объяснение!