MATLAB: извлечь несколько частей матрицы без использования циклов - PullRequest
8 голосов
/ 25 мая 2009

У меня огромная 2D-матрица, и я хотел бы извлечь из нее 15 различных частей размером 100x100. У меня есть два вектора x и y, где сохраняются верхние левые индексы частей. Я использовал что-то вроде этого:

result = cam1(x(1:end):(x(1:end)+99), y(1:end):(y(1:end)+99));

, но в результате получается матрица 100x100 вместо 15x100x100. Зачем?

Я знаю, что это легко сделать с помощью цикла, но нам не разрешено использовать циклы (это часть упражнения по обработке изображений). Другой возможностью было бы написать все 15 строк, но это довольно уродливо.

У вас есть какое-нибудь элегантное решение? Спасибо.

Ответы [ 3 ]

6 голосов
/ 25 мая 2009

Есть несколько способов сделать это без циклов. Большинство решений включают в себя расширение векторов x и y на более крупные матрицы индексов и, вероятно, использование одной или нескольких функций REPMAT , BSXFUN или SUB2IND . Хороший учебник по матричной индексации можно найти здесь .

Однако, так как вы попросили элегантное решение, вот несколько необычное. Он использует анонимные функции , а также функции ARRAYFUN и CAT :

indexFcn = @(r,c) cam1(r:(r+99),c:(c+99));
result = arrayfun(indexFcn,x,y,'UniformOutput',false);
result = cat(3,result{:});

ПОЯСНЕНИЯ:

Первая строка создает анонимную функцию . Это простая однострочная функция, которая может быть создана на лету без необходимости помещать ее в m-файл. Функция определяет два входа r и c , которые используются для извлечения подматрицы 100 на 100 из cam1 . Переменная indexFcn хранит дескриптор функции , который используется для вызова функции. Обратите внимание, что значения cam1 , используемые анонимной функцией, равны static . Даже если значения в переменной cam1 изменяются, анонимная функция по-прежнему использует значения, которые были в cam1 при создании функции.

Вторая строка вызывает ARRAYFUN, который применяет функцию к каждому элементу массива. ARRAYFUN проходит по каждой записи в x и y , передавая значения в indexFcn . Вывод сохраняется в result , 15-элементном массиве ячеек, где каждая ячейка содержит матрицу 100 на 100.

Третья строка использует функцию CAT для объединения матриц 100 на 100 в матрицу 100 на 100 на 15.

4 голосов
/ 25 мая 2009

Поскольку это, очевидно, домашнее задание, я не дам вам полный ответ.

Существует несколько способов индексации в матрице. Когда у вас есть такой разбросанный индекс, вам нужно использовать один индекс. Таким образом, если

A = rand(5,6)
A =
      0.81472      0.09754      0.15761      0.14189      0.65574      0.75774
      0.90579       0.2785      0.97059      0.42176     0.035712      0.74313
      0.12699      0.54688      0.95717      0.91574      0.84913      0.39223
      0.91338      0.95751      0.48538      0.79221      0.93399      0.65548
      0.63236      0.96489      0.80028      0.95949      0.67874      0.17119

A(3:4,3:4)

даст 2x2 подматрицу от A. Но мы также можем найти эту подматрицу как

reshape(A([13 14 18 19]),[2 2])
ans =
      0.95717      0.91574
      0.48538      0.79221

Почему я выбрал этот набор индексов? Для ответа вам нужно прочитать о sub2ind.

[I,J] = ndgrid(3:4,3:4);
sub2ind([5 6],I(:),J(:))
ans =
    13
    14
    18
    19

В конце концов, похоже, что вы хотите массив 15x100x100 из извлеченных частей. Итак, соберите необходимый индексный массив из частей, которые я показал. Вам нужно будет сделать окончательное изменение формы в конце, чтобы придать ему правильную форму.

Это должно дать вам достаточно начала, чтобы закончить домашнее задание.

0 голосов
/ 22 июня 2012

Вы думаете, что все сложно, попробуйте это: mat2cell

...