Как найти соседей в массиве 4D в MATLAB?

#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} ) );