2014-01-26 2 views
0

Итак, я пытаюсь написать алгоритм маркировки подключенных компонентов, но это не дает мне желаемого результата. Прямо сейчас у меня есть изображение с тремя розами (которые не перекрываются), и я хочу отметить каждую розу своим собственным значением серого. Прежде чем применить алгоритм маркировки, я использую порог, чтобы избавиться от фона и сохранить только розы. Розы получают серое значение 1 (которое полностью белое), а фон получает серое значение 0 (что является черным). Вот изображение того, как это выглядит: imageПроблемы с алгоритмом маркировки подключенных компонентов

После этого я применяю алгоритм маркировки. Это должно дать розам три разных значения серого в соответствии с меткой, которую они дали. Но вместо этого алгоритм создает этот странный вид градиентного рисунка над первыми двумя розами, тогда как последний кажется единственным серым значением. Вот изображение: image

Алгоритм может выглядеть сложным, но на самом деле это очень просто. Я сначала обрабатываю столбцы, а затем строки и для каждого нефонического пикселя. Я проверяю, отмечен ли какой-либо из его соседей (это означает, что их значение objectArray не равно нулю). Если это так, я добавляю их в список соседей. Затем я перехожу к проверке, не является ли этот список пустым, поэтому я однозначно маркирую текущий пиксель, увеличивая значение объектов и присваивая его значение текущему значению метки пикселя, и также устанавливаю родительское значение текущего пикселя на эту уникальную метку. Если он не пуст, я определяю наименьшее значение метки в списке соседей, задаю все родительские значения соседей этому значению метки, и я установил текущее значение метки и родительские значения этого ярлыка. Я повторяю это для каждого пикселя, пока не будет помечено все изображение.

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

Я не понимаю, почему алгоритм не правильно маркирует розы. Кто-нибудь может мне помочь? Вот алгоритм:

public void label() 
{ 
    int objects = 1; 
    int[,] objectArray = new int[colors.GetLength(1), colors.GetLength(0)]; 
    DisjointSets disjointSet = new DisjointSets(); 
    int[,] parents = new int[colors.GetLength(1), colors.GetLength(0)]; 
    List<List<int>> eqSet = new List<List<int>>(); 
    for (int i = 0; i < colors.GetLength(1); i++) for (int j = 0; j < colors.GetLength(0); j++) 
    { 
     if (this[i, j].Gray == 1) 
     { 
      List<Label> neighbors = new List<Label>(); 
      if (i > 0) 
      { 
       if (this[i - 1, j].Gray == 1) 
       { 
        if (objectArray[i - 1, j] != 0) 
        { 
         neighbors.Add(new Label(i - 1, j, 0)); 
        } 
       } 
       if (j > 0) 
       { 
        if (this[i - 1, j - 1].Gray == 1) 
        { 
         if (objectArray[i - 1, j - 1] != 0) 
         { 
          neighbors.Add(new Label(i - 1, j - 1, 0)); 
         } 
        } 
       } 
       if (j < colors.GetLength(0)) 
       { 
        if (this[i - 1, j + 1].Gray == 1) 
        { 
         if (objectArray[i - 1, j] != 0) 
         { 
          neighbors.Add(new Label(i - 1, j, 0)); 
         } 
        } 
       } 
      } 
      if (j > 0) 
      { 
       if (this[i, j - 1].Gray == 1) 
       { 
        if (objectArray[i, j - 1] != 0) 
        { 
         neighbors.Add(new Label(i, j - 1, 0)); 
        } 
       } 
       if (i < colors.GetLength(1)) 
       { 
        if (this[i + 1, j - 1].Gray == 1) 
        { 
         if (objectArray[i + 1, j - 1] != 0) 
         { 
          neighbors.Add(new Label(i + 1, j - 1, 0)); 
         } 
        } 
       } 
      } 
      if (i < colors.GetLength(1)) 
      { 
       if (this[i + 1, j].Gray == 1) 
       { 
        if (objectArray[i + 1, j] != 0) 
        { 
         neighbors.Add(new Label(i + 1, j, 0)); 
        } 
       } 
       if (this[i + 1, j + 1].Gray == 1) 
       { 
        if (objectArray[i + 1, j + 1] != 0) 
        { 
         neighbors.Add(new Label(i + 1, j + 1, 0)); 
        } 
       } 
      } 
      if (j < colors.GetLength(0)) 
      { 
       if (this[i, j + 1].Gray == 1) 
       { 
        if (objectArray[i, j + 1] != 0) 
        { 
         neighbors.Add(new Label(i, j + 1, 0)); 
        } 
       } 
      } 

      if (neighbors.Count == 0) 
      { 
       objects++; 
       objectArray[i, j] = objects; 
       parents[i, j] = objects; 
      } 
      if (neighbors.Count > 0) 
      { 
       int smallestLabel = 10000; 
       foreach (Label x in neighbors) 
        if (objectArray[x.X, x.Y] < smallestLabel) 
         smallestLabel = objectArray[x.X, x.Y]; 

       foreach (Label x in neighbors) 
        parents[x.X, x.Y] = smallestLabel; 

       objectArray[i, j] = smallestLabel; 
       parents[i, j] = smallestLabel; 
      } 
     } 
    } 
    for (int i = 0; i < colors.GetLength(1); i++) for (int j = 0; j < colors.GetLength(0); j++) 
    { 
     if (this[i, j].Gray == 1) 
     { 
      if (objectArray[i, j] != 0) 
      { 
       objectArray[i, j] = parents[i, j]; 
       ColorWrap c = this[i, j]; 
       c.X = (float)objectArray[i, j]/objects; 
       c.Y = (float)objectArray[i, j]/objects; 
       c.Z = (float)objectArray[i, j]/objects; 
       this[i, j] = c; 
      } 
     } 
    } 
} 
+0

