代码之家  ›  专栏  ›  技术社区  ›  Goz

离散小波变换整数道5/3提升问题

  •  5
  • Goz  · 技术社区  · 15 年前

    我试图运行一个整数到整数,在Lena的图像上提升5/3。我一直在关注Walker、Nguyen和Chen的论文“用于基于小波的图像压缩的低功耗低内存系统”。( Link 自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;
    }
    

    肯定有什么问题,但我就是搞不清楚。有谁能比我稍微聪明一点,指出我哪里出错了吗?值得注意的是,您可以看到工作代码之上的DAUB5/3的未解除版本,这也给了我相同的工件…我很困惑,因为我以前有过一次这样的工作(那是两年多以前的事了,我不再有那个代码了)。

    如有任何帮助,我们将不胜感激:)

    编辑:我似乎通过将低通像素限制在0到255范围内消除了溢出问题。不过,我有点担心这不是正确的解决方案。有人对此有何评论?

    3 回复  |  直到 9 年前
        1
  •  1
  •   e.tadeu    15 年前

    您可以使用极端值进行一些测试,以查看溢出的可能性。例子:

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

        2
  •  0
  •   John    15 年前

    我假设数据已经被脱粒了?

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

        3
  •  0
  •   Goz    15 年前

    好吧,只要我把前向转换后的数据存储在一个短的时间内,我就可以无损失地向前然后向后。显然,这比我希望的要占用更多的空间,但这确实为我进入各种压缩算法提供了一个很好的起点。您还可以使用SSE2指令一次压缩24个组件像素。这是我提出的标准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,并损失一点或两个精度。对于压缩来说,这确实不是问题。