上次介绍的是顺时针旋转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. 未能加载文件或程序集“System.Web.Mvc, Version=3.0.0.0,

    直接下载安装 ASP.NET MVC 3.0就可以了

  2. gulp监听文件变化,并拷贝到指定目录(转)---参考记录

    ###暂时不支持目录修改.创建.删除.var gulp = require('gulp'); var fs = require('fs'); var path = require('path'); v ...

  3. python 普通方法,@classmethod,@staticmethod

    普通方法 实例化一个类,然后通过类的实例化去调用方法: class method1: def __init__(self): self.items = [1,2,3,] def getvalue(se ...

  4. ORA-12705 解决方法

    问题:创建Oracle数据库出现ORA-12705:Cannot access NLS data files or invalid environment specified. 环境:重置系统,无Or ...

  5. C语言 · 排列数 · 排列式

    蓝桥练习场上不断碰到类似的题,都是一个递归搜索的套路. 算法提高 排列数   时间限制:1.0s   内存限制:256.0MB      问题描述 0.1.2三个数字的全排列有六种,按照字母序排列如下 ...

  6. <悟道一位IT高管20年的职场心经>笔记

    1. 你一定会在某个时候惊讶地发现,原来当初你曾经硬着头皮挨过来的日子对你是那么的珍贵.2. "'老板就是老板'.这一点,你可能会忘,他一定不会忘.'老板不会总是老板'.这一点,他可能会忘, ...

  7. A-Frame不如x3dom

    昨天才发现还有A-Frame这么个框架,是Mozilla(moz://a 这个logo挺有创意的)出的,但看了一下其实现方式和语法后,感觉与x3d/x3dom还是有差距的. 二者的实现方式都是基于We ...

  8. Java IO流学习

    Java IO流学习 Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是 ...

  9. 如何安装docker-compose

    docker-compose还是挺好用的~~~~~ 这里简单介绍下两种安装docker-compose的方式,第一种方式相对简单,但是由于网络问题,常常安装不上,并且经常会断开,第二种方式略微麻烦,但 ...

  10. java中GZIPOutputStream 流的使用(EOFException)

    GZip流的使用非常多人都出现了以下的异常:java.io.EOFException: Unexpected end of ZLIB input stream.或者出现压缩后的数据不全的情况(就是压缩 ...