2013-03-19 71 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