You are on page 1of 82

5.

4 多边形的扫描转换与区域填充
面对一个区域

1
5.4 多边形的扫描转换与区域填充
 区域内颜色值的重要性

2
5.4 多边形的扫描转换与区域填充
 如何在一个区域的内部填上不同的色彩?
 区域的几种表示方法:

顶点表示 边界表示 内点表示

3
5.4 多边形的扫描转换与区域填充
 如何在一个区域的内部填上不同的色彩?

多边形 区域

 多边形区域主要是指顶点表示的区域。
 区域通常指以像素点集合表示的区域(边界表示
和内点表示)。

4
5.4 多边形的扫描转换与区域填充
 多边形扫描转换与区域填充可以统称区域填充,
就是如何用颜色或图案来填充一个二维区域。
 填充主要做两件工作:一是确定需要填充的范
围,二是确定填充的内容。
 方法:
 扫描线法: x- 扫描线法 - 〉 Y 连贯性算法
 边缘填充算法
 种子填充算法(区域填充)

5
5.4.1 多边形的扫描转换
 对于一个多边形区域
输入:多边形顶点序列 P1(x1,y1) 到 P7(x7,y7)
并不仅需要边界而
输出:最佳逼近这个多边形的像素点集 是需要整个多边形
区域

多边形的扫描转换

顶点表示 点阵表示
6
5.4.1 多边形的扫描转换
 顶点表示:用多边形顶点的序列来刻划多边形。直
观、几何意义强、占内存少;不能直接用于面着色。
 点阵表示:用位于多边形内的像素的集合来刻划多
边形。失去了许多重要的几何信息;便于运用帧缓
冲存储器表示图形,易于面着色。

7
5.4.1 多边形的扫描转换
 多边形的扫描转换:把多边形的顶点表示转换为点
阵表示,也就是从多边形的给定边界出发,求出位
于其内部的各个像素,并给帧缓冲器内的各个对应
元素设置相应的灰度和颜色,通常称这种转换为多
边形的扫描转换或多边形的填充。
 两种常用方法:
 x- 扫描线算法
 y 连贯性算法(改进的有效边表算法)

8
X- 扫描线算法
 基本思想:按扫描线 y
12

顺序,计算扫描线与
11
10
9
多边形的相交区间, 8
7
6
再用要求的颜色显示 5
4
3
这些区间的所有像素。 2
1
1 2 3 4 5 6 7 8 9 10 11 12 x

9
X- 扫描线算法
算法步骤:
(1) 确定多边形所占有的最大扫描线数,得到多边形顶点的最小
和最大 y 值( ymin 和 ymax )。

(2) 从 y=ymin 到 y=ymax ,每次用一条扫描线进行填充。

(3) 对一条扫描线填充的过程可分为四个步骤:
①求交。
②排序。
③交点配对。
④区间填充。
10
X- 扫描线算法
算法步骤:
(1) 确定多边形所占有 ymax
的最大扫描线数,
得到多边形顶点的
最小和最大 y 值
( ymin 和 ymax )。

(2) 从 y=ymin 到 y=ymax , ymin


每次用一条扫描线
进行填充。

11
X- 扫描线算法
算法步骤:
(1) 确定多边形所占有
的最大扫描线数,
得到多边形顶点的
最小和最大 y 值
( ymin 和 ymax )。

(2) 从 y=ymin 到 y=ymax ,


每次用一条扫描线
进行填充。

12
X- 扫描线算法
算法步骤:
(3) 对一条扫描线填
充的过程可分为
四个步骤:
①求交。
1
②排序。
③交点配对。
④ 区间填充。
13
X- 扫描线算法
算法步骤:
(3) 对一条扫描线填
充的过程可分为
四个步骤:
①求交。
1
②排序。
③交点配对。
④ 区间填充。
14
X -扫描线算法——取整规则
 交点的取整规则:使生成的像素全部位于多边
形之内。(用于直线等图元扫描转换的四舍五
入原则可能导致部分像素位于多边形之外,从
而不可用)。

膨胀

15
X -扫描线算法——取整规则
 交点的取整规则:使生成的像素全部位于多边
