2016-04-13 9 views
2

В Matlab у меня есть матрица, где некоторые элементы установлены в ноль. Например:Matlab - Найти индексы ближайшего ненулевого элемента для каждого элемента нулевой матрицы

0 1 0 0 0 
2 5 0 3 0 
0 0 0 0 0 
0 5 0 2 1 

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

+0

'diff' может быть полезным. –

+1

Что вы подразумеваете под ближайшим? Вертикально, горизонтально, по диагонали? – DeeCee

+0

@dean_sh: Необходимо учитывать все указанные вами маршруты. –

ответ

4

Там находится в IPT эффективной bwdist function, что вычисляет distance transform:

M = [ 
    0 1 0 0 0 
    2 5 0 3 0 
    0 0 0 0 0 
    0 5 0 2 1 
]; 
[D,IDX] = bwdist(M~=0) 

Результат:

D = 
    1.0000   0 1.0000 1.0000 1.4142 
     0   0 1.0000   0 1.0000 
    1.0000 1.0000 1.4142 1.0000 1.0000 
    1.0000   0 1.0000   0   0 

IDX = 
      2   5   5   14   14 
      2   6   6   14   14 
      2   6   6   14   20 
      8   8   8   16   20 

Возвращенный IDX содержит линейные индексы ближайшего ненулевого значения в M. Он возвращает только один индекс на элемент.

+1

Дистанционное преобразование - это путь №1 для этого ... тем более, что есть очень эффективные реализации, которые не являются грубой силой. +1 от меня. – rayryeng

3

Вот Векторизованный подход с использованием bsxfun и mat2cell, который хранит индексы ненулевых ближайших элементов (евклидов расстояния) для каждого нулевого элемента в ячейке каждый -

%// Assuming A as the input matrix. Store rows, columns of zero and non-zeros 
[rz,cz] = find(A==0); 
[rnz,cnz] = find(A~=0); 

%// Store zero pt indices 
zero_pts = [rz cz]; 

%// Get squared euclidean distances 
dists = bsxfun(@minus,rnz,rz.').^2 + bsxfun(@minus,cnz,cz.').^2; 

%// Get all nearest XY indices of nonzeros for each zero pt 
[R_idx,C_idx] = find(bsxfun(@eq,min(dists,[],1),dists)); 
idx = [rnz(R_idx) cnz(R_idx)]; 

%// Cut at each shifting positions and thus create a cell array, with a 
%// cell of indices of non-zero nearest elements for each zero element 
nearest_nnonzero_pts = mat2cell(idx,histc(C_idx,1:max(C_idx))) 

ввода образца, выход -

Входной сигнал:

>> A 
A = 
    0  1  0  0  0 
    2  5  0  3  0 
    0  0  0  0  0 
    0  5  0  2  1 

Выход (Ноль очков):

>> disp(zero_pts) 
    1  1 
    3  1 
    4  1 
    3  2 
    1  3 
    2  3 
    3  3 
    4  3 
    1  4 
    3  4 
    1  5 
    2  5 
    3  5 

выход (корреспондент ближайших ненулевых точек):

>> celldisp(nearest_nnonzero_pts) 
nearest_nnonzero_pts{1} = 
    2  1 
    1  2 
nearest_nnonzero_pts{2} = 
    2  1 
nearest_nnonzero_pts{3} = 
    4  2 
nearest_nnonzero_pts{4} = 
    2  2 
    4  2 
nearest_nnonzero_pts{5} = 
    1  2 
nearest_nnonzero_pts{6} = 
    2  2 
    2  4 
nearest_nnonzero_pts{7} = 
    2  2 
    4  2 
    2  4 
    4  4 
nearest_nnonzero_pts{8} = 
    4  2 
    4  4 
nearest_nnonzero_pts{9} = 
    2  4 
nearest_nnonzero_pts{10} = 
    2  4 
    4  4 
nearest_nnonzero_pts{11} = 
    2  4 
nearest_nnonzero_pts{12} = 
    2  4 
nearest_nnonzero_pts{13} = 
    4  5