您的位置:首页 > 其它

旋转矩阵算法性能问题

2016-10-19 14:25 106 查看

背景

最近需要对Android摄像头采集出来的的NV21数据,做个顺时针90度的旋转,流畅352x288,与标清640x480算法都还能满足,但是高清1280x720的时候,算法A明显落后算法B.现在没时间研究,只能记录下来,希望你可以提出你们宝贵的意见,让我少走点弯路.


现象

在352x288分辨率下,两者耗时相当20ms左右;

在640x480时,算法A平均耗时50ms,而算法B平均耗时23ms;

在1280x720是,算法A平均耗时133ms,而算法B平均耗时55ms;

算法类别\分辨率352x288640x4801280x720
算法A20ms50ms133ms
算法B20ms23ms54ms

算法A

算法A共有3段代码

第一段

/**
* NV21数据 顺时针旋转90度
* @param inData
* @param outData
* @param width
* @param height
*/
public static void rotateNV21(byte[] inData, byte[] outData, int width, int height) {
int ySize = width * height;
int uvSize = ySize / 2;
//旋转Y
clockwise90Planar(inData, 0, ySize,outData, 0, width, height);
//旋转UV
clockwise90Packed(inData, ySize, uvSize, outData, ySize, width, height / 2, 2);
}


第二段

/**
* 顺时针旋转90度 矩阵数据
* @param in_data 输入数据
* @param width 旋转前 宽
* @param height 旋转前 高
* @param out_data 输出数据
* @param srcOffset 输入数据起始坐标
* @param length 操作数据长度
* @param offset 输出数据其实坐标
*/
public static void clockwise90Planar(byte[] in_data, int srcOffset,int length, byte[] out_data, int offset, int width, int height) {
//      if((length % width !=0) || (length % height !=0)) {
//          Log.e("Rotate", "clockwise90() data is valid!");
//      }
int x,y,/*x,y*/
xp,yp;/*x',y'*/
int outIndex = 0;//输出数组的下标
for (int index = 0; index < length - 1; index++) {
/** The first step is to convert the index => (x,y) */
x = index % width;
y = index / width;
/** The second step is to convert the (x',y') => out_index */
xp = (height - y -1);
yp = x;
outIndex = yp * height/*此处为新矩阵的width',所以用原来矩阵的height*/ + xp;
//          String s = String.format("     value - x = %d, y = %d, x' = %d, y' = %d, index = %d, oindex = %d, px = %d", x, y, xp, yp, index, outIndex, in_data[index]);
//          Log.i("Rotate", s);
/** fill data */
out_data[offset + outIndex] = in_data[srcOffset + index];
/** outIndex = ((index % width) + 1) x height - (index / width) - 1 */
}
}


第三段

/**
* 顺时针旋转90度 矩阵数据Packed类型
* @param in_data 输入数据
* @param width 旋转前 宽
* @param height 旋转前 高
* @param out_data 输出数据
* @param srcOffset 输入数据起始坐标
* @param length 操作数据长度
* @param offset 输出数据其实坐标
* @param pNum 每个组合的个数  如:YYYYYYYY UVUV 其中UV为一个旋转组合,pNum = 2
*/
public static void clockwise90Packed(byte[] in_data, int srcOffset,int length, byte[] out_data, int offset, int iWidth, int iHeight, int pNum) {
//      if((length % width !=0) || (length % height !=0)) {
//          Log.e("Rotate", "clockwise90() data is valid!");
//      }
int widthPerNum = iWidth / pNum;
int heightPerNum = iHeight;
/** 遍历uv集合的个数  */
int len = length / pNum;
int x,y,/*x,y*/
xp,yp;/*x',y'*/
int outIndex = 0;//输出数组的下标
for (int index = 0; index < len; index++) {
/** The first step is to convert the index => (x,y) */
x = index % widthPerNum;
y = index / widthPerNum;
/** The second step is to convert the (x',y') => out_index */
xp = (heightPerNum - y -1);
yp = x;
outIndex = yp * heightPerNum/*此处为新矩阵的width',所以用原来矩阵的height*/ + xp;
//          String s = String.format("     value - x = %d, y = %d, x' = %d, y' = %d, index = %d, oindex = %d, px = %d", x, y, xp, yp, index, outIndex, in_data[pNum * index]);
//          System.out.println(s);
/** fill data */
for (int j = 0; j < pNum; j++) {
out_data[offset + pNum * outIndex + j] = in_data[srcOffset + pNum * index + j];
}
/** outIndex = ((index % width) + 1) x height - (index / width) - 1 */
}
}


算法B

代码如下

/**
* 旋转NV21
* @param src
* @param dst
* @param W
* @param H
*/
public static void rotateNV21F(byte[] src,byte[] dst,int W,int H)
{
/*
*
*  YYYYYYYYVUVU
*
*/

int k=0;
//--1--rotate Y-----
for(int i=0;i<W;i++)
{
for(int j=H-1;j>=0;j--)
{
dst[k++] = src[j*W+i];
}
}
//--2--rotate VU---
int start = W*H;
int row = H/2;
int col = W/2;

for(int i=0;i<col;i++)//VU的列
{
for(int j=row-1;j>=0;j--)//VU的行数
{

dst[k++]=src[start + (j*col+i)*2];//V
dst[k++]=src[start + (j*col+i)*2+1]; //U

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: