Série de algoritmos 12: algoritmo de preenchimento de área poligonal - algoritmo de preenchimento de sementes recursivo

 

        O algoritmo de preenchimento de área plana é um algoritmo muito importante no campo da computação gráfica. O preenchimento de área é para fornecer o limite de uma área (ou nenhum limite, basta fornecer a cor especificada), e todas as unidades de pixel dentro do limite são necessárias Modifique-o para a cor especificada (ou preenchimento de padrão). O preenchimento de área mais comumente usado é o preenchimento de polígono. Neste artigo, discutiremos vários algoritmos de preenchimento de área de polígono.

1. Algoritmo de enchimento de sementes (enchimento de sementes)

        Se a área a ser preenchida é fornecida na forma de metadados de imagem, o algoritmo de enchimento de sementes (Seed Filling) geralmente é usado para o enchimento da área. O algoritmo de enchimento de sementes precisa fornecer a área dos dados da imagem e um ponto na área. Este algoritmo é mais adequado para operações de enchimento de imagens realizadas por interação homem-computador, e não é adequado para processamento automático de computador e julgamento de cores. De acordo com o método de definição do limite da área da imagem e o método de modificação da cor do ponto, o enchimento de sementes pode ser subdividido em várias categorias, como algoritmo de preenchimento (algoritmo de preenchimento), algoritmo de preenchimento de limite (algoritmo de preenchimento de limite) e para reduzir a recursão e empilhamento Algoritmo de enchimento de sementes de linha de varredura aprimorado e assim por diante.

        O núcleo de todos os algoritmos de enchimento de sementes é na verdade um algoritmo recursivo, que começa a partir de um ponto de semente especificado, pesquisa em todas as direções e processa pixel por pixel até encontrar um limite. Vários algoritmos de enchimento de sementes estão apenas processando cores e limites. O acima é diferente. Antes de introduzir o algoritmo de enchimento de sementes, dois conceitos também são introduzidos, a saber, "Algoritmo 4-Unicom" e "Algoritmo 8-Unicom". Por ser uma pesquisa, envolve a direção da pesquisa. A partir de qualquer ponto da área, se você pesquisar apenas qualquer pixel na área através das quatro direções para cima, para baixo, para a esquerda e para a direita, a área preenchida com este método é chamada Para quatro domínios conectados, este método de preenchimento é chamado de "algoritmo 4-conectado". Se você começar de qualquer ponto na área e alcançar qualquer pixel na área através de todas as oito direções: cima, baixo, esquerda, direita, superior esquerdo, inferior esquerdo, superior direito e inferior direito, a área preenchida por este método é chamada de domínio oito conectado. Este método de preenchimento é denominado "Algoritmo 8-Unicom". Conforme mostrado na Figura 1 (a), suponha que o ponto azul no centro seja o ponto atualmente sendo processado. Se for o "algoritmo 4-Unicom", apenas os quatro pontos marcados em azul ao redor do processamento serão pesquisados ​​e processados. Se for o "algoritmo 8-Unicom" "Além de processar os quatro pontos marcados em azul para cima, para baixo, esquerda e direita, ele também pesquisa e processa quatro pontos marcados em vermelho. Os efeitos de preenchimento dos dois algoritmos de pesquisa são mostrados na Figura 1 (b) e Figura 1 (c), respectivamente. Se o preenchimento começar a partir dos pontos amarelos, o "algoritmo 4-Unicom" pesquisa apenas como mostrado na Figura 1 (b) Preencha a área no canto esquerdo inferior, e o "algoritmo 8-Unicom" é mostrado na Figura 1 (c), preenchendo as áreas do canto esquerdo inferior e canto superior direito.

Figura (1) Efeito de preenchimento de "4-Unicom" e "8-Unicom"

 

        Não é apenas por causa do efeito de preenchimento na Figura 1 que o "algoritmo 8-Unicom" deve ser melhor do que o "algoritmo 4-Unicom". O método de pesquisa Unicom deve ser selecionado de acordo com o ambiente do aplicativo e as necessidades reais. Em muitos casos, apenas "4-Unicom" Algoritmo "pode ​​obter o resultado correto.

1.1 Algoritmo de Preenchimento (Flood Fill Algorithm)

        O algoritmo de preenchimento por injeção não enfatiza particularmente o limite da área, ele apenas começa na posição especificada e substitui os pontos de uma determinada cor em todas as áreas conectadas por outra cor para obter o efeito de preenchimento. O algoritmo de enchimento de injeção pode realizar funções como substituição de cor, que tem sido amplamente utilizada em software de processamento de imagem. A implementação do algoritmo de enchimento por injeção é muito simples. O núcleo é a recursão e a pesquisa. O seguinte é uma implementação do algoritmo de enchimento por injeção:

164  vazio FloodSeedFill ( int x , int y , int old_color , int new_color )

165  {

166      if ( GetPixelColor ( x , y ) == old_color )

167      {

168          SetPixelColor ( x , y , nova_cor );

169          para ( int i = 0 ; i < COUNT_OF ( direction_8 ); i ++)

170          {

171              FloodSeedFill ( x + direction_8 [ i ]. X_offset ,

172                            y + direction_8 [ i ]. y_offset , old_color , new_color );

173          }

174      }

175  }

 O loop for realiza a pesquisa recursiva nas 8 direções Unicom. O segredo está na definição de direction_8:

15  typedef struct tagDIRECTION

16  {

17      int x_offset ;

18      int y_offset ;

19  } DIREÇÃO ;

79 DIRECTION direction_8[] = { {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1} };

这个是搜索类算法中常用的技巧,无需做太多说明,其实只要将其替换成如下direction_4的定义,就可以将算法改成4个联通方向填充算法:

80 DIRECTION direction_4[] = { {-1, 0}, {0, 1}, {1, 0}, {0, -1} };

图2就是应用本算法实现的“4-联通”和“8-联通”填充效果:

图(2) 注入填充算法实现

1.2 边界填充算法(Boundary Fill Algorithm)

        边界填充算法与注入填充算法的本质其实是一样的,都是递归和搜索,区别只在于对边界的确认,也就是递归的结束条件不一样。注入填充算法没有边界的概念,只是对联通区域内指定的颜色进行替换,而边界填充算法恰恰强调边界的存在,只要是边界内的点无论是什么颜色,都替换成指定的颜色。边界填充算法在应用上也非常的广泛,画图软件中的“油漆桶”功能就是边界填充算法的例子。以下就是边界填充算法的一个实现:

177 void BoundarySeedFill(int x, int y, int new_color, int boundary_color)

178 {

179     int curColor = GetPixelColor(x, y);

180     if( (curColor != boundary_color)

181         && (curColor != new_color) )

182     {

183         SetPixelColor(x, y, new_color);

184         for(int i = 0; i < COUNT_OF(direction_8); i++)

185         {

186             BoundarySeedFill(x + direction_8[i].x_offset,

187                              y + direction_8[i].y_offset, new_color, boundary_color);

188         }

189     }

190 }

关于direction_8的说明请参考上一节,图3就是应用本算法实现的“4-联通”和“8-联通”填充效果(其中颜色值是1的点就是指定的边界):

图(3) 边界填充算法实现

 

<下一篇:扫描线种子填充算法>

Acho que você gosta

Origin blog.csdn.net/orbit/article/details/7323090
Recomendado
Clasificación