形之内。(用于直线等图元扫描转换的四舍五
入原则可能导致部分像素位于多边形之外,从
而不可用)。

 假定非水平边与扫描线 y=e 相交,交点的横坐


标为 x ,规则如下:

16
X -扫描线算法——取整规则
 规则 1 : X 为小数,即交点落于扫描线上两个相
邻像素之间时:
交点位于左边界之上,向右取整;
交点位于右边界之上,向左取整;

17
X -扫描线算法——取整规则
 规则 2 : X 为整数,避免填充扩大化。规定落
在右边边界上的像素不予填充。(具体实现时,只要
对扫描线与多边形的相交区间左闭右开)

图 5.18 取整规则 2
18
X -扫描线算法——个数计算规则
 规则 3 :当扫描线
与多边形顶点相交
时,交点的取舍,
保证交点正确配对。

19
X -扫描线算法——个数计算规则
解决方法:
当扫描线与多边形的顶点相交时,
 若共享顶点的两条边分别落在扫描线的两边,
交点只算一个;
 若共享顶点的两条边在扫描线的同一边,这时
交点作为零个或两个。

20
X -扫描线算法——个数计算规则
实际处理: 0
0
2
1
交点个数 =
0
构成这个顶点的两条边位
于扫描线上方的条数
2 2

21
改进出发点

x- 扫描线法需要进行多次求交、排序运算,效率较低。

改进出发点:
1 )对于某一条扫描线,需要与所有边求交吗?
2 )扫描线和直线在 Y 方向上都有连贯性,那
么交点怎么求?
3 )每次都需要排序吗?

22
改进出发点

1 )对于某一条扫描线,需要与所有边求交吗?
答:只与有效边求交!

有效边 有效边

23
改进出发点

1 )对于某一条扫描线,需要与所有边求交吗?
答:只与有效边求交! Y 连贯性算法
2 )扫描线和直线在 Y 方向上都有连贯性,那
么交点怎么求?
答:增量计算!
3 )每次都需要排序吗?
答:有新边加入时重新排序!
24
改进出发点

1 )对于某一条扫描线,需要与所有边求交吗?
答:只与有效边求交! Y 连贯性算法
2 )扫描线和直线在 Y 方向上都有连贯性,那
么交点怎么求?
答:增量计算!
3 )每次都需要排序吗?
答:有新边加入时重新排序!
25
改进的有效边表算法( Y 连贯性算
 法)
有效边( Active Edge ):指与当前扫描线
相交的多边形的边,也称为活性边。

 有效边表( Active Edge Table, AET ):


把有效边按与扫描线交点 x 坐标递增的顺序
存放在一个链表中,此链表称为有效(活
性)边表。

26
如何计算下一条扫描线与边的交点
直线方程: y=kx+b
当前交点坐标: (xi, yi)
下一交点坐标: (xi+1,yi+1)
当 yi+1 = yi +1
xi+1 = xi+1/k x ymax 1/k next
有效边表中需要存放的信息:
x :当前扫描线与边的交点的 x 坐标
1/k(Δx) :从当前扫描线到下一条扫描线之间的 x 增量 1/k
ymax :有效边所交的最高扫描线
27
数据结构与实现步骤
 为了方便有效边表的建立和更新,建立另一个
表 - 新边表 NET ( New Edge Table ) ,存放
在该扫描线第一次出现的边。
 表结构 NET 和 AET 中的基本元素为多边形的
边。边的结构由以下四个域组成:

28
数据结构与实现步骤 x ymax 1/k next

x :在 NET 中表示边的最低点的 x 坐标,在 AET


中则表示边与扫描线的交点的 x 坐标;
ymax :边的上端点的 y 坐标;
1/k(Δx) :边的斜率的倒数;(当前扫描线到下一条
扫描线 x 的增量)
next :指向下一条边的指针。

29
数据结构与实现步骤

AET 有效边表

x ymax 1/k(△x) next

X: 边与扫描线的交点的 x 坐标

NET 新边表

x ymax 1/k (△x) next

X: 边的下端点的 x 坐标
30
实例

31
实例

32
实例

33
x ymax 1/k next
实例

34
x ymax 1/k next
实例

