Efficient overlapping block processing with nested sub blocks (similar to im2col with stride)
Hello, I recently have been doing a side project to teach myself some more efficient and performance optimized MATLAB and I ran into the following problem. My solution feels "ugly" to me and I highly suspect that there is a better version. I am intentionally straying from builtin functions like im2col and blockproc but I definitely am not asking you to restrict your solutions especially if they are high performance.
Problem:
An example of the input to the problem is generated by the following code. It consists of square matrix with nxn blocks. I use ascending integers to make it easier to keep track of the format of the data.
% example input matrix A with nxn blocks
n = 2;
N = 2*n^2;
A = kron((1:n^2).’,ones(1,2*N)) + (1:n^2:N^2) – 1;
[row,col] = ind2sub([n n],1:n^2);
A((row-1).*n+col,:) = A((col-1).*n+row,:);
A = col2im(A, [n n], [N N], ‘distinct’).’
The desired output from the input is to take a sliding block of 2n x 2n with a stride of n in both the x and y directions. This generates a block with 4 subblocks of size n x n. I would like to generate a similar result of im2col, but with the caveat that the column result keeps the individual sub blocks together (as if I had taken im2col of each of the sub blocks and then stacked them into a single column). Normally im2col scans the matrix top to bottom and left to right, but the final desired requirement is that the columns come from a sweep from left to right and then top to bottom.
My solution is:
% intermediate matrix B with 2n patches with n stride
M = length(A(:,1)) + n;
A(end+1:M,end+1:M) = 0;
[x,y] = meshgrid(1:2*n);
[xs,ys] = meshgrid(0:n:(M-2*n));
idx = (reshape(y,4*n^2,[]) + ys(:)’) + (M*reshape(x-1,4*n^2,[]) + M*xs(:)’);
colB = A(idx);
% these 2 lines not part of my solution but may help visualize the
% intermediate step of expanding the matrix
szB = sqrt(numel(colB));
B = col2im(colB, [2*n 2*n], [szB szB], ‘distinct’);
% reshape and permute chain for desired format and ordering
C = reshape(colB,n,2,[]);
C = permute(C,[1 3 2]);
C = reshape(C, 4*n^2, n, []);
C = permute(C, [1 3 2]);
C = reshape(C, 4*n^2,[]) % final desired output
The final result is good for general n and the solution runs decently fast. However it just looks like there is still performance to squeeze out of this. I feel like there is a more direct method than constructing the intermediate matrix and then decomposing it. I also feel like there is a better reordering process than my reshape->permute->reshape->permute->reshape. After too many hours trying I am forced to concede but hopefully someone here can teach me something new. Thanks in advance.Hello, I recently have been doing a side project to teach myself some more efficient and performance optimized MATLAB and I ran into the following problem. My solution feels "ugly" to me and I highly suspect that there is a better version. I am intentionally straying from builtin functions like im2col and blockproc but I definitely am not asking you to restrict your solutions especially if they are high performance.
Problem:
An example of the input to the problem is generated by the following code. It consists of square matrix with nxn blocks. I use ascending integers to make it easier to keep track of the format of the data.
% example input matrix A with nxn blocks
n = 2;
N = 2*n^2;
A = kron((1:n^2).’,ones(1,2*N)) + (1:n^2:N^2) – 1;
[row,col] = ind2sub([n n],1:n^2);
A((row-1).*n+col,:) = A((col-1).*n+row,:);
A = col2im(A, [n n], [N N], ‘distinct’).’
The desired output from the input is to take a sliding block of 2n x 2n with a stride of n in both the x and y directions. This generates a block with 4 subblocks of size n x n. I would like to generate a similar result of im2col, but with the caveat that the column result keeps the individual sub blocks together (as if I had taken im2col of each of the sub blocks and then stacked them into a single column). Normally im2col scans the matrix top to bottom and left to right, but the final desired requirement is that the columns come from a sweep from left to right and then top to bottom.
My solution is:
% intermediate matrix B with 2n patches with n stride
M = length(A(:,1)) + n;
A(end+1:M,end+1:M) = 0;
[x,y] = meshgrid(1:2*n);
[xs,ys] = meshgrid(0:n:(M-2*n));
idx = (reshape(y,4*n^2,[]) + ys(:)’) + (M*reshape(x-1,4*n^2,[]) + M*xs(:)’);
colB = A(idx);
% these 2 lines not part of my solution but may help visualize the
% intermediate step of expanding the matrix
szB = sqrt(numel(colB));
B = col2im(colB, [2*n 2*n], [szB szB], ‘distinct’);
% reshape and permute chain for desired format and ordering
C = reshape(colB,n,2,[]);
C = permute(C,[1 3 2]);
C = reshape(C, 4*n^2, n, []);
C = permute(C, [1 3 2]);
C = reshape(C, 4*n^2,[]) % final desired output
The final result is good for general n and the solution runs decently fast. However it just looks like there is still performance to squeeze out of this. I feel like there is a more direct method than constructing the intermediate matrix and then decomposing it. I also feel like there is a better reordering process than my reshape->permute->reshape->permute->reshape. After too many hours trying I am forced to concede but hopefully someone here can teach me something new. Thanks in advance. Hello, I recently have been doing a side project to teach myself some more efficient and performance optimized MATLAB and I ran into the following problem. My solution feels "ugly" to me and I highly suspect that there is a better version. I am intentionally straying from builtin functions like im2col and blockproc but I definitely am not asking you to restrict your solutions especially if they are high performance.
Problem:
An example of the input to the problem is generated by the following code. It consists of square matrix with nxn blocks. I use ascending integers to make it easier to keep track of the format of the data.
% example input matrix A with nxn blocks
n = 2;
N = 2*n^2;
A = kron((1:n^2).’,ones(1,2*N)) + (1:n^2:N^2) – 1;
[row,col] = ind2sub([n n],1:n^2);
A((row-1).*n+col,:) = A((col-1).*n+row,:);
A = col2im(A, [n n], [N N], ‘distinct’).’
The desired output from the input is to take a sliding block of 2n x 2n with a stride of n in both the x and y directions. This generates a block with 4 subblocks of size n x n. I would like to generate a similar result of im2col, but with the caveat that the column result keeps the individual sub blocks together (as if I had taken im2col of each of the sub blocks and then stacked them into a single column). Normally im2col scans the matrix top to bottom and left to right, but the final desired requirement is that the columns come from a sweep from left to right and then top to bottom.
My solution is:
% intermediate matrix B with 2n patches with n stride
M = length(A(:,1)) + n;
A(end+1:M,end+1:M) = 0;
[x,y] = meshgrid(1:2*n);
[xs,ys] = meshgrid(0:n:(M-2*n));
idx = (reshape(y,4*n^2,[]) + ys(:)’) + (M*reshape(x-1,4*n^2,[]) + M*xs(:)’);
colB = A(idx);
% these 2 lines not part of my solution but may help visualize the
% intermediate step of expanding the matrix
szB = sqrt(numel(colB));
B = col2im(colB, [2*n 2*n], [szB szB], ‘distinct’);
% reshape and permute chain for desired format and ordering
C = reshape(colB,n,2,[]);
C = permute(C,[1 3 2]);
C = reshape(C, 4*n^2, n, []);
C = permute(C, [1 3 2]);
C = reshape(C, 4*n^2,[]) % final desired output
The final result is good for general n and the solution runs decently fast. However it just looks like there is still performance to squeeze out of this. I feel like there is a more direct method than constructing the intermediate matrix and then decomposing it. I also feel like there is a better reordering process than my reshape->permute->reshape->permute->reshape. After too many hours trying I am forced to concede but hopefully someone here can teach me something new. Thanks in advance. reshaping, im2col, block processing MATLAB Answers — New Questions









