案例8 四邻接点种子填充算法

合集下载

种子填充算法

种子填充算法

一、实验目标1.了解基于种子填充算法的基本思想;2.掌握基于种子填充算法的算法实现;3.掌握栈的使用。

二、实验内容本次实验主要是实现递归种子填充算法、简单种子填充算法、扫描线种子填充算法以及区域图案填充算法。

种子填充算法原理简述:在开始介绍种子填充算法之前,首先也介绍两个概念,就是“4-连通算法”和“8-连通算法”。

既然是搜索就涉及到搜索的方向问题,从区域内任意一点出发,如果只是通过上、下、左、右四个方向搜索到达区域内的任意像素,则用这种方法填充的区域就称为四连通域,这种填充方法就称为“4-连通算法”。

如果从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下全部八个方向到达区域内的任意像素,则这种方法填充的区域就称为八连通域,这种填充方法就称为“8-连通算法”。

种子填充算法采用的边界定义是区域边界上所有像素均具有某个特定的颜色值,区域内部所有像素均不取这一特定颜色,而边界外的像素则可以具有和边界相同的颜色值。

程序从(x,y)开始,先检测该点的颜色,如果它与边界色和填充色均不相同,就用填充色填充该点,然后检测相邻位置,以确定它们是否边界色和填充色,若不是,就填充该相邻点。

这个过程延续到已经检测完边界范围内的所有像素为止。

扫描线种子填充算法原理简述:当给定种子点(x, y)时,首先分别向左和向右两个方向填充种子点所在扫描线上的位于给定区域的一个区段,同时记下这个区段的范围[xLeft, xRight],然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。

反复这个过程,直到填充结束。

扫描线种子填充算法可由下列四个步骤实现:(1)初始化一个空的栈用于存放种子点,将种子点(x, y)入栈;(2)判断栈是否为空,如果栈为空则结束算法,否则取出栈顶元素作为当前扫描线的种子点(x, y),y是当前的扫描线;(3)从种子点(x, y)出发,沿当前扫描线向左、右两个方向填充,直到边界。

八邻接点种子填充算法编程

八邻接点种子填充算法编程
return
image[x][y] = value
for i in range(8):
fill(x + dx[i], y + dy[i])
#调用递归函数来填充种子周围的像素
fill(seed[0], seed[1])
这个算法使用了一个递归函数来填充种子周围的像素。在函数中,我们首先检查当前像素是否在图像的边界内,并且是否与种子像素相连。如果是,我们将其值设置为目标值,并递归地填充与当前像素相连的像素。通过调用fill(seed[0], seed[1]),我们可以从种子像素开始填充整个连通区域。
dy = [-1, 0, 1, -1, 0, 1, -1, 0]
#定义四个边界条件
left = 0
right = width - 1
top = 0
bottom = height - 1
#定义递归函数来填充种子周围的像素
def fill(x, y):
if x < left or x > right or y < top or y > bottom or image[x][y] != seed:
八邻接点种子填充算法是一种用于图像处理的算法,用于填充二值图像中的连通区域。以下是一个简单的Python实现:
def seedfill(image, height = image.shape
#定义八个方向的偏移量
dx = [-1, -1, -1, 0, 0, 0, 1, 1]

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

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

2.1 深度递归的种子填充算法
2.2 扫描线种子填充算法
2.1 深度递归的种子填充算法
种子填色又称边界填色(Boundary Filling)。 它的功能是,给出多边形光栅化后的边界位置及边 界色代码oundary_color,以及多边形内的一点(x, y)位置,要求将颜色fill_color填满多边形。
动画演示
扫描线种子填充算法特点
1. 该算法考虑了扫描线上象素的相关性,种子象 素不再代表一个孤立的象素,而是代表一个尚 未填充的区段。 2. 进栈时,只将每个区段选一个象素进栈(每个 区段最右边或最左边的象素),这样解决了堆 栈溢出的问题。 3. 种子出栈时,则填充整个区段。 4. 这样有机的结合:一边对尚未填充象素的登记 (象素进栈),一边进行填充(象素出栈), 既可以节省堆栈空间,又可以实施快速填充。

3. 已知有一个5边形如下。建立新边表 NET,并写出每一条扫描线经过时活性边 表AET中的数据状态。
X ΔX Ymax
第1项存当前扫描线与边的交点坐标x值; 第2项存从当前扫描线到下一条扫描线间x的增量Dx; 第3项存该边所交的最高扫描线号ymax; 第4项存指向下一条边的指针。
假定当前扫描线与多边形某一条边的交点的x 坐标为x,则下一条扫描线与该边的交点不要重计 算,只要加一个增量△x。(连贯性) 设该边的直线方程为:ax+by+c=0; 若y=yi,x=x i;则当y = y i+1时, x i+1=xi-b/a 其中ΔX= -b/a为常数, 另外使用增量法计算时,我们需要知道一条边 何时不再与下一条扫描线相交,以便及时把它从 活性边表中删除出去。
建立或调整AET(ActiveEdgeList);

射线填充——种子填充算法的改进

射线填充——种子填充算法的改进

a )栈 顶像 素 出栈 ; b )将 出栈像 素设 置成 填充 色 ; c )检 查 出栈像 素 的 8 一邻 接点 ,若 其 中某 个像 ( 3 ) 检 查 栈 是 否 为 空 ,若 栈 非 空 重 复 步 骤 ( 2 ) , 该填 充 算 法 过程 是 很 简 单 的 ,可 以在 用 户 先
关 键词 : 区域 填 充 ;种 子点 ;八连 通 ;射 线 ;不规 则 区域
中图分 类号:T P 3 9 1 . 4 1
文献 标识码 :A
文 字标 号:粤 内登 字。 一1 0 2 6 7 ( 2 0 1 3 ) 0 1 — 0 0 7 0 — 0 3
常 用 的填 充算 法可分 为 两大类 :扫描 转换 和种 区域边 界颜 色范 围 内的所有像 素 为止 。算法 步骤如
本 原理 为 : 只要 在某 个 区域 内有一 个 已知像 素 , 就
能 从此 像 素 出发找 到 区域 内所 有其 他像 素 , 并 对它 素不 是边界 色且 未置 成填充 色 ,则把该 像 素人栈 。
们进行填充 。根据区域的特性 , 种子填充法可分为
出发 。 可 以通 过 上 、下 、左 、右 四个方 向或者 上 、
l 1 . 子填 充 。前者着 重解 决 由多边形 轮廓 线所 围 的区域 下 【
的填色问题 。后者适用于任意形状轮廓线所围成的
区域 ,但 缺点是 要求 区域 必须 闭合且 一次 只能 填充