35
实例
如何体现:当扫描线与多边形顶点相交时,交
点的取舍策略?

交点个数 =
构成这个顶点的两条边
位于扫描线上方的条数

36
x ymax 1/k next
实例

37
x ymax 1/k next
实例

有效边表( Active Edge Table,AET ):开


始为空

38
x ymax 1/k next
实例

有效边表( Active Edge Table,AET ):与边表中 y=2 处边表合


39
x ymax 1/k next
实例

有效边表( Active Edge Table,AET ):增量计算

40
x ymax 1/k next
实例

有效边表( Active Edge Table,AET ):增量计算

41
x ymax 1/k next
实例

有效边表( Active Edge Table,AET ):删除之后的无效边、增量计



42
x ymax 1/k next
实例

有效边表( Active Edge Table,AET ):增量计算

43
x ymax 1/k next
实例

有效边表( Active Edge Table,AET ):删除无效边、增量计算、插


入新边

44
算法分析
 优点:
 采用增量计算的方法进行交点计算。
 仅仅在新边加入时排序。
 缺点:
 桶表、链表的维护开销大。

45
习题
如图所示多边形,若采用改进的有效边表算法 (Y 连贯
性算法 ) 进行填充,试写出该多边形的新边表( NET
表)和有效边表 (AET 表 ) 。

46
5.4.2 边缘填充法
 输入:多边形顶点序列 P1(x1,y1) 到
P7(x7,y7)
 输出:最佳逼近这个多边形的像素点集
逐边向右取补

47
5.4.2 边缘填充法

边缘填充

48
5.4.2 边缘填充法
 算法过程:对于每一条扫描线和每条多边形
边的交点( x1,y1 ) , 将该扫描线上交点右
方的所有像素取补,对多边形的每条边做同
样处理,多边形顺序随意 .

 算法简单,但对于复杂图型,每一像素可能
被访问多次。

49
改进 1- 栅栏填充算法
为了减少重复计算,可采用栅栏填充算法,栅栏指的是一条
过多边形顶点且与扫描线垂直的直线。它把多边形分为两半。

对于每个扫描线与多边形的交
点,将交点与栅栏之间的像素
取补,若交点位于栅栏左边,
则将交点之右,栅栏之左的所
有像素取补,若交点位于栅栏
右边,则将栅栏之右,交点之
左的像素取补。
50
改进 1- 栅栏填充算法

51
改进 2- 边标志算法
改进:先画边界后填色
边标志算法
基本思想:
( 1 )用一种特殊的颜色在帧缓冲存储器中将多边形的
边界勾画出来;
( 2 )将着色的像素点依 x 坐标递增的顺序两两配对;
( 3 )将每一对像素所构成的扫描线区间内的所有像素
置为填充色。

52
改进 2- 边标志算法
分为两个步骤:
(1) 打标记 下闭上开

(2) 填充
Inside
初值:假
遇到标记点:取反
真:填充;
假:不填充
53
改进 2- 边标志算法
分为两个步骤:
(1) 打标记
(2) 填充
左闭右开
Inside
初值:假
遇到标记点:取反
真:填充;
假:不填充
54
改进 2- 边标志算法
分为两个步骤:
(1) 打标记
(2) 填充
Inside
初值:假
遇到标记点:取反
真:填充;
假:不填充
55
边标志算法分析
 边标志算法对每个象素仅访问一次:

与边缘填充算法和栅栏填充算法相比,避免了对帧
缓存中大量元素的多次赋值,但仍然需逐条扫
描线地对帧缓存中的元素进行搜索和比较。

56
5.4.3 区域填充算法
 区域指已经表示成点阵形式的填充图形,它
是像素的集合。
 区域填充指先将区域的一点(种子点)赋予
指定的颜色,然后将该颜色扩展到整个区域
的过程。区域填充算法要求区域是连通的。

57
区域填充
 表示方法:边界表示、内点表示
 边界表示 (边界填充算法)
 枚举出边界上所有的像素
 边界上的所有像素着同一颜色
 非边界像素着与边界像素不同的
颜色
 内点表示 (泛填充算法)
 枚举出区域内部的所有像素
 内部的所有像素着同一个颜色
 区域外像素着与内部像素不同的颜色
