旋轉矩陣算法性能問題

背景

最近需要對Android攝像頭採集出來的的NV21數據,做個順時針90度的旋轉,流暢352x288,與標清640x480算法都還能滿足,但是高清1280x720的時候,算法A明顯落後算法B.現在沒時間研究,只能記錄下來,希望你可以提出你們寶貴的意見,讓我少走點彎路.

現象

  1. 在352x288分辨率下,兩者耗時相當20ms左右;
  2. 在640x480時,算法A平均耗時50ms,而算法B平均耗時23ms;
  3. 在1280x720是,算法A平均耗時133ms,而算法B平均耗時55ms;
算法類別\分辨率 352x288 640x480 1280x720
算法A 20ms 50ms 133ms
算法B 20ms 23ms 54ms

算法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

            }
        }
    }
發佈了74 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章