Определите соседние суперпиксели итеративно

Позволять A быть:

 1 1 1 1 1 1
 1 2 2 3 3 3
 4 4 2 2 3 4
 4 4 4 4 4 4
 4 4 5 5 6 6
 5 5 5 5 5 6

Мне нужно идентифицировать смежные пиксели конкретного суперпикселя,

например

1-я смежность 2 является 1, 3, 4

2-я смежность 2 является 5, 6

3-я смежность 2 является...

Какой самый быстрый способ сделать это?

3 ответа

Вот еще один подход повторного использования кода из вашего предыдущего вопроса:

%// create adjacency matrix
%// Includes code from @LuisMendo's answer
% // Data:
A = [ 1 1 1 1 1 1
      1 2 2 3 3 3
      4 4 2 2 3 4
      4 4 4 4 4 4
      4 4 5 5 6 6
      5 5 5 5 5 6 ];

adj = [0 1 0; 1 0 1; 0 1 0]; %// define adjacency. [1 1 1;1 0 1;1 1 1] to include diagonals

nodes=unique(A);
J=zeros(numel(nodes));
for value=nodes.'
   mask = conv2(double(A==value), adj, 'same')>0; %// from Luis' code
   result = unique(A(mask));                      %// from Luis' code
   J(value,result)=1;
   J(value,value)=0;
end

J теперь матрица смежности для вашей матрицы A, и это становится проблемой графа. Отсюда вы будете использовать соответствующий алгоритм, чтобы найти кратчайший путь. Длина пути 1 - это ваша "1-я смежность", длина пути 2 - "2-я смежность" и так далее.

  • Дейкстра, чтобы найти кратчайший путь из одного узла
  • Флойд-Варшалл, чтобы найти кратчайшие пути из всех узлов
  • Поиск в ширину для одного узла, плюс вы можете создать удобное дерево

Обновить

Я решил поиграть с настраиваемым обходом в ширину, чтобы использовать в этом случае, и это хорошая вещь, которую я сделал. Он выявил некоторые явные ошибки в моем псевдокоде, которые были исправлены выше с помощью работающего кода Matlab.

Используя ваш пример данных, код выше генерирует следующую матрицу смежности:

J =

   0   1   1   1   0   0
   1   0   1   1   0   0
   1   1   0   1   0   0
   1   1   1   0   1   1
   0   0   0   1   0   1
   0   0   0   1   1   0

Затем мы можем выполнить обход графика в глубину, поместив каждый уровень дерева в ширину в ряд массива ячеек так, чтобы D{1} перечисляет узлы, которые имеют расстояние 1, D{2} имеет расстояние 2 и т. д.

function D = BFD(A, s)
%// BFD - Breadth-First Depth
%// Find the depth of all nodes connected to node s
%// in graph A (represented by an adjacency matrix)
   A=logical(A);   %// all distances are 1
   r=A(s,:);       %// newly visited nodes at the current depth
   v=r;            %// previously visited nodes
   v(s)=1;         %// we've visited the start node
   D={};           %// returned Depth list
   while any(r)
      D(end+1,:)=find(r);
      r=any(A(r,:))&~v;
      v=r|v;
   end
 end

Для начального узла 2, вывод:

>> D=BFD(J,2)
D =
{
  [1,1] =

     1   3   4

  [2,1] =

     5   6

}

Предположим, у вас есть функция adj(value), который имеет код из вашего предыдущего вопроса.

sidenote: вам, вероятно, понравится adj() Функция не возвращает значение пикселя, который вы анализируете. Вы можете сделать это легко.

Вы могли бы сделать:

img=[your stuff];
imgaux=img;
ii=1;
val=2; %whatever value you want
while numel(unique(imgaux))>1 % Stop if the whole image is a single superpixel
   adjacent{ii}=adj(val);
   % expand the superpixel to the ii order of adjacency
   for jj=1:size(adjacent{ii},1)
       imgaux(imgaux==adjacent{ii}(jj))==val; 

   end
   ii=ii+1;
end

Сейчас size(adjacent,2) будет количество уровней смежности для этого суперпикселя.

Я предполагаю, что этот код является оптимизируемым, я приветствую любую попытку для этого!

Следуя предложению Дэна в комментариях, вот возможная реализация:

% Параметры pixVal = 2;

adj = {};
prevMask = A == pixVal;
for ii = 1:length(A)
    currMask = imdilate(prevMask, ones(2 * ii + 1));
    adj{ii} = setdiff(unique(A(currMask & ~prevMask))', [adj{:}]);
    if isempty(adj{ii})
        break
    end
    prevMask = currMask;
end

куда pixVal это пиксель, который вы хотите посмотреть.

Результат:

>> adj{:}

ans =

     1     3     4


ans =

     5     6


ans =

   Empty matrix: 1-by-0
Другие вопросы по тегам