2012-07-20 90 views
0

我正在研究iOS的一些图像处理应用程序,阈值确实是一个巨大的瓶颈。所以我试图用NEON来优化它。这是C版本的功能。有没有什么方法可以用NEON重写这个(不幸的是我绝对没有这方面的经验)?使用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]]; 
     } 
    } 
} 
+0

当然,只是做了'VCGT'与阈值,然后'VAND'它MAXVAL。不幸的是,我不知道ARM和NEON将它变成完整的东西。 – harold 2012-07-20 22:22:34

+0

[iOS的NEON指南](http://wanderingcoder.net/2010/06/02/intro-neon/)可能会有帮助,以及[iOS开发人员应该了解的有关ARM的一些内容](http: //wanderingcoder.net/2010/07/19/ought-arm/)。他们不能解决你确切的问题,但可能会给你一个地方开始调查。 – bouteillebleu 2012-07-20 22:33:28

+1

嵌套循环中的条件不应该是“j 2012-07-20 22:41:39

回答

7

这其实很简单,如果你能确保你的行始终的宽度为16个字节的倍数,因为编译器(铛)具有代表NEON矢量寄存器特殊类型,并且知道如何应用正常C运营商给他们。这里是我的小测试功能:

#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个字节。 A uint8x16_t是一个包含16个8位无符号整数的向量寄存器。 vdupq_n_u8返回一个向量uint8x16_t,其中填充16个参数。

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

&运算符适用于两个uint8x16_t值,计算128对的布尔运算结果的位。

循环编译为这一个发布版本:

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