( 1 ) 种子 像素 人栈 ;
( 2 ) 执行 如下 三步 :
个单 连 通 区域 。 种 子填 充法 是 区域 填充 的一种基 本 方法 , 其 基
内 的任 意像 素 。传统 的种 子填充 法存在 着 占用空 间 色和图案 ,用途比较广泛 。然而该算法需要很大的

第3章 填充

第3章 填充

3.5.2 多边形域填充 常用的填充方法是按扫描线顺序,计算扫描线 与多边形的相交区间,再用要求的颜色显示这些区 间的像素,即完成填充工作,简称为扫描线填充算 法。区间的端点可以通过计算扫描线与多边形边界 线的交点获得,该方法适用于自动填充。
1.多边形域的填充步骤 一般多边形的填充过程,对于一条扫描线,可以分为 4个步骤: (1) 求交:计算扫描线与多边形各边的交点。 (2) 排序:把所有交点按x递增顺序进行排序。 (3) 交点配对:第1个与第2个,第3个与第4个等两两配对, 每对交点就代表扫描线与多边形的一个相交区间。 (4) 区间填色:把这些相交区间内的像素置成多边形颜色。
对例3.4重新使用改进后的简单种子填充算法步骤如下。 解: (1) 种子像素(3, 2)入栈并着色。 (2) 出栈(3, 2)。入栈(2, 2)、(3, 3)、(4, 2)、(3, 1)并着色。 (3) 出栈(3, 1)。入栈(2, 1)、(4, 1)并着色。 (4) 出栈(4, 1)。 (5) 出栈(2, 1)。 (6) 出栈(4, 2)。 (7) 出栈(3, 3)。入栈(2, 3)并着色。 (8) 出栈(2, 3)。 (9) 出栈(2, 2)。入栈(1, 2)并着色。 (10) 出栈(1, 2),栈空结束。
3.5 区域填充
3.5.1 种子填充算法
(1) 内定义区域:区域内所有像素着相同颜色,区 域外像素着另一种颜色。区域填充是将区域内所有 像素的颜色置为新颜色。这种填充又称为泛填充, 如图3-46所示。
图3-46 区域的内点表示
(2) 边界定义区域:区域边界像素着特定颜色,区 域内像素不取特定颜色。区域填充是将区域内所有 像素的颜色置为边界像素颜色或新颜色。这种填充 称为边界填充,如图3-47所示。

区域填充算法

区域填充算法

7
9 9
9
对边界和内点表示的八连通区域的填充,只要将上述算法的对四 个像素点填充改为八个像素点即可。 四连通区域种子填充算法的缺点是有时不能通过狭窄区域区域, 因而不能填满多边形。八连通算法的缺点是有时会填出多边形的 边界。由于填不满比涂出更容易补救,因此四连通算法比八连通 算法用得更多。
(3)扫描线种子填充算法
(2)内点表示的四连通区域种子填充算法
基本思想:从多边形内部任一点(像素)出发,按照“右 上左下”的顺序判断相邻像素,若是区域内的像素,则对 其填充,并重复上述过程,直至所有像素填充完毕。 可以使用栈结构来实现该算法,种子像素入栈,档栈非空, 重复执行下面操作: 1)栈顶像素出栈; 2)将出栈像素置成多边形填充的颜色;
基本思想:从多边形内部任一点(像素)出发,按照 “右上左下”的顺序判断相邻像素,若不是边界像素 且没被填充过,则对其填充,并重复上述过程,直至 所有像素填充完毕。 可以使用栈结构来实现该算法,种子像素入栈,档栈 非空,重复执行下面操作: 1)栈顶像素出栈; 2)将出栈像素置成多边形填充的颜色; 3)按“右上左下”的顺序检查与出栈像素相邻的四个 像素,若其中某个像素不在边界上且未置成多边形色, 则把该像素入栈。
扫描线算法分析(举例分析)
基本思想:在任意不间断的区间中只取一个像素(不 间断区间指一条扫描线上的一组相邻元素),填充当 前扫描线上的该段区间,然后确定与这一段相邻的上 下两条扫描线位于区域内的区段,并依次把它们保存 起来,反复进行这个过程,指导所有保存的每个区段 都填充完毕。
(3)扫描线种子填充算法
种子像素入栈,当栈非空时,重复以下步骤: (1)栈顶像素出栈 (2)沿扫描线对出栈像素的左右像素进行填充, 直到遇到边界像素为止 (3)将上述区间内最左、最右像素记为xl 和xr (4)在区间[xl ,xr]中检查与当前扫描线相邻的上 下两条扫描线是否全为边界像素、或已填充 的像素,若为非边界、未填充的像素,则把 每一区间的最右像素取为种子像素入栈

计算机图形学四连通区域种子填充算法实验

计算机图形学四连通区域种子填充算法实验

计算机图形学四连通区域种子填充算法实验————————————————————————————————作者: ————————————————————————————————日期:ﻩ《计算机图形学实验》报告任课教师:钱文华2016年春季学期实验:四连通区域种子填充算法实验时间:2016年12月8日实验地点:信息学院2204实验目的:掌握种子填充算法的原理,并会用种子填充算法和opengl并结合使用c++语言编写程序绘制多边形。

