算法系列之十二:多边形区域填充算法--递归种子填充算法

转载 2012年04月05日 14:43:41
     平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界(也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜色(也可能是图案填充)。区域填充中最常用的是多边形填色,本文中我们就讨论几种多边形区域填充算法。

一、种子填充算法(Seed Filling)

        如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法(Seed Filling)进行区域填充。种子填充算法需要给出图像数据的区域,以及区域内的一个点,这种算法比较适合人机交互方式进行的图像填充操作,不适合计算机自动处理和判断填色。根据对图像区域边界定义方式以及对点的颜色修改方式,种子填充又可细分为几类,比如注入填充算法(Flood Fill Algorithm)、边界填充算法(Boundary Fill Algorithm)以及为减少递归和压栈次数而改进的扫描线种子填充算法等等。

        所有种子填充算法的核心其实就是一个递归算法,都是从指定的种子点开始,向各个方向上搜索,逐个像素进行处理,直到遇到边界,各种种子填充算法只是在处理颜色和边界的方式上有所不同。在开始介绍种子填充算法之前,首先也介绍两个概念,就是“4-联通算法”和“8-联通算法”。既然是搜索就涉及到搜索的方向问题,从区域内任意一点出发,如果只是通过上、下、左、右四个方向搜索到达区域内的任意像素,则用这种方法填充的区域就称为四连通域,这种填充方法就称为“4-联通算法”。如果从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下全部八个方向到达区域内的任意像素,则这种方法填充的区域就称为八连通域,这种填充方法就称为“8-联通算法”。如图1(a)所示,假设中心的蓝色点是当前处理的点,如果是“4-联通算法”,则只搜索处理周围蓝色标识的四个点,如果是“8-联通算法”则除了处理上、下、左、右四个蓝色标识的点,还搜索处理四个红色标识的点。两种搜索算法的填充效果分别如如图1(b)和图1(c)所示,假如都是从黄色点开始填充,则“4-联通算法”如图1(b)所示只搜索填充左下角的区域,而“8-联通算法”则如图1(c)所示,将左下角和右上角的区域都填充了。

图(1) “4-联通”和“8-联通”填充效果

 

        并不能仅仅因为图1的填充效果就认为“8-联通算法”一定比“4-联通算法”好,应该根据应用环境和实际的需求选择联通搜索方式,在很多情况下,只有“4-联通算法”才能得到正确的结果。

1.1 注入填充算法(Flood Fill Algorithm)

        注入填充算法不特别强调区域的边界,它只是从指定位置开始,将所有联通区域内某种指定颜色的点都替换成另一种颜色,从而实现填充效果。注入填充算法能够实现颜色替换之类的功能,这在图像处理软件中都得到了广泛的应用。注入填充算法的实现非常简单,核心就是递归和搜索,以下就是注入填充算法的一个实现:

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

165 {

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

167     {

168         SetPixelColor(x, y, new_color);

169         for(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 }

 for循环实现了向8个联通方向的递归搜索,秘密就在direction_8的定义:

15 typedefstruct tagDIRECTION

16 {

17     int x_offset;

18     int y_offset;

19 }DIRECTION;

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) 边界填充算法实现


算法系列之十二:多边形区域填充算法--递归种子填充算法 .

平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界(也可以是没有边界,只是给出指定颜色),要求将边界范围内的所有象素单元都修改成指定的颜色(也可能是图案填充)。区域填充...
  • mybloglucis009
  • mybloglucis009
  • 2013年01月08日 15:45
  • 189

Open gl 的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现

http://blog.csdn.net/jiangxinyu/article/details/7911876
  • qxbailv15
  • qxbailv15
  • 2013年10月29日 11:21
  • 2025

(8)种子填充算法

两种连通区域  四连通区域:从区域内一点出发,可通过上、下、左、右四个方向的移动组合,在不越出区域的前提下,能到达区域内的任意像素  八连通区域:从区域内每一像素出发,可通过八个方向,...
  • zl908760230
  • zl908760230
  • 2016年12月31日 14:02
  • 2194

多边形区域填充算法--递归种子填充算法

注意:读者若是对下面的种子填充算法还不是很了解的话,可以观看维基百科中的动画,可以有更加直观的认识! 平面区域填充算法是计算机图形学领域的一个很重要的算法,区域填充即给出一个区域的边界(也可以是没有...
  • jiangchenmiao
  • jiangchenmiao
  • 2016年02月17日 17:54
  • 2352

计算机图形学 - 扫描线种子填充算法

算法描述:   种子填充算法原理和程序都很简单, 但由于多次递归, 费时、费内存, 效率不高。为了减少递归次数, 提高效率可以采用扫描线种子填充算法。算法的基本过程如下: 当给定种子点( x, y) ...
  • xdg_blog
  • xdg_blog
  • 2016年10月18日 14:48
  • 1311

Java NIO系列教程(12)Java NIO与IO

当学习了Java NIO和IO的API后,一个问题马上涌入脑海: 我应该何时使用IO,何时使用NIO呢?在本文中,我会尽量清晰地解析Java NIO和IO的差异、它们的使用场景,以及它们如何影响您的...
  • zhangyuan19880606
  • zhangyuan19880606
  • 2016年04月27日 19:40
  • 150

Java NIO系列教程(十二) Java NIO与IO

原文地址:http://tutorials.jenkov.com/java-nio/nio-vs-io.html 作者:Jakob Jenkov   译者:郭蕾    校对:方腾飞 当学习了J...
  • fw0124
  • fw0124
  • 2015年03月17日 15:22
  • 1790

种子点生长算法上——二维种子点生长

下文提到的种子点生长算法,包括泛洪法,扫描线法,区段法三种。文本先从最简单的泛洪法入手介绍种子点生长算法的相关概念。之后进一步讨论了扫描线法和区段法,同时提供了实验数据验证其中的一些结论。本文按照如下...
  • wozhengtao
  • wozhengtao
  • 2016年05月17日 01:22
  • 3772

种子填充算法的使用—计算机图形学

(四连通区域填充示意图) 假设内部表示区域为G,其中的像素原有颜色为G0,需要填充的颜色为G1。 算法需要提供一个种子点(x, y),它的颜色为G0。以四连通区域为例:具体算法如下(四连通区...
  • yangyong0717
  • yangyong0717
  • 2017年05月04日 09:38
  • 1239

OpenGL-学习之路-不规则区域的填充算法

一. 简单递归的不规则区域填充
  • PatrickLin93
  • PatrickLin93
  • 2014年10月27日 22:48
  • 2877
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:算法系列之十二:多边形区域填充算法--递归种子填充算法
举报原因:
原因补充:

(最多只允许输入30个字)