One way to do this is by first finding all the unique m
-by-m
submatrices of your matrix using the function IM2COL, then sorting each column in descending order using the function SORT, and finally extracting the top n
rows. If your initial matrix is A
and your output matrix is B
, this is what it would look like:
B = sort(im2col(A,[m m],'distinct'),1,'descend');
B = B(1:n,:); %# Get the top n values
Note that B
will be an n
-by-m^2
matrix. If you want to turn this into a p
-by-q
cell array, you can do this using the functions NUM2CELL and RESHAPE:
nBlocks = ceil(size(A)./m); %# The number of blocks in each dimension
B = reshape(num2cell(B,1),nBlocks(1),nBlocks(2));
EDIT:
If you also want to get the indices of each value with respect to the input matrix A
, that is a bit more complicated. You can do it by getting the second output from SORT, which in this case will be the linear indices of the values within each m
-by-m
submatrix. You can convert these to subscripts using the function IND2SUB, then shift the row and column indices to account for the position of each m
-by-m
block:
[B,index] = sort(im2col(A,[m m],'distinct'),1,'descend');
B = B(1:n,:); %# Get the top n values
index = index(1:n,:); %# Get the top n values
[r,c] = ind2sub([m m],index); %# Convert linear indices to subscripts
nBlocks = size(A)./m; %# The number of blocks in each dimension
r = r+repmat(0:m:(nBlocks(1)-1)*m,n,nBlocks(2)); %# Shift the row indices
c = c+kron(0:m:(nBlocks(2)-1)*m,ones(n,nBlocks(1))); %# Shift the column indices
And now you can collect the row indices, column indices, and values together into a cell array using the functions MAT2CELL and RESHAPE:
B = mat2cell([r(:) c(:) B(:)],n.*ones(1,size(B,2)));
B = reshape(B,nBlocks(1),nBlocks(2));
Alternatively, you can create a structure array instead of a cell array using the functions NUM2CELL, STRUCT, and RESHAPE:
B = struct('rowIndices',num2cell(r,1),...
'colIndices',num2cell(c,1),...
'values',num2cell(B,1));
B = reshape(B,nBlocks(1),nBlocks(2));
NOTE:
The function IM2COL will pad partial blocks with zeroes in the event that a dimension of A
is not an even multiple of m
. If any of this zero-padding appears in the top n
values for a block, one or both of the corresponding row and column indices will be out of range (i.e. have a value larger than the size of that dimension for the matrix A
). Thus by checking that the row and column indices are in range you can make sure you are not including any of the zero-padding in your subsequent analysis.