5

我正在尝试在 lena 的图像上运行整数到整数提升 5/3。我一直在关注 Walker、Nguyen 和 Chen 的论文“A low-power Low-memory system for wavelet-based image compression”(链接于 2015 年 10 月 7 日有效)。

我遇到了问题。图像似乎不太正确。我似乎在绿色和蓝色通道中略微溢出,这意味着小波函数的后续通道会在不应该存在的地方找到高频。我也很确定我遇到了其他问题,因为我在高频部分的边缘看到了一条 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 范围内,我似乎已经消除了溢出问题。我有点担心这不是正确的解决方案。任何人都可以对此发表评论吗?

4

3 回答 3

1

你可以做一些极端值的测试,看看溢出的可能性。例子:

  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),因此,为了避免溢出或钳位,您需要一个额外的位、一些量化或另一种编码类型!

于 2010-01-14T16:09:01.877 回答
0

我假设数据已经被阈值化了?

我也不明白你为什么要加回+127 和-64。

于 2010-01-13T22:39:49.897 回答
0

好的,只要我将我的后正向变换数据存储在一个简短的范围内,我就可以无损地转发然后反向。显然,这占用的空间比我希望的要多,但这确实为我提供了一个了解各种压缩算法的良好起点。您还可以使用 SSE2 指令一次压缩 2 4 个分量像素。这是我想出的标准 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 并失去一两点准确性。对于压缩,这确实不是问题。

于 2010-01-16T10:17:13.760 回答