实验原理:种子填充算法又称为边界填充算法。

其基本思想是:从多边形区域的一个内点开始,由内向外用给定的颜色画点直到边界为止。

如果边界是以一种颜色指定的,则种子填充算法可逐个像素地处理直到遇到边界颜色为止。

内点的检测条件:if(interiorColor!=bo rderColor&&interiorColor!=fillColor)。

种子填充算法常用四连通域和八连通域技术进行填充操作。

从区域内任意一点出发,通过上、下、左、右四个方向到达区域内的任意像素。

用这种方法填充的区域就称为四连通域;这种填充方法称为四向连通算法。

从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下八个方向到达区域内的任意像素。

用这种方法填充的区域就称为八连通域;这种填充方法称为八向连通算法。

一般来说,八向连通算法可以填充四向连通区域,而四向连通算法有时不能填充八向连通区域。

四向连通填充算法:a)种子像素压入栈中;b)如果栈为空,则转e);否则转c);c) 弹出一个像素,并将该像素置成填充色;并判断该像素相邻的四连通像素是否为边界色或已经置成多边形的填充色,若不是,则将该像素压入栈;d)转b);e)结束。

四连通填充算法利用到了递归的思想。

本实验只包括四连通填充算法程序代码:#include<glut.h>#include<stdlib.h>#include<math.h>#include<windows.h>voidinit(void){ glClearColor(1.0,1.0,1.0,0.0);glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,300.0,0.0,300.0);}void setPixel(intx,inty,longfillColor){ glColor3f(fillColor<<16,fillColor<<8,fillColor);glBegin(GL_POINTS);glVertex2i(x,y);glEnd();}voidboundaryFill4(int x,inty,long fillColor,long borderColor){ unsignedchar params[3];long interiorColor;glReadPixels(x,y,1,1,GL_RGB,GL_UNSIGNED_BYTE,par ams);interiorColor=RGB(params[0],params[1],params[2]);if(interiorColor!=borderColor&&interiorColor!=fillColor){ setPixel(x,y,fillColor);boundaryFill4(x+1,y,fillColor,borderColor);boundaryFill4(x-1,y,fillColor,borderColor); boundaryFill4(x,y+1,fillColor,borderColor);boundaryFill4(x,y-1,fillColor,borderColor);} }voidlineSegment(void) {long borderColor=RGB(255,0,0);longfillColor=RGB(0,0,255);glClear(GL_COLOR_BUFFER_BIT); glColor3f(255,0,0); glBegin(GL_LINE_LOOP);glVertex2i(0,40);glVertex2i(20,0);glVertex2i(60,0);glVertex2i(80,40);glVertex2i(60,80);glVertex2i(20,80);glEnd();boundaryFill4(60,60,fillColor,borderColor);glFlush();}voidmain(int argc,char**argv){glutInit(&ar gc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowPosition(150,100);glutInitWindowSize(300,300);glutCreateWindow("种子填充");init();glutDisplayFunc(lineSegment);glutMainLoop();}上实验课时机房的实验结果:后来的实验结果:glVertex2i(0,40);glVertex2i(20,0);glVertex2i(60,0);glVertex2i(80,40);glVertex2i(60,80);glVertex2i(20,80);glEnd();boundaryFill4(60,60,fillColor,borderColor);以上这段程序改成如下glVertex2i(90,40);glVertex2i(120, 100);glVertex2i(90,160);glVertex2i(60, 160);glVertex2i(60, 40);glEnd();boundaryFill4(70,60,fillColor,borderColor); 改变参数后:再把glVertex2i(90,40);glVertex2i(120, 100);glVertex2i(90,160);glVertex2i(60, 160);glVertex2i(60, 40);glEnd();boundaryFill4(70,60,fillColor,borderColor);改成glVertex2i(100, 100);glVertex2i(200, 100);glVertex2i(150,150);//glVertex2i(60, 160);//glVertex2i(60, 40);glEnd();boundaryFill4(150,120,fillColor,borderColor);后的结果如下图:实验总结:通过多组数据的测试,知道了上面算法的正确,普适性。

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

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

实验二4-10一、实验题目扫描线种子填充算法是通过扫描线来填充多边形内的水平像素段,处理每条扫描线时仅需将其最右端像素入栈,可以有效提高填充效率。

请使用MFC编程填充图4-60所示的空心体汉字(四连通),填充效果如图4-61所示。

二、实验思想扫描线种子填充算法:先将种子像素入栈,种子像素为栈底像素,如果栈不为空,执行如下4步操作。

(1)栈顶像素出栈。

(2)沿扫描线对出栈像素的左右像素进行填充,直至遇到边界像素为止。

即每出栈一个像素,就对区域内包含该像素的整个连续区间进行填充。

(3)同时记录该区间,将区间最左端像素记为x left,最右端像素记为x right。

(4)在区间〔x left,x right〕中检查与当前扫描线相邻的上下两条扫描线的有关像素是否全为边界像素或已填充像素,若存在非边界且未填充的像素,则把未填充区间的最右端像素取作种子像素入栈。