58
区域填充
 区域填充要求区域是连通的
 连通性: 4 连通、 8 连通
定义: 4- 邻接点 8- 邻接点

P 的 4- 邻接点 P 的 8- 邻接点
59
区域填充
 区域填充要求区域是连通的
 连通性: 4 连通、 8 连通

 4 连通:

 8 连通

60
区域填充
 4 连通区域与 8 连通
区域的区别
 邻接点不同。 4 连
通区域访问 4- 邻接点,
8 连通区域访问 8- 邻
接点, 8- 邻接点中包
含了 4- 邻接点。
 边界要求不同。 8
连通区域对边界的要
求更高。
61
(a) 以边界表示的 4- 连通区域 (b) 以内点表示的 4- 连通区域

(c) 以边界表示的 8- 连通区域 (d) 以内点表示的 8- 连通区域

区域的边界表示和内点表示 62
种子填充算法
区域填充的算法:种子填充算法
4 连通算法
连通性
8 连通算法

边界填充算法(边界
表示的区域)
表示方式
泛填充算法(内点表示的
区域)
63
种子填充算法 -4- 连通边界填充
算法的输入:种子点坐标 (x,y) ,填充色和边界颜色。
栈结构实现 4- 连通边界填充算法的算法步骤为:
1 、种子像素入栈。
2 、当栈非空时重复执行如下三步操作:
(1) 栈顶像素出栈;
(2) 将出栈像素置成填充色;
(3) 按一定顺序检查出栈像素的 4- 邻接点,若其中某
个像素点不是边界色且未置成多边形色,则把该像
素入栈。
64
举例 -4- 连通边界填充
 以 s1 为种子, 4

按照左、上、
右、下顺序入
3 7 8

栈出栈,过程 2 9 6 S1 4

如下:
1 5 2 3

0 1 2 3 4 5

65
S1 2 3 4 5 6
S1

3 4

2 5 5 5 6
4
4 4 4 4 4

8 8 8 3 7 8
8 8

S1 6 6 6 6 6 2 9 6 S1 4

1 5 2 3
1 2 3 4 5
S1
0

0 1 2 3 4 5

9 4 8 6
7 8

7 8

9 9 9

4 4 4 4

8 8 8 8 8 4,8,6 像素
6 6 6 6 6 6 多次入栈

9 10 11
6 7 8 66
种子填充算法 - 4- 连通边界填充
void BoundaryFill4(int x,int y,int boundaryColor,int newColor)
{ int color;
color = GetPixel(x,y);
if((color != boundaryColor) && (color != newColor))
{ PutPixel(x,y,newColor);
BoundaryFill4(x,y+1,oldColor,newColor);
BoundaryFill4(x,y-1,oldColor,newColor);
BoundaryFill4(x-1,y,oldColor,newColor);
BoundaryFill4(x+1,y,oldColor,newColor);
}
}/*end of BoundaryFill4() */

67
种子填充算法 -8- 连通边界填充
栈结构实现 8- 连通边界填充算法的算法步骤为:

种子像素入栈;当栈非空时重复执行如下三步操作:

(1) 栈顶像素出栈;

(2) 将出栈像素置成填充色;

(3) 按一定顺序检查出栈像素的 8- 邻接点,若其中某个像


素点不是边界色且未置成多边形色,则把该像素入栈。

68
种子填充算法 -4- 连通泛填充算法
适合于内点表示区域的填充算法 .
设 G 为一内点表示的区域, (x,y) 为区域内一
点, old_color 为 G 的原色。现取 (x,y) 为种子点对区
域 G 进行填充:即先置像素 (x,y) 的颜色为 new_color ,
然后逐步将整个区域 G 都置为同样的颜色。 步骤如下:
种子像素入栈,当栈非空时,执行如下三步操作:
( 1 )栈顶像素出栈;
( 2 )将出栈像素置成填充色;
( 3 )按左、上、右、下的顺序检查与出栈像素相邻的
四个像素,若其中某个像素是给定内部点的颜色且未置
成新的填充色,则把该像素入栈。

