Дискретное целое вейвлет-преобразование Daub 5/3 лифтинга - PullRequest
5 голосов
/ 12 января 2010

Я пытаюсь выполнить целочисленное поднятие 5/3 на изображении Лены.Я следил за публикацией Уолкера, Нгуена и Чена «Система с низким энергопотреблением и малым энергопотреблением для вейвлет-сжатия» ( Link , активная с 7 октября 2015 г.).

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

Моя функция такова:

bool PerformHorizontal( Col24* pPixelsIn, Col24* pPixelsOut, int width, int pixelPitch, int height )
{
    const int widthDiv2 = width / 2;
    int y   = 0;
    while( y < height )
    {
        int x = 0;
        while( x < width )
        {
            const int n     = (x)       + (y * pixelPitch);
            const int n2    = (x / 2)   + (y * pixelPitch);

            const int s     = n2;
            const int d     = n2 + widthDiv2;

            // Non-lifting 5 / 3
            /*pPixelsOut[n2 + widthDiv2].r  = pPixelsIn[n + 2].r - ((pPixelsIn[n + 1].r + pPixelsIn[n + 3].r) / 2) + 128;
            pPixelsOut[n2].r                = ((4 * pPixelsIn[n + 2].r) + (2 * pPixelsIn[n + 2].r) + (2 * (pPixelsIn[n + 1].r + pPixelsIn[n + 3].r)) - (pPixelsIn[n + 0].r + pPixelsIn[n + 4].r)) / 8;

            pPixelsOut[n2   + widthDiv2].g  = pPixelsIn[n + 2].g - ((pPixelsIn[n + 1].g + pPixelsIn[n + 3].g) / 2) + 128;
            pPixelsOut[n2].g                = ((4 * pPixelsIn[n + 2].g) + (2 * pPixelsIn[n + 2].g) + (2 * (pPixelsIn[n + 1].g + pPixelsIn[n + 3].g)) - (pPixelsIn[n + 0].g + pPixelsIn[n + 4].g)) / 8;

            pPixelsOut[n2   + widthDiv2].b  = pPixelsIn[n + 2].b - ((pPixelsIn[n + 1].b + pPixelsIn[n + 3].b) / 2) + 128;
            pPixelsOut[n2].b                = ((4 * pPixelsIn[n + 2].b) + (2 * pPixelsIn[n + 2].b) + (2 * (pPixelsIn[n + 1].b + pPixelsIn[n + 3].b)) - (pPixelsIn[n + 0].b + pPixelsIn[n + 4].b)) / 8;*/

            pPixelsOut[d].r = pPixelsIn[n + 1].r    - (((pPixelsIn[n].r         + pPixelsIn[n + 2].r)   >> 1) + 127);
            pPixelsOut[s].r = pPixelsIn[n].r        + (((pPixelsOut[d - 1].r    + pPixelsOut[d].r)      >> 2) - 64);

            pPixelsOut[d].g = pPixelsIn[n + 1].g    - (((pPixelsIn[n].g         + pPixelsIn[n + 2].g)   >> 1) + 127);
            pPixelsOut[s].g = pPixelsIn[n].g        + (((pPixelsOut[d - 1].g    + pPixelsOut[d].g)      >> 2) - 64);

            pPixelsOut[d].b = pPixelsIn[n + 1].b    - (((pPixelsIn[n].b         + pPixelsIn[n + 2].b)   >> 1) + 127);
            pPixelsOut[s].b = pPixelsIn[n].b        + (((pPixelsOut[d - 1].b    + pPixelsOut[d].b)      >> 2) - 64);

            x += 2;
        }
        y++;
    }
    return true;
}

Там определенно что-то не так, но я просто не могу понять это.Может ли кто-нибудь с чуть большим количеством мозга, чем я, указать, где я иду не так?Стоит отметить, что вы можете увидеть неотнятую версию Daub 5/3 над рабочим кодом, и это тоже дает мне те же артефакты ... Я очень запутался, поскольку у меня это уже работало однажды (было более 2 лет назад, и у меня больше нет этого кода).

Любая помощь будет принята с благодарностью:)

Редактировать: Кажется, я устранил свои проблемы переполнения, зафиксировав пиксели нижних частот в диапазоне от 0 до 255.Я немного обеспокоен тем, что это не правильное решение.Кто-нибудь может прокомментировать это?

Ответы [ 3 ]

1 голос
/ 14 января 2010

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

  pPixelsOut[d].r = pPixelsIn[n + 1].r - (((pPixelsIn[n].r  + pPixelsIn[n + 2].r) >> 1) + 127);

If:
  pPixelsIn[n  ].r == 255
  pPixelsIn[n+1].r == 0
  pPixelsIn[n+2].r == 255

Then:
  pPixelsOut[d].r == -382


But if:
  pPixelsIn[n  ].r == 0
  pPixelsIn[n+1].r == 255
  pPixelsIn[n+2].r == 0

Then:
  pPixelsOut[d].r == 128

У вас есть диапазон из 511 возможных значений (-382 .. 128), поэтому, чтобы избежать переполнения или ограничения, вам потребуется один дополнительный бит, некоторое квантование или другой тип кодирования!

0 голосов
/ 16 января 2010

ОК. Я могу без потерь пересылать и переворачивать, пока я сохраняю свои данные пост-трансформации в коротком формате.Очевидно, это занимает немного больше места, чем я надеялся, но это позволяет мне стать хорошей отправной точкой для изучения различных алгоритмов сжатия.Вы также можете сжимать 2 4-х компонентные пиксели за раз, используя инструкции SSE2.Это стандартное прямое C-преобразование, которое я придумал:

        const int16_t dr    = (int16_t)pPixelsIn[n + 1].r   - ((((int16_t)pPixelsIn[n].r        + (int16_t)pPixelsIn[n + 2].r)  >> 1));
        const int16_t sr    = (int16_t)pPixelsIn[n].r       + ((((int16_t)pPixelsOut[d - 1].r   + dr)                           >> 2));

        const int16_t dg    = (int16_t)pPixelsIn[n + 1].g   - ((((int16_t)pPixelsIn[n].g        + (int16_t)pPixelsIn[n + 2].g)  >> 1));
        const int16_t sg    = (int16_t)pPixelsIn[n].g       + ((((int16_t)pPixelsOut[d - 1].g   + dg)                           >> 2));

        const int16_t db    = (int16_t)pPixelsIn[n + 1].b   - ((((int16_t)pPixelsIn[n].b        + (int16_t)pPixelsIn[n + 2].b)  >> 1));
        const int16_t sb    = (int16_t)pPixelsIn[n].b       + ((((int16_t)pPixelsOut[d - 1].b   + db)                           >> 2));

        pPixelsOut[d].r = dr;
        pPixelsOut[s].r = sr;

        pPixelsOut[d].g = dg;
        pPixelsOut[s].g = sg;

        pPixelsOut[d].b = db;
        pPixelsOut[s].b = sb;

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

0 голосов
/ 14 января 2010

Я предполагаю, что данные уже были пороговыми?

Я также не понимаю, почему вы добавляете обратно в +127 и -64.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...