旋转矩阵算法性能问题

背景

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

现象

  1. 在352x288分辨率下,两者耗时相当20ms左右;
  2. 在640x480时,算法A平均耗时50ms,而算法B平均耗时23ms;
  3. 在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

            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值