0

ネオンベクトルを使用して画像を 3 ダウンサンプリングすることは可能ですか? そのためのアルゴリズムを紙に書こうとしていますが、それは不可能のようです。たとえば 8 バイトを取得すると、3*3 ピクセルを取得できないため、ダウンサンプリング操作を完了するのに十分なピクセルがありません。downsample by 2: Explaining ARM Neon Image Sampling によると、1 つの行から 16 バイト、次に 8 バイトをロードし、それらを 32 バイトのベクトルに割り当て、そのベクトルの 24 バイトを処理することを考えています。

更新: 回答に従ってサンプル コードを記述しましたが、vst1_u8 でセグメンテーション違反が発生します...

inline void downsample3dOnePass( uint8_t* src, uint8_t *dst, int srcWidth)
{

    // make sure rows/cols dividable by 8
    int rows = ((srcWidth>>3)<<3);
    // 8 pixels per row
    rows=rows>>3;

    for (int r = 0; r < rows; r++)
    {
       // load 24 pixels (grayscale)
       uint8x8x3_t pixels     = vld3_u8(src);
       // first sum = d0 + d1
       uint8x8_t firstSum     = vadd_u8 ( pixels.val[0], pixels.val[1] );
       // second sum = d1+d2;
       uint8x8_t secondSum    = vadd_u8 ( firstSum,  pixels.val[2] );
       // total sum = d0+d1+d2
       uint8x8_t totalSum     = vadd_u8(secondSum, firstSum);
       // average = d0+d1+d2/8 ~9 for test
       uint8x8_t totalAverage = vshr_n_u8(totalSum,3);
       // store 8 bytes
       vst1_u8(dst, totalAverage);
       // move to next 3 rows
       src+=24;
       // move to next row
       dst+=8;

    }

}
4

1 に答える 1

2

処理するすべてのスキャンラインに対して、 を介して構造ロードvld3.8を使用できます。ピクセルの 1 行目、2 行目、3 行目の開始アドレスがあるr0..r2場合:

vld3.8 {d0,d1,d2}, [r0]
vld3.8 {d3,d4,d5}, [r1]
vld3.8 {d6,d7,d8}, [r2]

あなたにあげる

  • d0[0,3,6,9,12,15,18,21]最初の行のバイトがあります
  • d1[1,4,7,10,13,16,19,22]最初の行のバイトがあります
  • d2[2,5,8,11,14,17,20,23]最初の行のバイトがあります
  • 2 行目の..と 3行目のd3..も同じd5d6d8

次に、それらすべてを平均します。精度を落とさないようにするために、16 ビットに拡張することをお勧めします。

編集:合計は次のようになります (9 分割は除外):

//
// load 3x8 bytes from three consecutive scanlines
//
uint8x8x3_t pixels[3] =
    { vld3_u8(src), vld3_u8(src + srcwidth), vld3_u8(src + 2*srcwidth) };

//
// expand them to 16bit so that the addition doesn't overflow
//
uint16x8_t wpix[9] =
    { vmovl_u8(pixels[0].val[0]),
      ...
      vmovl_u8(pixels[3].val[2]) };

//
// nine adds. Don't always add to wpix[0] because of possible dependencies.
//
wpix[0] = vaddq_u16(wpix[0], wpix[1]);
wpix[2] = vaddq_u16(wpix[2], wpix[3]);
wpix[4] = vaddq_u16(wpix[4], wpix[5]);
wpix[6] = vaddq_u16(wpix[6], wpix[7]);
wpix[0] = vaddq_u16(wpix[0], wpix[8]);

wpix[1] = vaddq_u16(wpix[2], wpix[4]);
wpix[3] = vaddq_u16(wpix[6], wpix[0]);
wpix[0] = vaddq_u16(wpix[1], wpix[3]);

[ .. divide-by-nine magic (in 16bit, aka for uint16x8_t), in wpix[0] ... ]
//
// truncate to 8bit and store back
//
vst1_u8(dst, vmovn_u16(wpix[0]);

幸運を !

于 2013-03-19T18:34:49.763 に答える