2013-03-19 59 views
0

我想知道是否有可能与霓虹灯向量降采样图像3? 我正在试图为纸上写一个算法,但它似乎是不可能的。因为当你得到例如8字节,你不能得到3 * 3像素,将没有足够的像素来完成下采样操作。根据下降采样2:Explaining ARM Neon Image Sampling 我想加载16bytes,然后从一行8bytes,然后将它们分配给一个32bytes的向量,然后处理该向量的24个字节?算法下采样3使用霓虹灯的图像

更新: 我写根据答案的样本代码,但是我在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; 

    } 

} 
+0

我不知道你在问什么。您提供的链接中的代码每行处理8 *像素*,而不是8个字节。 – 2013-03-19 18:28:22

+0

@CareyGregory我假设灰度图像 – 2013-03-19 18:49:13

回答

2

您每处理扫描线,您可以通过使用vld3.8structure loads。如果你有像素的第一,第二和第三线的起始地址在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]
  • 同为d3 .. d5为2号线和d6 .. d8第三

然后取它们的平均值所有。你可能想扩展到16位,以免失去精度。

编辑:总颇像(左除以九):

// 
// 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]); 

祝你好运!

+0

9的平均指令是什么?之后,我应该存储平均值? – 2013-03-19 18:50:52

+2

没有单一的指令。将它们加起来并近似除以9.(d9 + d9 >> 3 - d9 >> 6)>> 3;已经非常接近了。 – 2013-03-19 21:42:58

+1

这个着名的例子章节来自黑客喜欢constants_的_division,http://www.hackersdelight.org/divcMore.pdf,它有一个例子,说明如何使用常量移位来编码'div9'并添加。如有必要,这可以在NEON指令中完全完成。阿基的代码就是这个近似值。 – 2013-03-20 09:13:31