三、实验代码void CTestView::OnLButtonDown(UINT nFlags, CPoint point)//左键按下函数{// TODO: Add your message handler code here and/or call defaultSeed=point;//选择种子位置CharFill();//进行填充CView::OnLButtonDown(nFlags, point);}void CTestView::CharFill()//文字填充函数{CRect Rect;GetClientRect(&Rect);CClientDC dc(this);COLORREF BoundColor;//边界色int Width=Rect.right-Rect.left;int Hight=Rect.bottom-Rect.top ;int Flag;int x0,y0,x,y;CPoint Point;std::vector<CPoint> FillBuffle;//定义CPoint类型的数组序列对象FillBuffle.reserve(10);//定义数组序列的大小FillBuffle.push_back(CPoint(Seed)); //把种子结点压入数组序列BoundColor=RGB(0,0,0);//定义边界色为黑色while(!FillBuffle.empty())//如果数组序列非空{Point=FillBuffle.front();//弹出数组序列头元素x=Point.x;y=Point.y;FillBuffle.erase(FillBuffle.begin());//清除数组序列内的元素dc.SetPixel(Point,Fillcolor);//绘制像素//判断像素的位置是否在图形内部x0=x+1;//右方判断while(dc.GetPixel(x0,y)!=BoundColor&&dc.GetPixel(x0,y)!=Fillcolor) {x0=x0+1;if(x0>=Width)//到达屏幕最右端{MessageBox("种子超出范围","警告");RedrawWindow();return;}}y0=y+1;//下方判断while(dc.GetPixel(x,y0)!=BoundColor&&dc.GetPixel(x,y0)!=Fillcolor) {y0=y0+1;if(y0>=Hight)//到达屏幕最下端{MessageBox("种子超出范围","警告");RedrawWindow();return;}}RightPoint.x=x0;//右边界内的左邻点x0=x-1;while(dc.GetPixel(x0,y)!=Fillcolor&&dc.GetPixel(x0,y)!=BoundColor){dc.SetPixel(x0,y,Fillcolor);x0=x0-1;if(x0<=0)//到达屏幕最左端{MessageBox("种子超出范围","警告");RedrawWindow();return;}}y0=y-1;while(dc.GetPixel(x,y0)!=BoundColor&&dc.GetPixel(x,y0)!=Fillcolor){y0=y0-1;if(y0<=0)//到达屏幕最上端{MessageBox("种子超出范围","警告");RedrawWindow();return;}}LeftPoint.x=x0+1;//左边界内的右邻点x0=LeftPoint.x;y=y+1;//下一条扫描线while(x0<RightPoint.x){Flag=0;while((dc.GetPixel(x0,y)!=Fillcolor)&&(dc.GetPixel(x0,y)!=BoundColor)) {if(Flag==0)Flag=1;x0++ ;}if(Flag==1){if((x0==RightPoint.x)&&(dc.GetPixel(x0,y)!=Fillcolor)&&(dc.GetPixel(x0,y)!=BoundColor))FillBuffle.push_back(CPoint(x0,y));//进入数组序列else{FillBuffle.push_back(CPoint(x0-1,y));}Flag=0;}PointNext.x=x0;while(((dc.GetPixel(x0,y)==Fillcolor)&&(x0<RightPoint.x))||((dc.GetPixel(x0,y)==BoundColor) &&(x0<RightPoint.x))){x0 ++;}}x0=LeftPoint.x;y=y-2;while(x0<RightPoint.x){Flag=0;while((dc.GetPixel(x0,y)!=Fillcolor)&&(dc.GetPixel(x0,y)!=BoundColor)&&(x0<RightPoint.x)) {if(Flag==0)Flag=1;x0++ ;}if(Flag==1){if((x0==RightPoint.x)&&(dc.GetPixel(x0,y)!=Fillcolor)&&(dc.GetPixel(x0,y)!=BoundColor))FillBuffle.push_back(CPoint(x0,y));else{FillBuffle.push_back(CPoint(x0-1,y));}Flag=0;}PointNext.x=x0;while((dc.GetPixel(x0,y)==Fillcolor&&x0<RightPoint.x)||(dc.GetPixel(x0,y)==BoundColor&&x 0<RightPoint.x)){x0++;}}}FillBuffle.clear();return;}void CTestView::OnMENUFill(){// TODO: Add your command handler code hereRedrawWindow();MessageBox("请在空心字体内部单击鼠标左键!","提示");}四、实验结果截图。

计算机图形学——区域填充算法(基本光栅图形算法)

计算机图形学——区域填充算法(基本光栅图形算法)

计算机图形学——区域填充算法(基本光栅图形算法)⼀、区域填充概念区域:指已经表⽰成点阵形式的填充图形,是象素的集合。

区域填充:将区域内的⼀点(常称【种⼦点】)赋予给定颜⾊,然后将这种颜⾊扩展到整个区域内的过程。

区域填充算法要求区域是连通的,因为只有在连通区域中,才可能将种⼦点的颜⾊扩展到区域内的其它点。

1、区域有两种表⽰形式1)内点表⽰:枚举出区域内部的所有象素,内部所有象素着同⼀个颜⾊,边界像素着与内部象素不同的颜⾊。

2)边界表⽰:枚举出区域外部的所有象素,边界上的所有象素着同⼀个颜⾊,内部像素着与边界象素不同的颜⾊。

21)四向连通区域:从区域上⼀点出发可通过【上、下、左、右】四个⽅向移动的组合,在不越出区域的前提下,到达区域内的任意象素。

2)⼋向连通区域:从区域上⼀点出发可通过【上、下、左、右、左上、右上、左下、右下】⼋个⽅向移动的组合,在不越出区域的前提下,到达区域内的任意象素。

⼆、简单种⼦填充算法给定区域G⼀种⼦点(x, y),⾸先判断该点是否是区域内的⼀点,如果是,则将该点填充为新的颜⾊,然后将该点周围的四个点(四连通)或⼋个点(⼋连通)作为新的种⼦点进⾏同样的处理,通过这种扩散完成对整个区域的填充。

