计算机图形学四连通区域种子填充算法实验
————————————————————————————————作者: ————————————————————————————————日期:
ﻩ
《计算机图形学实验》报告
任课教师:钱文华
2016年春季学期
实验:四连通区域种子填充算法
实验时间:2016年12月8日
实验地点:信息学院2204
实验目的:掌握种子填充算法的原理,并会用种子填充算法和ope
ngl并结合使用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);
后的结果如下图:
实验总结:通过多组数据的测试,知道了上面算法的正确,普适性。
种子填充的递归算法的优点是原理非常简单,容易理解,缺点是由于多次递归,费时,费内存,效率不高,需要大量栈空间来存储相邻的点,太大的区域会由于递归太深而无法运行。
为了减少递归次数,可采用扫描线种子算法。
扫描线填充算法就是它的改进的方法。
它是通过沿扫描线填充水平像素段,来处理四连通或八连通相邻点,这样就仅仅只需要将每个水平像素段的起始位置压入栈,而不需要将当前位置周围尚未处理的相邻像素都压入栈,从而可以节省大量的栈空间。