上次介绍的是顺时针旋转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=;i<height;i+=)
{
for(int j=;j<width;j+=)
{
//step0 load 8x8 bytes in 8 registers
y_mat1.val[]=vld1_u8(srcImg+i*width+j);
y_mat1.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat1.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat1.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
//step1 reverse every element in a row
y_mat1.val[]=vrev64_u8(y_mat1.val[]);
y_mat1.val[]=vrev64_u8(y_mat1.val[]);
y_mat1.val[]=vrev64_u8(y_mat1.val[]);
y_mat1.val[]=vrev64_u8(y_mat1.val[]);
y_mat2.val[]=vrev64_u8(y_mat2.val[]);
y_mat2.val[]=vrev64_u8(y_mat2.val[]);
y_mat2.val[]=vrev64_u8(y_mat2.val[]);
y_mat2.val[]=vrev64_u8(y_mat2.val[]);
//step2 store every row in reverse order
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat2.val[]);
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat2.val[]);
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat2.val[]);
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat2.val[]);
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat1.val[]);
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat1.val[]);
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat1.val[]);
vst1_u8(dstImg+(height-i-)*width+(width-j-),y_mat1.val[]);
}
}
}

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=;i<height;i+=)
{
for(int j=;j<width;j+=)
{
//step0 load 8x8 bytes in 8 registers
y_mat1.val[]=vld1_u8(srcImg+i*width+j);
y_mat1.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat1.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat1.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
y_mat2.val[]=vld1_u8(srcImg+(i+)*width+j);
//step1 trn nearby registers
temp1=vtrn_u8(y_mat1.val[],y_mat1.val[]);
temp2=vtrn_u8(y_mat1.val[],y_mat1.val[]);
temp3=vtrn_u8(y_mat2.val[],y_mat2.val[]);
temp4=vtrn_u8(y_mat2.val[],y_mat2.val[]);
//step2 trn 1,3 2,4 5,7 6,8
temp5.val[]= vreinterpret_u16_u8(temp1.val[]);
temp5.val[]= vreinterpret_u16_u8(temp1.val[]);
temp6.val[]= vreinterpret_u16_u8(temp2.val[]);
temp6.val[]= vreinterpret_u16_u8(temp2.val[]);
temp7.val[]= vreinterpret_u16_u8(temp3.val[]);
temp7.val[]= vreinterpret_u16_u8(temp3.val[]);
temp8.val[]= vreinterpret_u16_u8(temp4.val[]);
temp8.val[]= vreinterpret_u16_u8(temp4.val[]);
temp9=vtrn_u16(temp5.val[],temp6.val[]);
temp10=vtrn_u16(temp5.val[],temp6.val[]);
temp11=vtrn_u16(temp7.val[],temp8.val[]);
temp12=vtrn_u16(temp7.val[],temp8.val[]);
//step3 trn 1,5 2,6 3,7 4,8
temp13.val[]= vreinterpret_u32_u16(temp9.val[]);
temp13.val[]= vreinterpret_u32_u16(temp9.val[]);
temp14.val[]= vreinterpret_u32_u16(temp10.val[]);
temp14.val[]= vreinterpret_u32_u16(temp10.val[]);
temp15.val[]= vreinterpret_u32_u16(temp11.val[]);
temp15.val[]= vreinterpret_u32_u16(temp11.val[]);
temp16.val[]= vreinterpret_u32_u16(temp12.val[]);
temp16.val[]= vreinterpret_u32_u16(temp12.val[]);
temp17=vtrn_u32(temp13.val[],temp15.val[]);
temp18=vtrn_u32(temp13.val[],temp15.val[]);
temp19=vtrn_u32(temp14.val[],temp16.val[]);
temp20=vtrn_u32(temp14.val[],temp16.val[]);
//step4 store bytes in correct position,the order now is 1,2,3,4,5,6,7,8
temp1.val[]= vreinterpret_u8_u32(temp20.val[]);
temp1.val[]= vreinterpret_u8_u32(temp18.val[]);
temp2.val[]= vreinterpret_u8_u32(temp19.val[]);
temp2.val[]= vreinterpret_u8_u32(temp17.val[]);
temp3.val[]= vreinterpret_u8_u32(temp20.val[]);
temp3.val[]= vreinterpret_u8_u32(temp18.val[]);
temp4.val[]= vreinterpret_u8_u32(temp19.val[]);
temp4.val[]= vreinterpret_u8_u32(temp17.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp1.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp1.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp2.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp2.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp3.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp3.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp4.val[]);
vst1_u8(dstImg+(width-j-)*height+i,temp4.val[]);
}
}
}