这⾥给出⼀个四连通的种⼦填充算法(区域填充递归算法),使⽤【栈结构】来实现原理算法原理如下:种⼦像素⼊栈,当【栈⾮空】时重复如下三步:这⾥给出⼋连通的种⼦填充算法的代码:void flood_fill_8(int[] pixels, int x, int y, int old_color, int new_color){if(x<w&&x>0&&y<h&&y>0){if (pixels[y*w+x]==old_color){pixels[y*w+x]== new_color);flood_fill_8(pixels, x,y+1,old_color,new_color);flood_fill_8(pixels, x,y-1,old_color,new_color);flood_fill_8(pixels, x-1,y,old_color,new_color);flood_fill_8(pixels, x+1,y,old_color,new_color);flood_fill_8(pixels, x+1,y+1,old_color,new_color);flood_fill_8(pixels, x+1,y-1,old_color,new_color);flood_fill_8(pixels, x-1,y+1,old_color,new_color);flood_fill_8(pixels, x-1,y-1,old_color,new_color);}}}简单种⼦填充算法的不⾜a)有些像素会多次⼊栈,降低算法效率,栈结构占空间b)递归执⾏,算法简单,但效率不⾼,区域内每⼀像素都要进/出栈,费时费内存c)改进算法,减少递归次数,提⾼效率三、扫描线种⼦填充算法基本思想从给定的种⼦点开始,填充当前扫描线上种⼦点所在的⼀区段,然后确定与这⼀段相邻的上下两条扫描线上位于区域内的区段(需要填充的区间),从这些区间上各取⼀个种⼦点依次把它们存起来,作为下次填充的种⼦点。

区域填充算法

区域填充算法
该算法具有运算速度快、对图形的适应性强、 填充结果重复性好等优点;它从根本上克服了多 边形填充法对区域形状有一定限制,种子填充法 要求知道区域内一点(填充胚)以及对区域内像 素点进行重复判断等弊端;而且该算法适应于任 何一种可以准确描绘出边界曲线的区域填充处理。
3、基于曲线积分的区域填充算法
• 算法的实现: ➢对一个区域进行轮廓跟踪,求出区域的边
• 改进算法的基本思想是:每找到一个新的内部
区段时,不仅将新区段的y值(yn)和左右列值xnl, xnr压入堆栈,而且同时把当前区段的y值和左右 列值xl,xr也压入堆栈,以保存和传递有关的信息。
3、基于曲线积分的区域填充算法
基于曲线积分的区域填充算法是邓国强,孙 景鳌等(2001)提出的一种以格林公式求区域面 积为基本原理进行区域填充的特殊算法。
1、递归种子填充算法
递归种子填充算法,又称边界填色算 法。
算法的原理是:让单个像元作为填充 胚,在给定的区域范围内,通过某种方法 进行蔓延,最终填充满整个多边形区域。 为了实现填充胚的蔓延,可采用四邻法或 八邻法进行填充。
2、扫描线种子填充算法
(1)扫描线种子填充算法
扫描线种子填充算法的对象是一个个扫描 线段。扫描线段是指区域内同值相邻像素 在水平方向的组合,它的两端以具有边界 值的像素为边界,即一段扫描线段的中间 只有同一种像素。
(2)计算多边形面积
4、区域填充算法在地图制图中的应用
(2)计算多边形面积
Sa
24
1 5 2
1 13 33 2
Sb
30
1 2
5
1 2
17
41
ScΒιβλιοθήκη 1031 213
1 2
17

计算机图形学实验报告8-种子点填充

计算机图形学实验报告8-种子点填充

《计算机图形学实验》报告2016年春季学期实验四:种子点填充算法 Seed Filling实验时间:2016年9月底实验地点:实验目的:掌握使用opengl 的种子点填充算法,观察改变参数对生成图形的改变(改变点的位置、颜色等)如果要填充的区域是以图像元数据方式给出的,通常使用种子填充算法进行区域填充。

种子填充算法的核心是一个递归算法,都是从指定的种子点开始,向各个方向上搜索,逐个像素进行处理,直到遇到边界。

种子填充算法常用四连通域和八连通域技术进行填充操作。

从区域内任意一点出发,通过上、下、左、右四个方向到达区域内的任意像素。

用这种方法填充的区域就称为四连通域;这种填充方法称为四向连通算法。

从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下八个方向到达区域内的任意像素。

用这种方法填充的区域就称为八连通域;这种填充方法称为八向连通算法。

算法的优点是非常简单,缺点是需要大量栈空间来存储相邻的点。

程序代码:使用的运行环境是vc++6.0#include <glut.h>#include <fstream>typedef float Color[3];//获取像素点的颜色void getpixel(GLint x, GLint y, Color color) {glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, color); //OPENGL自带}//画点函数void setpixel(GLint x, GLint y) {glBegin(GL_POINTS);glVertex2f(x, y);glEnd();}//比较颜色是否相等int compareColor(Color color1, Color color2) {if (color1[0] != color2[0] || color1[1] != color2[1] || color1[2] != color2[2]) { return 0; }else { return 1; }}void boundaryFill4(int x, int y, Color fillColor, Color boarderColor) {Color interiorColor;getpixel(x, y, interiorColor);if (compareColor(interiorColor, fillColor) == 0 && compareColor(interiorColor, boarderColor) == 0) {setpixel(x, y);boundaryFill4(x + 1, y, fillColor, boarderColor);boundaryFill4(x - 1, y, fillColor, boarderColor);boundaryFill4(x, y + 1, fillColor, boarderColor);boundaryFill4(x, y - 1, fillColor, boarderColor);}}void boundaryFill8(int x, int y, Color fillColor, Color boarderColor) {Color interiorColor, a, b, c, d;getpixel(x, y, interiorColor);getpixel(x + 1, y, a);getpixel(x, y - 1, b);getpixel(x, y + 1, c);getpixel(x - 1, y, d);int i = 0;if (compareColor(a, boarderColor) == 1) i++;if (compareColor(b, boarderColor) == 1) i++;if (compareColor(c, boarderColor) == 1) i++;if (compareColor(d, boarderColor) == 1) i++;if (i <= 1) {if (compareColor(interiorColor, fillColor) == 0 && compareColor(interiorColor, boarderColor) == 0) {setpixel(x, y);boundaryFill8(x+1,y,fillColor,boarderColor);boundaryFill8(x-1,y,fillColor,boarderColor);boundaryFill8(x,y+1,fillColor,boarderColor);boundaryFill8(x,y-1,fillColor,boarderColor);boundaryFill8(x-1,y+1,fillColor,boarderColor);boundaryFill8(x-1,y-1,fillColor,boarderColor);boundaryFill8(x+1,y+1,fillColor,boarderColor);boundaryFill8(x+1,y-1,fillColor,boarderColor);}}}void polygon() {glBegin(GL_LINE_LOOP);glLineWidth(5);//此处修改坐标,绘制多边形glVertex2f(100, 150);glVertex2f(150, 200);glVertex2f(200, 200);glVertex2f(200, 160);glEnd();}void display(void) {Color fillColor = {0.0, 1.0, 1.0};//填充颜色Color boarderColor = {0.0, 1.0, 0.0};//边界颜色glClear(GL_COLOR_BUFFER_BIT);glViewport(0, 0, 500, 500);glColor3fv(boarderColor);polygon();glColor3fv(fillColor);//boundaryFill4(150, 150, fillColor, boarderColor);//设置起点坐标及颜色boundaryFill8(120, 160, fillColor, boarderColor);glFlush();}int main(int argc, char **argv) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RED);glutInitWindowSize(500, 500);glutInitWindowPosition(100, 100);glutCreateWindow("BoundaryFill1");glClearColor(1, 1, 1, 0.0);glMatrixMode(GL_PROJECTION);//投影模型 gluOrtho2D(0.0, 500.0, 0.0, 500.0);glutDisplayFunc(display);glutMainLoop();return 0;}实验结果:(更改颜色)(更改形状)。

