上次介绍的是顺时针旋转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. tf.Variable

    tf.Variable __init__( initial_value=None, trainable=True, collections=None, validate_shape=True, cac ...

  2. ZooKeeper管理分布式环境中的数据

    Reference: http://www.cnblogs.com/wuxl360/p/5817549.html 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  3. 基于jQuery悬停图片变色放大特效

    分享一款基于jQuery悬停图片变色放大特效是一款响应式鼠标悬停图片放大效果代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div style="width ...

  4. RDD、DataFrame和DataSet

    简述 RDD.DataFrame和DataSet是容易产生混淆的概念,必须对其相互之间对比,才可以知道其中异同:DataFrame多了数据的结构信息,即schema.RDD是分布式的 Java对象的集 ...

  5. Redis提供的持久化机制(二)

    1.前言 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集 ...

  6. PropertyChangeSupport

    1 import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; /** * @author h ...

  7. Drupal 7 配置ckeditor和ckfinder编辑器实现图片上传--不用wysisyg

    注意: 1.这里的ckeditor编辑器是独立模块,不是那个wysiwyg模块. 2.这里的图片上传仅仅为文章内图片,非字段图片.   1.下载文件(1) http://drupal.org/proj ...

  8. Ext 组件的一些操作

    原文:http://linder0209.iteye.com/blog/1039200 1.Ext.Component 该组件在渲染的时候会默认的创建div DOM,是根据this.autoEl的配置 ...

  9. SpringCloud 详解配置刷新的原理 使用jasypt自动加解密后 无法使用 springcloud 中的自动刷新/refresh功能

    之所以会查找这篇文章,是因为要解决这样一个问题: 当我使用了jasypt进行配置文件加解密后,如果再使用refresh 去刷新配置,则自动加解密会失效. 原因分析:刷新不是我之前想象的直接调用conf ...

  10. n个括号对的所有可能情况

    所有可能情况的数量为卡特兰数.故求所有可能的出栈情况与此类似. 思路: 若左括号没全插入,则插入左括号: 若已插入左括号数比已插入右括号数多,则插入右括号: #include<stdio.h&g ...