如何在不使用MATLAB循环的情况下从矩阵的每个m×m窗口中提取n个元素?

时间:2011-03-15 16:21:20

标签: matlab matrix

我有一个矩阵和2个参数。第一个参数n是要选择的元素数。第二个是窗口大小m

我想从矩阵中的每个n - by - m窗口中选择m个元素。因此,我们将有p - by - q单元格数组,pmatrix_height/mqmatrix_width/m

单元格数组的每个元素都包含相应窗口中的n个最大数字。它不一定需要是一个单元格数组,它可以是存储必要数据的任何东西。

1 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是首先使用函数IM2COL查找矩阵的所有唯一m - by - m子矩阵,然后使用以下内容按降序对每列进行排序函数SORT,最后提取前n行。如果您的初始矩阵为A且输出矩阵为B,则会出现以下情况:

B = sort(im2col(A,[m m],'distinct'),1,'descend');
B = B(1:n,:);  %# Get the top n values

请注意,B将是n - by - m^2矩阵。如果您想将其转换为p - by - q单元格数组,则可以使用NUM2CELLRESHAPE函数执行此操作:

nBlocks = ceil(size(A)./m);  %# The number of blocks in each dimension
B = reshape(num2cell(B,1),nBlocks(1),nBlocks(2));

修改

如果你还想得到每个值相对于输入矩阵A的索引,那就有点复杂了。您可以通过获取SORT的第二个输出来完成此操作,在这种情况下,该输出将是每个m - { - 1}}子矩阵内的值的线性索引。您可以使用函数IND2SUB将这些转换为下标,然后将行索引和列索引转换为每个m - by - m块的位置:

m

现在,您可以使用函数MAT2CELLRESHAPE将行索引,列索引和值一起收集到单元格数组中:

[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

或者,您可以使用函数NUM2CELLSTRUCTRESHAPE创建结构数组而不是单元数组:

B = mat2cell([r(:) c(:) B(:)],n.*ones(1,size(B,2)));
B = reshape(B,nBlocks(1),nBlocks(2));

注意:

如果B = struct('rowIndices',num2cell(r,1),... 'colIndices',num2cell(c,1),... 'values',num2cell(B,1)); B = reshape(B,nBlocks(1),nBlocks(2)); 的维度不是A的偶数倍,则函数IM2COL将使用零填充部分块。如果任何此零填充出现在块的顶部m值中,则相应的行和列索引中的一个或两个将超出范围(即,具有大于该维度的大小的值)矩阵n)。因此,通过检查行和列索引是否在范围内,您可以确保在后续分析中不包括任何零填充。