2017-04-26 65 views
1

所以我有以下問題:我有一個方法將一個大矩陣分成相同大小的較小塊。在我對塊進行了一些操作之後,我想按照正確的順序重構這個大矩陣,但是我會以某種方式出錯。整個矩陣塊的列表 - java

以下代碼正確地重建了一個4x4矩陣,該矩陣可以分解爲2x2,但對於任何其他維度而言,它無法正常工作。

public long[][] blocksToMatrix(List<long[][]> blocks, int blockDimension, int width, int height){ 
     long[][] yuvMatrix = new long[height][width]; 
     int heightPos = 0; 
     int widthPos = 0; 
     for (int i = 0; i < blocks.size(); i++) { 
     long[][] yuvBlock = blocks.get(i); 
     int heightPosTemp = heightPos; 
     for (int j = 0; j < blockDimension * blockDimension; j++) { 
      yuvMatrix[heightPos][widthPos] = yuvBlock[j/blockDimension][j % blockDimension]; 
      widthPos++; 
      if (widthPos >= width){ 
       widthPos = (i * blockDimension) % width; 
       heightPos++; 
      } 
      if (widthPos == ((i + 1) * blockDimension) % width){ 
       widthPos = (i * blockDimension) % width; 
       heightPos++; 
      } 
     } 
     if (heightPos == height){ 
      heightPos = heightPosTemp; 
     } 
     else { 
      heightPos = (i * blockDimension) % height; 
     } 
     widthPos = ((i + 1) * blockDimension) % width; 
     } 
     return yuvMatrix; 
    } 

我用來打破的矩陣的方法:

public static void testareMatBlo(int height, int width, int blockdim){ 
     long[][] test = new long[height][width]; 
     int val = 1; 
     for (int i = 0; i < height; i++){ 
     for (int j = 0; j < width; j++){ 
      test[i][j] = val; 
      val++; 
     } 
     } 
     List<long[][]> blocks = matrixToBlocks(test, blockdim, width, height); 
     long[][] matrix = blocksToMatrix(blocks, blockdim, width, height); 
     if (Arrays.deepEquals(test, matrix)){ 
     System.out.println("YES"); 
     } 
     else { 
     System.out.println("NO"); 
     } 
    } 

這工作:

testareMatBlo(4, 4, 2); 

但什麼都沒有按

public List<long[][]> matrixToBlocks(long[][] yuvMatrix, int blockDimension, int width, int height){ 
     int blocksSize = width/blockDimension * (height/blockDimension); 
     List<long[][]> blocks = new ArrayList<long[][]>(); 
     for (int i = 0; i < blocksSize; i++) { 
     long[][] subBlock = new long[blockDimension][blockDimension]; 
     int heightPos = (blockDimension * (i/blockDimension)) % height; 
     int widthPos = (blockDimension * i) % width; 
     if (widthPos + blockDimension > width) { 
      widthPos = 0; 
     } 
     for (int row = 0; row < blockDimension; row++) { 
      for (int col = 0; col < blockDimension; col++) { 
       subBlock[row][col] = yuvMatrix[heightPos + row][col + widthPos]; 
      } 
     } 
     blocks.add(subBlock); 
     } 
     return blocks; 
    } 

我測試了它的方式「T。任何人都可以解釋我做錯了什麼?

+0

上'matrixToBlocks幾側音符(長[] [] yuvMatrix,整數blockDimension,INT寬度,高度INT)'(和'blocksToMatrix(...)'):假定'width'和'高度意思是你可能不需要它們的矩陣的維數,因爲你已經可以像'yuvMatrix.length'和'yuvMatrix [0] .length'那樣得到它們(假設你可以相信第二維總是具有相同的尺寸)。另外,你應該確保'blockDimension'是矩陣維數的一個因素,否則你可能在分解成塊的時候遇到困難(例如,將5×5矩陣分解成2×2塊)。 – Thomas

+0

是的,我已經知道所有這些,但是謝謝你提醒我。在我讓他們工作之後,我正在清理這些方法,現在他們有點混亂。 – Pred

+0

You'r'blocksToMatrix(...)'缺少一些代碼:'long [] [] yuvBlock = blocks.get(i);' - 'i'沒有在您發佈的代碼中定義。 – Thomas

回答

1

我沒有仔細閱讀你的代碼matrixToBlocks(...)但像int blocksSize = width/blockDimension * (height/blockDimension);所有這些計算是非常有可能引進很難發現錯誤 - 你其實並不需要他們:

public static List<long[][]> matrixToBlocks(long[][] yuvMatrix, int blockDimension){  
    //Check matrix and block dimension match 
    if(yuvMatrix.length == 0 || yuvMatrix.length % blockDimension != 0 
    || yuvMatrix[0].length == 0 || yuvMatrix[0].length % blockDimension != 0) { 
    throw new IllegalArgumentException("whatever message you like"); 
    } 

    List<long[][]> blocks = new ArrayList<long[][]>(); 

    //Iterate over the blocks in row-major order (down first, then right) 
    for(int c = 0; c < yuvMatrix.length; c += blockDimension) { 
    for(int r = 0; r < yuvMatrix[c].length; r += blockDimension) { 
     long[][] subBlock = new long[blockDimension][blockDimension]; 

     //Iterate over the block in row-major order 
     for(int bc = 0; bc < blockDimension; bc++) { 
     for(int br = 0; br < blockDimension; br++) { 
      subBlock[bc][br]=yuvMatrix[c+bc][r+br]; 
     } 
     }  

     blocks.add(subBlock); 
    } 
    } 

    return blocks; 
} 

這種方法沒有按」看起來更短,但它是:折扣你的初步檢查是缺少的只有8個實際的代碼行,而你的代碼只有13個。但這不是關鍵。更重要的是邏輯更簡單,因爲只涉及少量計算(如c+bc)。

您可能認爲這樣做效率不高,但它不是:您只訪問一次元素,因此即使有4個嵌套循環,總體複雜度仍然是O(n),其中n是矩陣的大小。

構造回矩陣同樣容易。您需要關注的主要問題是塊的排序:如果您按照主要行的順序創建它們(塊之下的塊在列表中彼此相鄰),則需要按照相同的方式重新創建矩陣:

public static long[][] blocksToMatrix(List<long[][]> blocks, int width, int height) { 
    long[][] yuvMatrix = new long[width][height]; 
    int c = 0; 
    int r = 0; 

    for(long[][] block : blocks) { 
    int blockWidth = block.length; 
    int blockHeight = block[0].length; 

    for(int bc = 0; bc < block.length; bc++) { 
     for(int br = 0; br < block[bc].length; br++) { 
     yuvMatrix[c + bc][r + br] = block[bc][br]; 
     } 
    } 

    //calculate the next offset into the matrix 
    //The blocks where created in row-major order so we need to advance the offset in the same way 
    r += blockHeight; 
    if(r >= height) { 
     r = 0; 
     c += blockWidth; 
    } 
    } 

    return yuvMatrix; 
} 
+0

謝謝你,你是對的,這看起來更乾淨,但仍然存在重建矩陣的問題,'blocksToMatrix(...)'方法仍然存在。 – Pred

+0

@Pred看到我的更新,我剛剛添加它。 – Thomas

+0

這太好了,謝謝。現在一切似乎都更加清潔。但似乎仍然有一個小問題,測試似乎失敗了,因爲以下參數'testareMatBlo(800,600,8);' – Pred