华师网络2014年9月课程考试《计算机图形学》练习题库及答案

华师网络2014年9月课程考试《计算机图形学》练习题库及答案

《计算机图形学》练习题库及答案一.选择题1.实验表明,镜面反射系数W(θ)与物体类型和角度有关。

当角度θ在30到60度时,金、银玻璃三种物体的W(θ)值从小到大依次为( )。

A 银、金、玻璃B 玻璃、银、金C 金、玻璃、银D 玻璃、金、银2.灰度等级为16级,分辨率为1024*1024的显示器,至少需要的帧缓存容量为()A 512KB;B 1MBC 2MB;D 3MB 3.在面片的数量非常大的情况下哪一个消隐算法速度最快? ( )A 深度缓存算法(Z-Buffer)B 扫描线消隐算法C 深度排序算法(画家算法)D 不知道4.双三次Bezier曲面的4条边界都是三次Bezier曲线,其特征网格有( )个顶点。

A 9;B 12;C 16;D 20 5.下列有关平面几何投影的叙述,错误的是( )A 透视投影又可分为一点透视、二点透视、三点透视;B 斜投影又可分为斜等测、斜二测;C 正轴测又可分为正一测、正二测、正三测;D 正视图又可分为主视图、侧视图、俯视图。

6.下面关于深度缓存消隐算法(Z-Buffer)的论断哪一条不正确? ( )A 深度缓存算法并不需要开辟一个与图像大小相等的深度缓存数组B 深度缓存算法不能用于处理对透明物体的消隐C 深度缓存算法能并行实现D 深度缓存算法中没有对多边形进行排序7.用转角法判别点在区域的内外。

将疑点M与边界上一点P连接,当P沿边界移动一周时,M点处于区域外的是( )A MP与给定的某条直线夹角变化值为0;B MP与给定的某条直线夹角变化值为2π;C MP与给定的某条直线夹角变化值为π;D MP与给定的某条直线夹角变化值为3π8. 在下列叙述语句中,不正确的论述为()A 在图形文件系统中,点、线、圆等图形元素通常都用其几何特征参数来描述;B 在图形系统中,图形处理运算的精度不取决于显示器的分辨率;C 在光栅扫描图形显示器中,所有图形都按矢量直接描绘显示,不存在任何处理;D 在彩色图形显示器中,使用RGB颜色模型。

CGA填充算法之种子填充算法

CGA填充算法之种子填充算法

CGA填充算法之种⼦填充算法CGA填充算法之种⼦填充算法 平⾯区域填充算法是计算机图形学领域的⼀个很重要的算法,区域填充即给出⼀个区域的边界(也可以是没有边界,只是给出指定颜⾊),要求将边界范围内的所有象素单元都修改成指定的颜⾊(也可能是图案填充)。

区域填充中最常⽤的是多边形填⾊,本⽂讨论种⼦填充算法(Seed Filling) 如果要填充的区域是以图像元数据⽅式给出的,通常使⽤种⼦填充算法(Seed Filling)进⾏区域填充。

种⼦填充算法需要给出图像数据的区域,以及区域内的⼀个点,这种算法⽐较适合⼈机交互⽅式进⾏的图像填充操作,不适合计算机⾃动处理和判断填⾊。

根据对图像区域边界定义⽅式以及对点的颜⾊修改⽅式,种⼦填充⼜可细分为⼏类: ⽐如:①注⼊填充算法(Flood Fill Algorithm)、 ②边界填充算法(Boundary Fill Algorithm)以及 ③为减少递归和压栈次数⽽改进的扫描线种⼦填充算法等等。

所有种⼦填充算法的核⼼其实就是⼀个递归算法,都是从指定的种⼦点开始,向各个⽅向上搜索,逐个像素进⾏处理,直到遇到边界,各种种⼦填充算法只是在处理颜⾊和边界的⽅式上有所不同。

在开始介绍种⼦填充算法之前,⾸先也介绍两个概念,就是“4-联通算法”和“8-联通算法”。

既然是搜索就涉及到搜索的⽅向问题,从区域内任意⼀点出发,如果只是通过上、下、左、右四个⽅向搜索到达区域内的任意像素,则⽤这种⽅法填充的区域就称为四连通域,这种填充⽅法就称为 “4-联通算法”。

