所以我遇到了以下问题:我有一种方法可以将大矩阵分解为相同大小的较小块。在对 block 进行一些操作后,我想以正确的顺序重建大矩阵,但我在某种程度上出错了。
以下代码可以正确重建分解为 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);
但是其他的都没有。谁能解释一下我做错了什么?
最佳答案
我没有彻底阅读您的matrixToBlocks(...)
代码,但是所有这些计算,例如intblockSize = 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 是矩阵的大小。
构造矩阵同样容易。您需要注意的主要事情是 block 的顺序:如果您按行优先顺序创建它们(彼此下方的 block 在列表中彼此相邻),则需要以相同的方式重新创建矩阵:
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;
}
关于java - 整个矩阵的 block 列表 - java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43629389/