使用NEON指令进行图像阈值处理

我正在为iOSdevise一些image processing应用程序,阈值确实是一个巨大的瓶颈。 所以我试图用NEON来优化它。 这里是C版本的函数。 有没有什么办法可以用NEON来重写(不幸的是我绝对没有这方面的经验)?

static void thresh_8u( const Image& _src, Image& _dst, uchar thresh, uchar maxval, int type ) { int i, j; uchar tab[256]; Size roi = _src.size(); roi.width *= _src.channels(); memset(&tab[0], 0, thresh); memset(&tab[thresh], maxval, 256-thresh); for( i = 0; i < roi.height; i++ ) { const uchar* src = (const uchar*)(_src.data + _src.step*i); uchar* dst = (uchar*)(_dst.data + _dst.step*i); j = 0; for(; j <= roi.width; ++j) { dst[j] = tab[src[j]]; } } } 

实际上,如果你可以确保你的行总是16字节宽的倍数,因为编译器(clang)具有代表NEON向量寄存器的特殊types,并且知道如何将正常的C运算符应用于它们。 这是我的小testingfunction:

 #ifdef __ARM_NEON__ #include <arm_neon.h> void computeThreshold(void *input, void *output, int count, uint8_t threshold, uint8_t highValue) { uint8x16_t thresholdVector = vdupq_n_u8(threshold); uint8x16_t highValueVector = vdupq_n_u8(highValue); uint8x16_t *__restrict inputVector = (uint8x16_t *)input; uint8x16_t *__restrict outputVector = (uint8x16_t *)output; for ( ; count > 0; count -= 16, ++inputVector, ++outputVector) { *outputVector = (*inputVector > thresholdVector) & highValueVector; } } #endif 

这个操作一次16个字节。 uint8x16_t是一个包含16个8位无符号整数的向量寄存器。 vdupq_n_u8返回一个向量uint8x16_t填充16个参数。

应用于两个uint8x16_t值的>运算符在8位无符号整数对之间进行16次比较。 如果左input大于右input,则返回0xff(这与正常C > ,后者只返回0x01)。 如果左侧input小于或等于右侧input,则返回0.(编译成VCGT.U8指令。)

应用于两个uint8x16_t值的&操作符计算128对位的布尔AND。

循环在发布版本中编译为:

 0x6e668: vldmia r2, {d4, d5} 0x6e66c: subs r0, #16 0x6e66e: vcgt.u8 q10, q10, q8 0x6e672: adds r2, #16 0x6e674: cmp r0, #0 0x6e676: vand q10, q10, q9 0x6e67a: vstmia r1, {d4, d5} 0x6e67e: add.w r1, r1, #16 0x6e682: bgt 0x6e668