Efficient overlapping block processing with nested sub blocks (similar to im2col with stride)
Mostrar comentarios más antiguos
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.
1 comentario
Matthew
el 23 de Mzo. de 2026 a las 4:36
Respuesta aceptada
Más respuestas (1)
If the reordering is something you want to repeat on multiple matrices of the same size and block structure, then you can use your current method once, and recycle some intermediate results to make subsequent processing faster. This generalizes very easily to other dimensions and other kinds of reorderings:
clc,
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').'*10
tic; %pre-computation
[tmp,mask,idx]=Reordering(size(A),n);
toc;
tic; %subsequent passes
C=tmp;
C(mask)=A(idx);
toc;
C
function [C,mask,idx]=Reordering(dims,n)
A=reshape(1:prod(dims),dims);
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);
% 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
mask=logical(C);
idx=C(mask);
end
1 comentario
Matthew
hace alrededor de 19 horas
Categorías
Más información sobre Shifting and Sorting Matrices en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!