Android平臺-彩色RGB影象灰度化-neon優化例項解析
阿新 • • 發佈:2019-02-04
影象的灰度化公式比較簡單。
Y = (R * 77 + G * 151 + B * 28 ) / 256
傳統的C語言一次處理一個畫素點,neon指令可以一次處理8個畫素點,下面看看neon優化後的加速效果。
在Android NDK Samples 中有一個hello-neon的工程,裡面有一個濾波器的C程式碼和neon優化程式碼時間對比,
這裡可以在這個框架上加入RGB灰度化的neon例項。
程式碼如下:
//image gray sample //NEON優化前的程式碼 void reference_convert (uint8_t * __restrict dest, uint8_t * __restrict src, int n) { int i; for (i=0; i<n; i++) { int r = *src++; // load red int g = *src++; // load green int b = *src++; // load blue // build weighted average: int y = (r*77)+(g*151)+(b*28); // undo the scale by 256 and write to memory: *dest++ = (y>>8); } }
//NEON優化後的程式碼 void neon_convert (uint8_t * __restrict dest, uint8_t * __restrict src, int n) { int i; uint8x8_t rfac = vdup_n_u8 (77); // 轉換權值 R uint8x8_t gfac = vdup_n_u8 (151); // 轉換權值 G uint8x8_t bfac = vdup_n_u8 (28); // 轉換權值 B n/=8; for (i=0; i<n; i++) { uint16x8_t temp; uint8x8x3_t rgb = vld3_u8 (src); uint8x8_t result; temp = vmull_u8 (rgb.val[0], rfac); // vmull_u8 每個位元組(8bit)對應相乘,結果為每個單位2位元組(16bit) temp = vmlal_u8 (temp,rgb.val[1], gfac); // 每個位元對應相乘並加上 temp = vmlal_u8 (temp,rgb.val[2], bfac); result = vshrn_n_u16 (temp, 8); // 全部移位8位 vst1_u8 (dest, result); // 轉存運算結果 src += 8*3; dest += 8; } }
程式碼解析:
uint8x8_t 為一個8位的向量,向量的每個元素的資料型別為uint8_t型別,實際上也就是 unsigned char型別
uint16x8_t 為一個8位的向量,向量的每個元素的資料型別為uint16_t型別,實際上也就是 unsigned short型別
vdup_n_u8 裝載8位常數向量
uint8x8x3_t 是一個結構定義:
struct int8x8x3_t
{
int8x8_t val[3];
};
包含了3個int8x8_t資料型別
vmull_u8 每個位元組對應相乘
vmlal_u8 乘累加
vshrn_n_u16
右移操作vst1_u8 資料轉存,
從uint8X8_t變為位元組流