Московский государственный университет имени М.В.Ломоносова
Опубликован: 23.04.2007 | Доступ: свободный | Студентов: 3308 / 461 | Оценка: 4.18 / 3.71 | Длительность: 17:54:00
ISBN: 978-5-9556-0098-7
Специальности: Программист
Лекция 6:

Заполнение многоугольников и областей

< Лекция 5 || Лекция 6: 1234 || Лекция 7 >

6.3. Заполнение с затравкой

Область, подлежащая заполнению, не всегда задается в виде многоугольника. В этом разделе мы рассмотрим случай, когда заполняемая область задается цветом своей границы. Множество пикселей на растре не задает область однозначно, поэтому требуется задать координаты "затравочного" пикселя, принадлежащего области.

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

Простейший алгоритм заполнения с затравкой - это так называемый алгоритм короеда, получивший подобное название, поскольку заполняемая область последовательно "выедается" по одному пикселю. Он устроен следующим образом:

//Заполняет цветом A область, ограниченную цветом B
Добавить затравочный пиксель в стек;
while(стек не пуст)
{
      P = стек.Извлечь(); //извлечение пикселя из стека
      Закрасить пиксель P;
      foreach(Q in соседние с P пиксели)
            if(цвет Q != B и Q еще не закрашен)
                  стек.Добавить(Q)
}
Листинг 6.5. Алгоритм короеда

При обходе соседних пикселей может рассматриваться и 4-связность ( Q принимает 4 значения), и 8-связность ( Q принимает 8 значений). В зависимости от этого результат будет различным.

Внутри приведенного алгоритма производится проверка "Q еще не закрашен". Если известно, что пикселей цвета А внутри нашей области изначально не было, то это условие эквивалентно условию "цвет Q != A". В противном случае для проверки этого условия требуется введение специального буфера, где каждому пикселю соответствует флаг закраски, инициализируемый нулем и становящийся единицей при закраске пикселя.

Пример работы алгоритма показан на рис. 6.7. 4-связная область закрашивается в серый цвет и ограничена темными пикселями. Пиксель P извлечен из стека. Он закрашивается серым. Соседние незакрашенные пиксели Q, R и S добавляются в стек.

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

Алгоритм короеда.

Рис. 6.7. Алгоритм короеда.
//Заполняет цветом A область, ограниченную цветом B
Добавить затравочный пиксель в стек;
while(стек не пуст)
{
      (X,Y) = стек.Извлечь(); //извлечение пикселя из стека
   
      X_min = X;
      while(цвет(X_min-1,Y) != B)
            X_min--;

      X_max = X;
      while(цвет(X_max+1,Y) != B)
            X_max++;

      Закрасить отрезок (X_min,Y)--(X_max,Y) цветом A;

      //обработка строки сверху
      флаг = 1;
      for(X = X_min; X <= X_max; X++)
      {
            if( цвет(X,Y-1) != B и (X,Y-1) еще не закрашен)
            {
                  if( флаг == 1 )
                  {
                        стек.Добавить(X,Y-1);
                        флаг = 0;
                  }
            }
            else
                  флаг = 1;
      }
      //обработка строки снизу
      флаг = 1;
      for(X = X_min; X <= X_max; X++)
      {
            if( цвет(X,Y+1) != B и (X,Y+1) еще не закрашен)
            {
                  if( флаг == 1 )
                  {
                        стек.Добавить(X,Y+1);
                        флаг = 0;
                  }
            }
            else
                  флаг = 1;
      }
}
Листинг 6.6. Заполнение с затравкой по отрезкам

Пример работы алгоритма показан на рис. 6.8. Пиксель P - затравочный; 4-связная область закрашивается в серый цвет и ограничена темными пикселями. При первой итерации производится заполнение целого отрезка. Пиксели Q и R на строке сверху и S на строке снизу добавляются в стек.

Заметим, что приведенные в данном разделе алгоритмы несложно переделать для перекрашивания с затравкой области постоянного цвета A в другой цвет B. Иными словами, для случая, когда область задается не цветом границы, а собственным цветом. В этом случае алгоритмы даже упрощаются: соседний пиксель добавляется в стек, только если он имеет цвет A (иначе он или не принадлежит перекрашиваемой области, или уже закрашен).

Заполнение с затравкой по отрезкам.

Рис. 6.8. Заполнение с затравкой по отрезкам.
< Лекция 5 || Лекция 6: 1234 || Лекция 7 >