旋转矩阵算法性能问题

背景

最近需要对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

            }
        }
    }
本人经过几年的努力,终于掌握了C#的编程,与同学一起开发了这套软件。与各位网友共勉。 1.5版正式推出!主要修正了(以下都是重大问题所以应及时更新,对给您造成的不便,本公司深表歉意): 1、重装软件后提示30天试用期已过的BUG; 2、机器码和注册码的0和字母O不好区分的问题。 3、一个注册表错误,会使软件重启后当成试用期结束。 “世间能有几回运,彩票游戏存玄机” ,也许您会有疑问:彩票开奖号码不是完全随机的吗?那我还算什么,随便写几个数字买算了!!其实您错了,世界上并没有绝对理想的随机数,就算是用电脑也只能产生接近随机的数:在彩票开奖产生号码时,诸如摇奖机的物理特性、每个球的重量和光滑度的差异、空气的流动性等等都会使开奖结果产生一定的偏态,在中短期内有一定的规律可寻。 那么怎样才能找出偏态,利用偏态提高中奖的概率呢?用手工显然不行,您需要一款称手软件!但是现在彩票软件多得让人眼花缭乱,哪个才是适合您的呢?得彩易彩票旋转矩阵选号杀号王双色球专用版的问世,解决了您的烦恼,您只要下载使用了,软件就会主动成为您的好帮手,让您中奖不再是梦想! 本公司双色球项目开发小组根据组里多名长年研究彩票双色球的专家的成果,经过反复的概率验证,精心设计了算法,其中大部分属于本公司原创独有。程序运行时随着期数的增加,出号趋势会愈发明显,算法也会愈发准确,一般开奖期数在最近50-150期时效果最为明显。 友情提示:彩票软件可以帮您提高中奖的概率,但并不能保证您100%中大奖,本软件也不例外!如果有所谓专家向您推荐号码并保证能中大奖的,请您一定要当心受骗! 1、本软件基于微软.net框架进行开发,技术先进。 2、市面上的一般彩票软件所提供的旋转矩阵只有廖廖几个方案(如保6中5,保5中4),本软件则提供了几十种方案,应有尽有。 3、选号杀号功能的强大和全面是其它一般彩票软件所没有的。 4、过滤功能全面,完全可以满足需要。 5、开奖数据可以更新,导入和导出,极大的方便彩民朋友。 6、学习容易,帮助文档详尽,上手极快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值