Как взять часть матрицы, если неизвестное число измерений в Matlab?

Предположим, я хочу сделать что-то похожее на

image(1:end-1,2:end,:)

который здесь занимает часть цветного изображения

но с неизвестным количеством измерений, т.е. который будет работать автоматически, как

image(1:end-1,2:end)

для 2 измерений

image(1:end-1,2:end,:)

на 3 и

image(1:end-1,2:end,:,:)

на 4 и так далее.


person Suzan Cioc    schedule 23.06.2013    source источник


Ответы (4)


Если вы всегда хотите взять все 3-е мерцание и выше, вы можете использовать

>> image(1:end-1,2:end,:,:,:)

даже для 2D массива.

В качестве альтернативы вы можете использовать subsref для менее специального/хакерского подхода:

>> [S.subs{1:ndims(image)}] = deal(':');
>> S.subs{1} = '1:end-1';
>> S.subs{2} = '2:end';
>> S.type = '()';
>> subsref(image, S )
person Shai    schedule 23.06.2013
comment
Шай предлагает решение задачи MATLAB, которое не использует bsxfun!? :) - person Dang Khoa; 24.06.2013
comment
@DangKhoa, не забывайте, что у меня есть фоновый процесс, который запускает bsxfun в цикле (цикл векторизации), поэтому каждое мое решение имеет bsxfun (и даже это рифмуется;) - person Shai; 24.06.2013

У меня есть две идеи на этот случай.

1-й способ: вы могли изменить форму изображения раньше, например,

% transform image to 3d format
% do not forget to transform all used entities to this 3d-format as well
sizeIm = size(image);
image3 = reshape(image,[sizeIm(1:2),prod(sizeIm(3:end)])

% work on image3
image3(1:end-1,2:end,:) = ...;

% transform back:
image = reshape(image3,sizeIm);

2-й способ: может быть решением использовать eval и repmat, например.

eval(['image(1:end-1,2:end',repmat(',:',[1,length(size(image))-2]) ')'])

Немного зависит от того, для чего вы его используете (настройка, получение, ...).

person matheburg    schedule 23.06.2013
comment
-1 За оценку. Код и так не просто читать, с eval() будет кошмар. - person Oleg; 23.06.2013
comment
Вау... это справедливо! Это всего лишь одно предложение. Вы знаете, где и как именно он хочет его использовать? - person matheburg; 23.06.2013
comment
Я голосую против eval() решений в 99% случаев (в будущем я обновлю свое описание, почему). - person Oleg; 23.06.2013
comment
Я знаю много аргументов против eval самостоятельно, тем не менее, я дал 2 более или менее полезных ответа, которые вы, конечно, не должны голосовать, но предупредительного комментария с аргументами против 2-го пути было бы более чем достаточно. - person matheburg; 23.06.2013
comment
С другой стороны, преображение приятное. - person Oleg; 24.06.2013

Предположим, у вас есть массив A:

A  = rand(2,3,2,5,7);

Затем вы можете заполнить ':' оставшимися размерами вашего выбора:

nd   = ndims(A);
subs = repmat({':'},1,nd-2);
A(1:end-1,2:end, subs{:})
person Oleg    schedule 23.06.2013

У меня есть небольшая идея. Вы можете сформулировать функцию, которая анализирует размер вашей Матрицы с помощью size(size(Matrix),2). Затем вы можете создать строку, содержащую нужную команду, с небольшим циклом for, и после этого вы выполняете эту строку с помощью eval.

A=rand(3,3,3,3,3,3,3,3,3,3) %<--- change here dimension

dim=size(size(A),2)

addstr='';
if dim>2
    for i=1:dim-2
        addstr=[addstr ',:'];
    end
end

command=['A(1:2,1:2' addstr ')']

eval(command)
person Erik Sommer    schedule 23.06.2013
comment
Эй, я разместил это 15 минут назад в одной строке. Я полагаю, что Олег скоро поставит вам минус ;-) - person matheburg; 24.06.2013
comment
@matheburg ты так прав. Потому что я думаю, что это не такая уж плохая идея, я снова проголосую за вас ;-) - person Erik Sommer; 24.06.2013