如果从区域内任意⼀点出发,通过上、下、左、右、左上、左下、右上和右下全部⼋个⽅向到达区域内的任意像素,则这种⽅法填充的区域就称为⼋连通域,这种填充⽅法就称为“8-联通算法”。

如图1(a)所⽰,假设中⼼的蓝⾊点是当前处理的点,如果是“4-联通算法”,则只搜索处理周围蓝⾊标识的四个点,如果是“8-联通算法”则除了处理上、下、左、右四个蓝⾊标识的点,还搜索处理四个红⾊标识的点。

区域填充算法区域填充算法

区域填充算法区域填充算法

区域填充算法区域填充算法
下面将介绍两种常见的区域填充算法:扫描线填充算法和种子填充算法。

1. 扫描线填充算法(Scanline Fill Algorithm):
-扫描线填充算法基于扫描线的原理,从图像的上方向下扫描,对每条扫描线上的像素进行填充。

-算法流程如下:
-选择一个初始扫描线,例如选择图像的最上面一条扫描线;
-遍历该扫描线上的每一个像素,判断是否需要填充该像素;
-如果需要填充,则向区域内部延伸扫描线,同时判断该扫描线上的相邻像素是否需要填充;
-一直延伸扫描线,直到整个区域被填充完毕。

-扫描线填充算法的优点是简单、易于实现,但是算法的效率较低,在处理大尺寸区域时耗时较长。

2. 种子填充算法(Seed Fill Algorithm):
-种子填充算法基于种子点的概念,选择一个起始点作为种子点,然后根据预设的填充规则进行填充。

-算法流程如下:
-选择一个起始点作为种子点,将该点填充上颜色;
-判断该种子点的相邻像素是否需要填充,如果需要则将其填充;
-一直延伸填充,直到整个区域被填充完毕。

-种子填充算法的优点是效率较高,能够处理较大的区域,但是需要选择合适的填充规则,否则可能会导致填充区域不准确或者出现漏填的情况。

以上两种区域填充算法在实际应用中会根据具体的场景和需求选择合适的算法进行使用。

在实际实现时,还需要考虑一些特殊情况,如图像边界处理、扫描顺序等,以确保算法的正确性和效率。

一、四向种子填充算法.doc

一、四向种子填充算法.doc

