2017-04-26 14 views
1

私は次の問題があります。大きな行列を同じサイズの小さなブロックに分割する方法があります。ブロック上でいくつかの操作を行った後、正しい順序で大きな行列を再構成したいのですが、何とか間違っています。ブロック全体の一覧 - java

次のコードは、2x2に分解する4x4行列を正しく再構成しますが、他の次元では正しく機能しません。

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 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; 
    } 

私はそれをテスト方法:

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); 

しかし、何かのdoesn 't。誰かが私が間違っていたことを説明できますか?

+0

少数側ノート'' yuvMatrix.length'や 'yuvMatrix [0] .length'のようなものをすでに取得できているので、必要としない行列の次元を意味します(2次元を常に信頼できると仮定した場合、サイズ)。さらに、 'blockDimension'が行列の次元の要素であることを確認する必要があります。そうでなければ、それらをブロックに分解することが難しいかもしれません(例えば、5x5行列を2x2ブロックに分解する)。 – Thomas

+0

ええ、私はすでにすべてを知っていましたが、私に思い出させてくれてありがとう。私は彼らが仕事をした後、メソッドをきれいにするつもりだった、今はちょっと混乱しています。 – Pred

+0

あなたが '{blockToMatrix(...)'にコードがありません: '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; 
} 

方法は「doesnのことより短く見えますが、予備チェックを割り引くことはあなたのコードでは13に比べてコードのわずか8行が存在しません。しかしそれはポイントではない。さらに重要なことは、(c+bcのような)わずかな計算しか含まれていないので、ロジックが簡単だということです。

これは非効率的だと思うかもしれませんが、そうではありません。各要素には1回しかアクセスしないため、ネストされたループが4つあっても全体の複雑さは依然としてO(n) 。

行列を構成することも同様に簡単です。あなたが気をつけなければならない主なものは、ブロックの順序です:行優先順序で作成する場合(互いに下にあるブロックがリスト内で隣り合っている場合)、同じ方法で行列を再作成する必要があります。仮定 `width`と`高さ: `matrixToBlocks(長い[] [] yuvMatrix、INT blockDimension、INT幅、INT高さ)(` `とblocksToMatrix(...)`)に

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

関連する問題