利用neon技术对矩阵旋转进行加速(2)的更多相关文章

  1. 利用neon技术对矩阵旋转进行加速

    一般的矩阵旋转操作都是对矩阵中的元素逐个操作,假设矩阵大小为m*n,那么时间复杂度就是o(mn).如果使用了arm公司提供的neon加速技术,则可以并行的读取多个元素,对多个元素进行操作,虽然时间复杂 ...

  2. 利用Cayley-Hamilton theorem 优化矩阵线性递推

    平时有关线性递推的题,很多都可以利用矩阵乘法来解决. 时间复杂度一般是O(K3logn)因此对矩阵的规模限制比较大. 下面介绍一种利用利用Cayley-Hamilton theorem加速矩阵乘法的方 ...

  3. 利用Hadoop实现超大矩阵相乘之我见(一)

    前记 最近,公司一位挺优秀的总务离职,欢送宴上,她对我说“你是一位挺优秀的程序员”,刚说完,立马道歉说“对不起,我说你是程序员是不是侮辱你了?”我挺诧异,程序员现在是很低端,很被人瞧不起的工作吗?或许 ...

  4. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  5. 利用Hadoop实现超大矩阵相乘之我见(二)

    前文 在<利用Hadoop实现超大矩阵相乘之我见(一)>中我们所介绍的方法有着“计算过程中文件占用存储空间大”这个缺陷,本文中我们着重解决这个问题. 矩阵相乘计算思想 传统的矩阵相乘方法为 ...

  6. VC中利用多线程技术实现线程之间的通信

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

  7. [LeetCode]Rotate Image(矩阵旋转)

    48. Rotate Image     Total Accepted: 69437 Total Submissions: 198781 Difficulty: Medium You are give ...

  8. 计蒜客模拟赛D1T1 蒜头君打地鼠:矩阵旋转+二维前缀和

    题目链接:https://nanti.jisuanke.com/t/16445 题意: 给你一个n*n大小的01矩阵,和一个k*k大小的锤子,锤子只能斜着砸,问只砸一次最多能砸到多少个1. 题解: 将 ...

  9. HDU 5950 - Recursive sequence - [矩阵快速幂加速递推][2016ACM/ICPC亚洲区沈阳站 Problem C]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950 Farmer John likes to play mathematics games with ...

随机推荐

  1. iOS友盟推送测试模式添加手机设备报红解决如下

    设备描述红色一般是没有往友盟发日志,或者appkey漏掉了.先检查是否正确的填写了推送的appkey,统计的方法为MobClick startWithAppkey:推送的方法为UMessage sta ...

  2. mariadb是替代MySQL的好方式

    像Oracle这样成熟稳定的数据库,足以支撑海量数据的存储与查询了?为什么还需要数据切片呢?的确,Oracle的DB确实很成熟很稳定,但是高昂的使用费用和高端的硬件支撑不是每一个公司能支付的起的.试想 ...

  3. 用apt爽还是apt-get爽

    debian系linux发行版的高级软件包管理工具叫apt(for Advanced Package Tool) . debian的包管理体系很立体,dpkg -> apt ->aptit ...

  4. slf4j+log4j2 pom配置

    <!-- log start --> <dependency> <groupId>org.slf4j</groupId> <artifactId& ...

  5. Github ——转

    Github 简明教程 分类 编程技术 如果你是一枚Coder,但是你不知道Github,那么我觉的你就不是一个菜鸟级别的Coder,因为你压根不是真正Coder,你只是一个Code搬运工. 但是你如 ...

  6. OpenCV颜色空间——HLS颜色空间

    引自:http://blog.csdn.net/zhangping1987/article/details/73699335 HLS颜色模型 HLS颜色空间,三个分量分别是色相(H).亮度(L).饱和 ...

  7. Java编程的逻辑 (73) - 并发容器 - 写时拷贝的List和Set

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  8. 移动端 图片切换 轮播(banner)

    发现一个很好用的jquery控件 操作很简单 1.引入css <link href="/Resources/style/swiper.min.css" rel="s ...

  9. Reservoir Sampling - 蓄水池抽样问题

    问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the o ...

  10. Altium Designer 规则设置

    设计规则设置 Designer Rules Check(DRC) Electrical 电气规则.安全间距,线网连接等 Routing 布线,线宽.过孔形状尺寸.布线拓扑.布线层.封装出线等 SMT ...