5

レナの画像で整数から整数へのリフティング 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) の範囲があるため、オーバーフローまたはクランプを回避するために、1 つの余分なビット、いくつかの量子化、または別のエンコード タイプが必要になります。

于 2010-01-14T16:09:01.877 に答える
0

OKポストフォワード変換データを短く保存する限り、ロスレスでフォワードしてからインバースすることができます。明らかに、これは私が望んでいたよりも少し多くのスペースを占有しますが、これは私がさまざまな圧縮アルゴリズムに入る良い出発点を可能にします。また、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にシャントして、精度を1〜2ビット失うことができるかどうかを確認します。圧縮の場合、これは実際には問題ではありません。

于 2010-01-16T10:17:13.760 に答える
0

データはすでにしきい値処理されていると思いますか?

また、なぜ +127 と -64 を追加しているのかわかりません。

于 2010-01-13T22:39:49.897 に答える