一、四向种子填充算法void BoundaryFill4(int x, int y, COLORREF fillClr, COLORREF edgeClr, CDC *pDC){COLORREF cPixel;cPixel=pDC->GetPixel(x, y);if((cPixel !=edgeClr)&&(cPixel !=fillClr)){pDC->SetPixel(x,y,fillClr);Sleep(0);BoundaryFill4( x, y+1, fillClr,edgeClr,pDC);BoundaryFill4( x, y-1, fillClr,edgeClr,pDC);BoundaryFill4( x-1, y, fillClr,edgeClr,pDC);BoundaryFill4( x+1, y, fillClr,edgeClr,pDC);}}二、八向种子填充算法void Scanline_seed_fill(CDC *pDC, int seedx, int seedy, COLORREF color, COLORREF fillcolor){COLORREF clr;int x,y,x0,y0,xl,xr,flag,xnextspan;iStack=0;x=seedx;y=seedy;y0=y;push(x,y);color=pDC->SetPixel(x,y,color);while(iStack >0){pop(x,y);clr=pDC->SetPixel(x,y,fillcolor);x0=x+1;while(pDC->GetPixel(x0,y) !=color){pDC->SetPixelV(x0,y,fillcolor);x0++;}xr=x0-1; // 最右像素x0=x-1;while(pDC->GetPixel(x0,y) !=color){pDC->SetPixelV(x0,y,fillcolor);x0--;}xl=x0+1; // 最左像素//x0=xl;y=y+1;while(x0<=xr){flag=0;while(pDC->GetPixel(x0,y) !=color &&pDC->GetPixel(x0,y) !=clr && x0<xr){if(flag==0) flag=1;x0++;}if(flag==1){if(x0==xr && pDC->GetPixel(x0,y) !=color && pDC->GetPixel(x0,y) !=clr)push(x0,y);elsepush(x0-1,y);flag=0;}xnextspan=x0;while(pDC->GetPixel(x0,y) ==color ||pDC->GetPixel(x0,y) ==clr && x0<=xr)x0++;if(xnextspan==x0) x0++;}//x0=xl;y=y-2;while(x0<=xr){flag=0;while(pDC->GetPixel(x0,y) !=color &&pDC->GetPixel(x0,y) !=clr && x0<xr){if(flag==0) flag=1;x0++;}if(flag==1){if(x0==xr && pDC->GetPixel(x0,y) !=color && pDC->GetPixel(x0,y) !=clr)push(x0,y);elsepush(x0-1,y);flag=0;}xnextspan=x0;while(pDC->GetPixel(x0,y) ==color ||pDC->GetPixel(x0,y) ==clr && x0<=xr)x0++;if(xnextspan==x0) x0++;}}}void push(int x, int y){if(iStack>1000)return;else{iStack++;stackX[iStack]=x;stackY[iStack]=y;}}int pop(int &x, int &y){if(iStack<=0) return -1;x=stackX[iStack];y=stackY[iStack];iStack--;return iStack;}。

计算机图形学-4实区域填充

计算机图形学-4实区域填充

表5
4∧
3
2
1 0∧
P4P5
528 .
P5P6
5 -1.5 7 ∧
11 0 8 ∧ P3P4
2 0 7 ∧ P6P1
5 -3 2 . 5 3 3 ∧
P1P2
P2P3
P4P5
P3P4
y=7
9 2 8 . 11 0 8 ∧
更新边表,删除P6P1和P5P6,填充交点之间的区域
更新边表,删除P4P5和P3P4,有效边表为空,没有新边,填充算法结束
扫描线与多边形相交的边分处扫描线的两侧,则计 一个交点。设yi是扫描线,yi-1,yi+1分别是共享该顶 点的另外两个顶点,即 yi>yi-1,yi<yi+1,则计1个交 点,如P1。
扫描线与多边形相交的边分处扫描线同侧,且 yi<yi-1,yi<yi+1,则计2个交点(填色),如P2。
扫描线与多边形相交的边分处扫描线同侧,且 yi>yi-1,yi>yi+1,则计0个交点(不填色),如P6。
八向连通算法种子填充算法八向连通区域连通方式对填充结果的影响4连通区域填充算法的填充结果8连通区域填充算法的填充结果简单的种子填充算法4连通边界按右上左下顺序检查与出栈象素相邻的四象素若其中某象素不在边界上且未被置成填充色则将其入栈填充算法演示简单的种子像素入栈有些象素会入栈多次这样一方面降低了算法的效率另一方面还要求很大的存储空间以实现栈的结构解决这个问题的一个办法是在任意一个扫描线与多边形的相交区间含有若干个连续象素中只取一个种象素入栈相应的算法称为扫描线填充算法
扫描线填充算法规则
规则1: 边界上象素的取舍问题,避免填充扩大化。 解决方法: 边界象素:规定落在右上边界的象素不予填充。 具体实现时,只要对扫描线与多边形的相交区间左闭 右开,下闭上开。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机图形学实践教程(VisualC++版)(第2版)
案例8 四邻接点种子填充算法
孔令德 太原工业学院计算机工程系 2017.1.10
知识点


四邻接点种子填充算法。 判断种子像素位于多边形之内的方法。 种子像素四邻接点的访问方法。 堆栈操作函数。
案例描述
请使用四邻接点种子算法填充示例多边形。在1024×768的显
总结
本案例设计了CStackNode类用于执行堆栈操作。种子填 充算法一般要求填充色与边界色不同。 种子算法将太多的像素入栈,当图形较大时,栈内的数 据量庞大,填充效率很低。改进方法是使用扫描线种子填充
算法,这样入到明显改善。
pTop=pHead->pNext;
pHead->pNext=pTop->pNext; point=pTop->PixelPoint; delete pTop; } }
程序代码
(4)填充函数 void CTestView::FillPolygon(CDC *pDC) { COLORREF BoundaryClr=RGB(0,0,0); //边界色 COLORREF PixelClr; //当前像素的颜色 pHead=new CStackNode; //建立栈头结点 pHead->pNext=NULL; //栈头结点的指针域总为空 Push(Seed); //种子像素入栈 CP2 PopPoint; Pop(PopPoint); pDC->SetPixelV(Round(PopPoint->PixelPoint.x),Round(PopPoint>PixelPoint.y),SeedClr); PointLeft.x=PopPoint->PixelPoint.x-1; //搜索出栈结点的左方像素 PointLeft.y=PopPoint->PixelPoint.y; PixelClr=pDC->GetPixel(Round(PointLeft.x),Round(PointLeft.y)); if(BoundaryClr!=PixelClr && SeedClr!=PixelClr) Push(PointLeft); //左方像素入栈
示分辨率下,将多边形顶点放大为P0(50,100),P1(150,300),P2(-250,50),P3(-150,-250) ,P4(0,-50), P5 (100,-250), P6(300,150)。
效果图
图8-1 效果图
原理算法
(1)调用颜色对话框读取填充色。 (2)绘制示例多边形区域。 (3)设置默认边界色为黑色,默认种子色为蓝色。 (4)鼠标选择种子的像素的坐标(x0,y0)位置,执行x=x0±1与 y=y0±1操作,判断x或y是否到达客户区边界。如果x或y到达客户区边 界,给出“种子不在图形之内”的警告信息,重新选择种子像素的位 置。 (5)将位于多边形区域之内的种子像素入栈。 (6)如果栈不为空,将栈顶的像素点出栈,用种子色绘制出栈像素。 (7)按左、上、右、下顺序搜索出栈像素的四个邻接点像素。如果相 邻像素的颜色不是边界色并且不是种子色,将其入栈,否则丢弃。 (8)重复步骤(6),直到栈为空。
程序代码
(2)入栈函数 void CTestView::Push(CP2 point)
{
pTop=new CStackNode; pTop->PixelPoint=point; pTop->pNext=pHead->pNext; pHead->pNext=pTop; }
程序代码
(3)出栈函数 void CTestView::Pop(CP2 &point) { if(pHead->pNext!=NULL) {
程序代码
(4)填充函数 PointTop.x=PopPoint->PixelPoint.x; PointTop.y=PopPoint->PixelPoint.y+1; //搜索出栈结点的上方像素 PixelClr=pDC->GetPixel(Round(PointTop.x),Round(PointTop.y)); if(BoundaryClr!=PixelClr && SeedClr!=PixelClr) Push(PointTop); //上方像素入栈 PointRight.x=PopPoint->PixelPoint.x+1; //搜索出栈结点的右方像素 PointRight.y=PopPoint->PixelPoint.y; PixelClr=pDC->GetPixel(Round(PointRight.x),Round(PointRight.y)); if(BoundaryClr!=PixelClr && SeedClr!=PixelClr) Push(PointRight); //右方像素入栈 PointBottom.x=PopPoint->PixelPoint.x; PointBottom.y=PopPoint->PixelPoint.y-1; //搜索出栈结点的下方像素 PixelClr=pDC->GetPixel(Round(PointBottom.x),Round(PointBottom.y)); if(BoundaryClr!=PixelClr && SeedClr!=PixelClr) Push(PointBottom); //下方像素入栈 } }
程序代码
(1)建立栈结点类CStackNode 栈结点用于动态存储多边形内区域内的像素,PixelPoint为像素的坐标。 class CStackNode { public: CStackNode(); virtual ~CStackNode(); public: CP2 PixelPoint; CStackNode *pNext; };
相关文档
最新文档