69
种子填充算法 - 4- 连通泛填充算法
 递归算法可实现如下:
void FloodFill4(int x,int y,int oldColor,int newColor)
{ if(GetPixel(x,y) == oldColor)
{ PutPixel(x,y,newColor);
FloodFill4(x,y+1,oldColor,newColor);
FloodFill4(x,y-1,oldColor,newColor);
FloodFill4(x-1,y,oldColor,newColor);
FloodFill4(x+1,y,oldColor,newColor);
}
}/*end of FloodFill4() */

70
举例 - 4- 连通泛填充算法
 以 s1 为种子, 4

按照左、上、
右、下顺序入
3 7 8

栈出栈,过程 2 9 6 S1 4

如下:
1 5 2 3

0 1 2 3 4 5

71
S1 2 3 4 5 6
S1

3 4

2 5 5 5 6

4 4 4 4 4
7 8
8 8 8 8 8

S1 6 6 6 6 6
9 6 S1 4

1 2 3 4 5
S1
5 2 3

9 4 8 6
7 8

7 8

9 9 9

4 4 4 4

8 8 8 8 8 4,8,6 像素
6 6 6 6 6 6 多次入栈

9 10 11
6 7 8 72
种子填充算法
该算法也可以填充有孔区域。
 缺点:
(1) 有些像素会入栈多次,降低算法效率;栈结构占空
间。
(2) 递归执行,算法简单,但效率不高,区域内每一象
素都引起一次递归,进 / 出栈,费时费内存。
 解决方法
改进算法,减少递归次数,提高效率。
解决方法是用扫描线填充算法。

73
扫描线种子填充算法(四连通)
 目标:减少递归层次
 以边界表示的 4 连通区域为例
 算法思想:在任意不间断区间中只取一个种子像素(不
间断区间指在一条扫描线上一组相邻元素),填充当前
扫描线上的该段区间;然后确定与这一区段相邻的上下
两条扫描线上位于区域内的区段,并依次把它们保存起
来,反复进行这个过程,直到所保存的个区段都填充完
毕。

74
扫描线填充算法
(1) 初始化:堆栈置空。将种子点( x , y )入栈。
(2) 出栈:若栈空则结束。否则取栈顶元素( x , y ),以
y 作为当前扫描线。
(3) 填充并确定种子点所在区段:从种子点( x , y ) 出发,
沿当前扫描线向左、右两个方向填充,直到边界。分别标
记区段的左、右端点坐标为 xl 和 xr 。
(4) 并确定新的种子点:在区间 [xl , xr] 中检查与当前扫描
线 y 上、下相邻的两条扫描线上的像素。若存在非边界、
未填充的像素,则把每一区间的最右像素作为种子点压入
堆栈,返回第( 2 )步。
优点:上述算法对于每一个待填充区段,只需压栈一次,
因此,扫描线填充算法提高了区域填充的效率。
75
扫描线算法分析(例 1 分析)
 该算法也可以
填充有孔区域。
 像素中的序号
标指它所在区
段位于堆栈中
的位置

76
扫描线算法分析(例 1 分析)

77
扫描线算法分析(例 1 分析)

78
扫描线算法分析(例 1 分析)

79
5.4.4 多边形扫描转换与区域填充方法比

 联系:都是光栅图形面着色,用于真实感图形显示,
可相互转换。
 多边形的扫描转换转化为区域填充问题:当给定多
边形内一点为种子点,并用 Bresenham 或 DDA 算
法将多边形的边界表示成八连通区域后,则多边形
的扫描转换转化为区域填充。
 区域填充转化为多边形的扫描转换;若已知给定多
边形的顶点,则区域填充转化为多边形的扫描转换。

80
多边形扫描转换与区域填充方法比较
不同点:
1. 基本思想不同;前者是顶点表示转换成点阵表示,
后者只改变区域内填充颜色,没有改变表示方法。
2. 对边界的要求不同
前者 : 只要求扫描线与多边形边界交点个数为偶数
后者:区域封闭,防止递归填充跨界。
3. 基本的条件不同
前者:从边界顶点信息出发。
后者:区域内种子点。
81
多边形扫描转换与区域填充
边界

S451
23

82

You might also like