利用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=;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)的更多相关文章
- 利用neon技术对矩阵旋转进行加速
一般的矩阵旋转操作都是对矩阵中的元素逐个操作,假设矩阵大小为m*n,那么时间复杂度就是o(mn).如果使用了arm公司提供的neon加速技术,则可以并行的读取多个元素,对多个元素进行操作,虽然时间复杂 ...
- 利用Cayley-Hamilton theorem 优化矩阵线性递推
平时有关线性递推的题,很多都可以利用矩阵乘法来解决. 时间复杂度一般是O(K3logn)因此对矩阵的规模限制比较大. 下面介绍一种利用利用Cayley-Hamilton theorem加速矩阵乘法的方 ...
- 利用Hadoop实现超大矩阵相乘之我见(一)
前记 最近,公司一位挺优秀的总务离职,欢送宴上,她对我说“你是一位挺优秀的程序员”,刚说完,立马道歉说“对不起,我说你是程序员是不是侮辱你了?”我挺诧异,程序员现在是很低端,很被人瞧不起的工作吗?或许 ...
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- 利用Hadoop实现超大矩阵相乘之我见(二)
前文 在<利用Hadoop实现超大矩阵相乘之我见(一)>中我们所介绍的方法有着“计算过程中文件占用存储空间大”这个缺陷,本文中我们着重解决这个问题. 矩阵相乘计算思想 传统的矩阵相乘方法为 ...
- VC中利用多线程技术实现线程之间的通信
当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...
- [LeetCode]Rotate Image(矩阵旋转)
48. Rotate Image Total Accepted: 69437 Total Submissions: 198781 Difficulty: Medium You are give ...
- 计蒜客模拟赛D1T1 蒜头君打地鼠:矩阵旋转+二维前缀和
题目链接:https://nanti.jisuanke.com/t/16445 题意: 给你一个n*n大小的01矩阵,和一个k*k大小的锤子,锤子只能斜着砸,问只砸一次最多能砸到多少个1. 题解: 将 ...
- 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 ...
随机推荐
- 让cpu跑到100%的bat文件
请你新建一个叫“virus.bat”的批处理文件,里面填写上如下三段命令: Echo "welcom to the aqjava's world"Tree /fCall virus ...
- java---简单的ATM存取系统,
新手练手必备~ 密码账户为: 先创建账户类: package cn.Atm; /** * @author 偶my耶 */ import java.io.*; import com.project.pr ...
- SQL自定义函数
1,自定义函数--返回单一值 CREATE FUNCTION [dbo].[Round2] ( -- Add the parameters for the function here @p1 sql_ ...
- 一个简单有效的kubernetes部署案例
部署web-rc:web应用需要去获取redis注入的ip环境变量cluster_ip,以此来访问 [root@sdw1 files]# cat testweb-rc.yaml kind: Repli ...
- drupal7 的核心模块
核心模块 Drupal 7 block Block(区块)模块提供了与区块相关的功能,通过区块可将内容放置在网站不同区域.Block模块是Drupal的基础模块之一,不能被禁用.它是通过单独的区块管理 ...
- 【jquery】jquery 自定义滚动条
可以自由的给滚动条定义背景,上下按钮,当然不仅仅是颜色,连图片当背景也可以.支持鼠标滚轮,点击滚动条滚轴定位,上下按钮久按加速,兼容 ie,firefox,chrome. 调用方法: $(" ...
- C# Notes
Token Based Authentication Attributes Tutorial - Conditional - Obsolete Covariance and Contravarianc ...
- Navi.Soft31.阅读导航
Navi.Soft31.核心类库 Navi.Soft31.WinForm框架 Navi.Soft31.WebMVC框架 Navi.Soft31.微信WinForm框架 Navi.Soft31.Mobi ...
- android studio 解析Excel数据格式导入poi-3.17.jar时的一系列报错及处理Failed resolution of: Ljavax/xml/stream/XMLEventFactory,duplicate entry: org/apache/xmlbeans/xml/stream/Location.class,GC overhead limit exceeded
在org官网下载的poi jar包,导入到studio compile files('libs/poi-3.17.jar') compile files('libs/poi-ooxml-3.17.ja ...
- Loadrunner中Error-26612HTTP Status-Cod
最近在测试一系统的时候,录制脚本没有错误,回放的时候总是出现如下错误: Action.c(6): Error -26612: HTTP Status-Code=500 (Internal Server ...