上次介绍的是顺时针旋转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. 如何在线程中获取spring 管理的bean

    转载自:https://my.oschina.net/skyline520/blog/181158?fromerr=GjtR6Wec spring xml中定义 <!--spring 工具类-- ...

  2. java中的元数据

    java中的Annotation和C#中的Attribute相似. 写法上差别较大 @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLA ...

  3. JAVA是否可以作脚本语言呢

    答:是可以的. 只是叫另一个名字-beanshell.印象里她好像还是第一款jvm语言.应该挺多年没更新了. 我之所以知道它,是当年折腾jEdit这款编辑器较多,它的内置脚本引擎使用的就是beansh ...

  4. Java线程池关闭1-shutdown和isTerminated<转>

    shutdownvoid shutdown()启动一次顺序关闭,执行以前提交的任务,但不接受新任务.若已经关闭,则调用没有其他作用.抛出:SecurityException - 如果安全管理器存在并且 ...

  5. Linxu安装Tomcat与Jdk并卸载自带OpenJdk

    下载安装tomcat 1.下载apache-tomcat-7.0.47.tar.gz tomcat压缩包上传到linxu服务器 2.cd到文件存放目录使用(tar -xvzf apache-tomca ...

  6. GIT——总结.1-

    创建版本库 时光机穿梭 版本回退 工作区和暂存区 管理修改 撤销修改 删除文件 Git Git是目前世界上最先进的分布式版本控制系统(没有之一) Git是分布式版本控制系统 首先,分布式版本控制系统根 ...

  7. 计算机名、主机名、用户账户名与NetBIOS名有什么区别

    1.计算机名:右击“我的电脑”,选择“属性”,在“系统属性”对话框的“计算机名”选项卡里,可以设置计算机名.计算机名是对域(或工作组)中的计算机的标识,如果你的计算机名设置为“至清水”,则在网上邻居里 ...

  8. drupal pathauto的配置

  9. Spark硬件配置推荐

    1.存储系统 如果可以的话,把Spark的hadoop的节点安装在一起,最容易的方式是用standalone的模式安装,用mapred.child.java.opts设置每个任务的内存,用mapred ...

  10. jQuery(三):样式操作

    一.DOM操作分类 DOM Core:任何一种支持DOM的编程语言都可以使用它,例如:getElementById(). HTML-DOM:用于处理HTML文档,例如:document.forms. ...