zoukankan      html  css  js  c++  java
  • 利用neon技术对矩阵旋转进行加速(2)

    上次介绍的是顺时针旋转90度,最近用到了180度和270度,在这里记录一下。

    1.利用neon技术将矩阵顺时针旋转180度:

    顺时针旋转180度比顺时针旋转90度容易很多,如下图

    A1 A2 A3 A4              D4 D3 D2 D1

    B1 B2 B3 B4        顺时针旋转180度    C4 C3 C2 C1

    C1 C2 C3 C4              B4 B3 B2 B1

    D1 D2 D3 D4               A4 A3 A2 A1

    其实就是把矩阵每一行的元素逆序排列,再把矩阵的每一行逆序排列,代码如下:

    void rotate180(unsigned char* dstImg,unsigned char* srcImg,int width,int height)
    {
        uint8x8x4_t y_mat1;  //use 2 register array to load a 8x8 patch
        uint8x8x4_t y_mat2;
        for(int i=0;i<height;i+=8)
        {
            for(int j=0;j<width;j+=8)
            {
                //step0 load 8x8 bytes in 8 registers
                y_mat1.val[0]=vld1_u8(srcImg+i*width+j);
                y_mat1.val[1]=vld1_u8(srcImg+(i+1)*width+j);
                y_mat1.val[2]=vld1_u8(srcImg+(i+2)*width+j);
                y_mat1.val[3]=vld1_u8(srcImg+(i+3)*width+j);
                y_mat2.val[0]=vld1_u8(srcImg+(i+4)*width+j);
                y_mat2.val[1]=vld1_u8(srcImg+(i+5)*width+j);
                y_mat2.val[2]=vld1_u8(srcImg+(i+6)*width+j);
                y_mat2.val[3]=vld1_u8(srcImg+(i+7)*width+j);
                //step1 reverse every element in a row
                y_mat1.val[0]=vrev64_u8(y_mat1.val[0]);
                y_mat1.val[1]=vrev64_u8(y_mat1.val[1]);
                y_mat1.val[2]=vrev64_u8(y_mat1.val[2]);
                y_mat1.val[3]=vrev64_u8(y_mat1.val[3]);
                y_mat2.val[0]=vrev64_u8(y_mat2.val[0]);
                y_mat2.val[1]=vrev64_u8(y_mat2.val[1]);
                y_mat2.val[2]=vrev64_u8(y_mat2.val[2]);
                y_mat2.val[3]=vrev64_u8(y_mat2.val[3]);
                //step2 store every row in reverse order
                vst1_u8(dstImg+(height-i-8)*width+(width-j-8),y_mat2.val[3]);
                vst1_u8(dstImg+(height-i-7)*width+(width-j-8),y_mat2.val[2]);
                vst1_u8(dstImg+(height-i-6)*width+(width-j-8),y_mat2.val[1]);
                vst1_u8(dstImg+(height-i-5)*width+(width-j-8),y_mat2.val[0]);
                vst1_u8(dstImg+(height-i-4)*width+(width-j-8),y_mat1.val[3]);
                vst1_u8(dstImg+(height-i-3)*width+(width-j-8),y_mat1.val[2]);
                vst1_u8(dstImg+(height-i-2)*width+(width-j-8),y_mat1.val[1]);
                vst1_u8(dstImg+(height-i-1)*width+(width-j-8),y_mat1.val[0]);
            }
        }
    }

    2.利用neon技术将矩阵顺时针旋转270度:

    这个和顺时针旋转90度非常像,只是在对neon寄存器中的向量进行转置时不太一样,这点需要注意

    void rotate270(unsigned char* dstImg,unsigned char* srcImg,int width,int height)
    {
        uint8x8x4_t y_mat1;  //use 2 register array to load a 8x8 patch
        uint8x8x4_t y_mat2;
    
        uint8x8x2_t temp1;
        uint8x8x2_t temp2;
        uint8x8x2_t temp3;
        uint8x8x2_t temp4;
    
        uint16x4x2_t temp5;
        uint16x4x2_t temp6;
        uint16x4x2_t temp7;
        uint16x4x2_t temp8;
        uint16x4x2_t temp9;
        uint16x4x2_t temp10;
        uint16x4x2_t temp11;
        uint16x4x2_t temp12;
    
        uint32x2x2_t temp13;
        uint32x2x2_t temp14;
        uint32x2x2_t temp15;
        uint32x2x2_t temp16;
        uint32x2x2_t temp17;
        uint32x2x2_t temp18;
        uint32x2x2_t temp19;
        uint32x2x2_t temp20;
        for(int i=0;i<height;i+=8)
        {
            for(int j=0;j<width;j+=8)
            {
                //step0 load 8x8 bytes in 8 registers
                y_mat1.val[0]=vld1_u8(srcImg+i*width+j);
                y_mat1.val[1]=vld1_u8(srcImg+(i+1)*width+j);
                y_mat1.val[2]=vld1_u8(srcImg+(i+2)*width+j);
                y_mat1.val[3]=vld1_u8(srcImg+(i+3)*width+j);
                y_mat2.val[0]=vld1_u8(srcImg+(i+4)*width+j);
                y_mat2.val[1]=vld1_u8(srcImg+(i+5)*width+j);
                y_mat2.val[2]=vld1_u8(srcImg+(i+6)*width+j);
                y_mat2.val[3]=vld1_u8(srcImg+(i+7)*width+j);
                //step1 trn nearby registers
                temp1=vtrn_u8(y_mat1.val[0],y_mat1.val[1]);
                temp2=vtrn_u8(y_mat1.val[2],y_mat1.val[3]);
                temp3=vtrn_u8(y_mat2.val[0],y_mat2.val[1]);
                temp4=vtrn_u8(y_mat2.val[2],y_mat2.val[3]);
                //step2 trn 1,3 2,4 5,7 6,8
                temp5.val[0]= vreinterpret_u16_u8(temp1.val[0]);
                temp5.val[1]= vreinterpret_u16_u8(temp1.val[1]);
                temp6.val[0]= vreinterpret_u16_u8(temp2.val[0]);
                temp6.val[1]= vreinterpret_u16_u8(temp2.val[1]);
                temp7.val[0]= vreinterpret_u16_u8(temp3.val[0]);
                temp7.val[1]= vreinterpret_u16_u8(temp3.val[1]);
                temp8.val[0]= vreinterpret_u16_u8(temp4.val[0]);
                temp8.val[1]= vreinterpret_u16_u8(temp4.val[1]);
                temp9=vtrn_u16(temp5.val[0],temp6.val[0]);
                temp10=vtrn_u16(temp5.val[1],temp6.val[1]);
                temp11=vtrn_u16(temp7.val[0],temp8.val[0]);
                temp12=vtrn_u16(temp7.val[1],temp8.val[1]);
                //step3 trn 1,5 2,6 3,7 4,8
                temp13.val[0]= vreinterpret_u32_u16(temp9.val[0]);
                temp13.val[1]= vreinterpret_u32_u16(temp9.val[1]);
                temp14.val[0]= vreinterpret_u32_u16(temp10.val[0]);
                temp14.val[1]= vreinterpret_u32_u16(temp10.val[1]);
                temp15.val[0]= vreinterpret_u32_u16(temp11.val[0]);
                temp15.val[1]= vreinterpret_u32_u16(temp11.val[1]);
                temp16.val[0]= vreinterpret_u32_u16(temp12.val[0]);
                temp16.val[1]= vreinterpret_u32_u16(temp12.val[1]);
                temp17=vtrn_u32(temp13.val[0],temp15.val[0]);
                temp18=vtrn_u32(temp13.val[1],temp15.val[1]);
                temp19=vtrn_u32(temp14.val[0],temp16.val[0]);
                temp20=vtrn_u32(temp14.val[1],temp16.val[1]);
                //step4 store bytes in correct position,the order now is 1,2,3,4,5,6,7,8
                temp1.val[0]= vreinterpret_u8_u32(temp20.val[1]);
                temp1.val[1]= vreinterpret_u8_u32(temp18.val[1]);
                temp2.val[0]= vreinterpret_u8_u32(temp19.val[1]);
                temp2.val[1]= vreinterpret_u8_u32(temp17.val[1]);
                temp3.val[0]= vreinterpret_u8_u32(temp20.val[0]);
                temp3.val[1]= vreinterpret_u8_u32(temp18.val[0]);
                temp4.val[0]= vreinterpret_u8_u32(temp19.val[0]);
                temp4.val[1]= vreinterpret_u8_u32(temp17.val[0]);
                vst1_u8(dstImg+(width-j-8)*height+i,temp1.val[0]);
                vst1_u8(dstImg+(width-j-7)*height+i,temp1.val[1]);
                vst1_u8(dstImg+(width-j-6)*height+i,temp2.val[0]);
                vst1_u8(dstImg+(width-j-5)*height+i,temp2.val[1]);
                vst1_u8(dstImg+(width-j-4)*height+i,temp3.val[0]);
                vst1_u8(dstImg+(width-j-3)*height+i,temp3.val[1]);
                vst1_u8(dstImg+(width-j-2)*height+i,temp4.val[0]);
                vst1_u8(dstImg+(width-j-1)*height+i,temp4.val[1]);
            }
        }
    }
  • 相关阅读:
    Java 动态代理机制分析及扩展
    记:从百度空间搬家到博客园写博客要写的舒服
    字符串与byte[]之间的转换
    关于中文的几个编码GB2312、GBK、GB18030、GB13000
    深入biztalk中各种端口绑定方式(七) 直接绑定之Partner Orchestration
    X.509 数字证书结构和实例
    深入biztalk中各种端口绑定方式(六) 直接绑定之Self Correlating
    在代码中使用biztalk类库建立Message和Part
    Byte[]和BASE64之间的转换
    深入biztalk中各种端口绑定方式(五) 直接绑定之MessageBox
  • 原文地址:https://www.cnblogs.com/hrlnw/p/3767853.html
Copyright © 2011-2022 走看看