#matlab #multidimensional-array #neighbours
#matlab #многомерный массив #соседи
Вопрос:
Я немного сбит с толку и был бы очень признателен за некоторую помощь.
Я прочитал много сообщений о поиске соседних пикселей, и это чрезвычайно полезно:
http://blogs.mathworks.com/steve/2008/02/25/neighbor-indexing-2/
Однако у меня возникли проблемы с применением его к матрице 4D (A) с размером (A) = [8 340 340 15]. Он представляет собой 8 групп 3D-изображений (по 15 фрагментов в каждой), из которых я хочу получить соседей. Я не уверен, какой размер использовать для вычисления смещений. Это код, который я пробовал, но я думаю, что он не работает, потому что смещения должны быть адаптированы для 4 измерений? Как я могу сделать это без цикла?
%A is a 4D matrix with 0 or 1 values
Aidx = find(A);
% loop here?
[~,M,~,~] =size(A);
neighbor_offsets = [-1, M, 1, -M]';
neighbors_idx = bsxfun(@plus, Aidx', neighbor_offsets(:));
neighbors = B(neighbors_idx);
Спасибо,
Зигги
Комментарии:
1. Будет ли что-то вроде bwlabeln работать для этого случая?
2. у вас ошибка: что произойдет, если один из
Aidx
них находится на границе изображения? в этом случае выneighbors
будете указывать за пределы изображения…3. Каких соседей вы ищете? 4 соседи по второму измерению?
4. Я точно знаю, что в конкретных наборах данных у меня не будет Aidx в границах изображения. Я ищу 4 соседей на каждом срезе в каждой группе, так что эффективно на каждом изображении (340 * 340). Затем мне нужно будет создать маску ненулевых соседей и применить ее к другой матрице.
Ответ №1:
Рассматривали ли вы возможность использования convn
?
msk = [0 1 0; 1 0 1; 0 1 0];
msk4d = permute( msk, [3 1 2 4] ); % make it 1-3-3-1 mask
neighbors_idx = find( convn( A, msk4d, 'same' ) > 0 );
Возможно, вам будет conndef
полезно определить basic msk
в общем виде.
Комментарии:
1. Что
A
в этом примере? Это линейный индекс элемента, соседей которого вы ищете? Конечно, вам все равно нужно было бы предоставитьconvn
некоторую информацию о размере исходной матрицы?2. @Dan
A
— это 4-мерная логическая матрица, определенная OP.3. Мне тоже нравится это решение. Не могли бы вы опубликовать вывод, чтобы показать, что соседи также идентифицированы, пожалуйста?
4. @kkuilla поскольку у меня нет входных данных, я не могу опубликовать выходные данные 😉
5. Шай, один thing..in ваша вторая строка с функцией перестановки, msk4d — это не маска 1-3-3-1, я думаю, что это 1-3-3
Ответ №2:
Не уверен, понял ли я ваш вопрос, но как насчет такого подхода:
если ваша матрица равна 1D:
M = rand(10,1);
N = M(k-1:k 1); %//immediate neighbours of k
Однако это может привести к ошибке, если k
находится на границе. Это легко исправить с помощью max
и min
:
N = M(max(k-1,1):min(k 1,size(M,1))
Теперь давайте добавим измерение:
M = rand(10,10);
N = M(max(k1-1,1):min(k1 1,size(M,1), max(k2-1,1):min(k2 1,size(M,2))
Это было легко, все, что вам нужно было сделать, это повторить тот же индекс, внеся незначительные изменения в использование size(M,2)
для границы (а также я изменил k
на k1
and k2
, вы можете обнаружить, что использование массива for k
вместо отдельных k1
k2
переменных and работает лучше, т.е. k(1)
and k(2)
)
ХОРОШО, теперь давайте перейдем к 4 измерениям:
M = rand(10,10,10,10);
N = M(max(k(1)-1,1):min(k(1) 1,size(M,1)), ...
max(k(2)-1,1):min(k(2) 1,size(M,2)), ...
max(k(3)-1,1):min(k(3) 1,size(M,3)), ...
max(k(4)-1,1):min(k(4) 1,size(M,4))); %// Also you can replace all the `size(M,i)` with `end` if you like
Я знаю, вы сказали, что вам не нужен цикл, но как насчет действительно короткого цикла, чтобы немного реорганизовать, а также сделать его обобщенным:
n=ndims(M);
ind{n} = 0;
for dim = 1:n
ind{dim} = max(k(dim)-1,1):min(k(dim) 1,size(M,dim));
end
N = M(ind{:});
Комментарии:
1. Спасибо за этот очень подробный ответ, Дэн! Извините, у меня недостаточно репутации, чтобы поддержать его. Я принял ответ Шая, потому что он более компактный и работает хорошо.
Ответ №3:
Вот как получить соседей по второму измерению
sz = size( A );
ndims = numel(sz); % number of dimensions
[d{1:ndims}] = ind2sub( sz, find( A ) );
alongD = 2; % work along this dim
np = d{alongD} 1;
sel = np <= sz( alongD ); % discard neighbors that fall outside image boundary
nm = d{alongD} - 1;
sel = sel amp; nm > 0; % discard neighbors that fall outside image boundary
d = cellfun( @(x) x(sel), d, 'uni', 0 );
neighbors = cat( 1, ...
ind2sub( sz, d{1:alongD-1}, np(sel), d{alongD 1:end} ),...
ind2sub( sz, d{1:alongD-1}, nm(sel), d{alongD 1:end} ) );