Как я могу извлечь n элементов из каждого м-м-м окна матрицы без использования циклов в MATLAB? - PullRequest
1 голос
/ 15 марта 2011

У меня есть матрица и 2 параметра. Первый параметр n - это количество элементов, которые нужно выбрать. Второй размер окна m.

Я хочу выбрать n количество элементов из каждого окна m -by- m из матрицы. В результате у нас будет массив ячеек p -by- q, где p равно matrix_height/m и q равно matrix_width/m.

Каждый элемент массива ячеек содержит n наибольшие числа из соответствующего окна. Это не обязательно должен быть массив ячеек, это может быть что угодно, что будет хранить необходимые данные.

1 Ответ

3 голосов
/ 15 марта 2011

Один из способов сделать это - сначала найти все уникальные m -by- m подматрицы вашей матрицы, используя функцию IM2COL , а затем отсортировать каждый столбец в порядке убывания, используя функцию 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, вы можете сделать это, используя функции NUM2CELL и RESHAPE :

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

EDIT:

Если вы также хотите получить индексы каждого значения относительно входной матрицы A, это немного сложнее. Вы можете сделать это, получив второй вывод из SORT , который в этом случае будет линейным индексом значений в каждой подматрице m -by- m. Вы можете преобразовать их в подписки, используя функцию IND2SUB , а затем сдвинуть индексы строк и столбцов, чтобы учесть положение каждого m -by- m блока:

[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

И теперь вы можете собирать индексы строк, индексы столбцов и значения вместе в массив ячеек, используя функции MAT2CELL и RESHAPE :

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

В качестве альтернативы вы можете создать структурный массив вместо массива ячеек, используя функции NUM2CELL , STRUCT и RESHAPE :

B = struct('rowIndices',num2cell(r,1),...
           'colIndices',num2cell(c,1),...
           'values',num2cell(B,1));
B = reshape(B,nBlocks(1),nBlocks(2));

Примечание:

Функция IM2COL будет заполнять частичные блоки нулями в случае, если размерность A не кратна m. Если какое-либо из этих дополнений нулями появляется в верхних значениях n для блока, один или оба из соответствующих индексов строки и столбца будут вне диапазона (то есть имеют значение, превышающее размер этого измерения для матрицы A). Таким образом, проверив, что индексы строк и столбцов находятся в диапазоне, вы можете убедиться, что вы не включили ни одного дополнения нулями в последующий анализ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...