Что такое «Этикетка»? –

+0

Просто значение int для каждого пикселя, которое составляет объект, который я использую, чтобы дать этим объектам определенное значение серого. Алгоритм должен проверять изображение для подключенных пикселей и давать каждому найденному «объекту» («группе» подключенных пикселей, которые должны быть каждой из роз), значение метки (например, пиксели, составляющие верхнюю левую розу, будут получите значение метки 1, нижние левые пиксели будут получать значение метки 2, а пиксели, составляющие правую розу, получат значение метки 3). Я использую эти значения меток, чтобы дать этим пикселям новое значение серого (c.X = (float) objectArray [i, j]/objects; и т. Д.) – user1683526

+0

@ user1683526 - это бинарное изображение или шкала серого? –

ответ

1

Вы получили ошибку индекса при проверке третьего соседа:

   if (this[i - 1, j + 1].Gray == 1) 
       { 
        if (objectArray[i - 1, j] != 0) 
        { 
         neighbors.Add(new Label(i - 1, j, 0)); 
        } 
       } 

Это должно быть «J + 1» во всех трех местах.

Это не решит вашу проблему. У вашего алгоритма есть проблемы, когда он встречается с диагональными краями, которые являются черными для северо-западного и белого цвета на юго-востоке.

Вы просматриваете столбец изображения слева направо и каждый столбец по строкам сверху вниз. Вы проверяете наличие восьми потенциальных соседей, но на самом деле вы можете добавлять только пиксели в свой список соседей, который вы уже прошли, а именно три пикселя в столбце слева и пиксель над вашей текущей позицией. Остальные четыре соседние пиксели будут иметь родителя (или индекс объекта) 0.

Теперь рассмотрим преимущество, как это: «»

  #######... 
      ######.... 
      #####..... 
      ####...... 
      ###O...... 
      ###....... 
      ##x....... 
      #xx....... 

(«#» черный, белый не назначается " x '- белый, которому присвоен родительский элемент, а «O» обозначает ваше текущее положение.)

Вы найдете только черные или неназначенные смежные плитки. Список ваших соседей будет пустым, а это значит, что ваш алгоритм создает новый объект, хотя он должен логически принадлежать еще не открытому объекту к юго-востоку.

(Вы пытаетесь создать-трек, назначив все соседние пикселы значения новой группы, но фиксирует только один пиксель. Он также может создавать пустые группы, то есть объекты, которые не имеют соответствующий пикселя.)

Я думаю, что ваш подход слишком сложный, во всяком случае. Он также не учитывает укромные места выше и слева от основного компонента компонентов. Нет необходимости создавать дополнительные структуры данных, вы можете сделать маркировку в самом изображении, если используете изображение с оттенками серого. После преобразования изображения в черно-белый, пропустите все пиксели один раз. Если пиксель белый, заливайте заливку оттуда положительным значением серого, которое соответствует следующему объекту и увеличивает количество объектов. Затем снова передайте все пиксели и настройте серое значение в соответствии с идентификатором объекта и количеством объектов.

Предостережение: Когда я говорю, что вы можете делать все на самом изображении, вы ограничиваете свою маркировку 254 объектами.

Кроме того, вы можете немного очистить свой код. Вы не используете eqSet и disjointSet, поэтому, пожалуйста, удалите их из своего кода. Два массива objectArray и parents используются друг для друга для одного и того же предмета; объединить их в один. Вы также должны реорганизовать поиск восьми соседних пикселей в функцию (с одним вызовом для каждого потенциального соседа), чтобы упростить чтение и избежать ошибок индексирования, как указано выше.

+0

Большое спасибо. Я рассмотрю алгоритм наводнения, я не думал об этом. – user1683526

Смежные вопросы