区域填充种子算法实现
实验三 区域填充算法的实现
![实验三 区域填充算法的实现](https://img.taocdn.com/s3/m/746a1c2b0722192e4536f68f.png)
实验三区域填充算法的实现一、实验目的和要求:1、掌握区域填充算法基本知识2、理解区域的表示和类型,能正确区分四连通和八连通的区域3、了解区域填充的实现原理,利用Microsoft Visual C++ 6.0或win-TC实现区域种子填充的递归算法。
二、实验内容:1、编程完成区域填色2、利用画线函数,在屏幕上定义一个封闭区域。
3、利用以下两种种子填充算法,填充上述步骤中定义的区域(1)边界表示的四连通区域种子填充的实现(2)内点表示的四连通区域种子填充的实现4、将上述算法作部分改动应用于八连通区域,构成八连通区域种子填充算法,并编程实现。
三、实验结果分析四连通图的实现:程序代码:#include<graphics.h>#include <conio.h>#include<math.h>#include<time.h>void BoundaryFill4(int x,int y,int Boundarycolor,int newcolor){if(getpixel(x,y) != newcolor && getpixel(x,y) !=Boundarycolor){putpixel(x,y,newcolor);Sleep(1);BoundaryFill4(x-1,y,Boundarycolor,newcolor);BoundaryFill4(x,y+1,Boundarycolor,newcolor);BoundaryFill4(x+1,y,Boundarycolor,newcolor);BoundaryFill4(x,y-1,Boundarycolor,newcolor);}}void polygon(int x0,int y0,int a,int n,float af){int x,y,i;double dtheta,theta;if(n<3)return;dtheta=6.28318/n;theta=af*0.0174533;moveto(x0,y0);x=x0;y=y0;for(i=1;i<n;i++){x=x+a*cos(theta);y=y+a*sin(theta);lineto(x,y);theta=theta+dtheta;}lineto(x0,y0);}void main(){int x=50,y=75;int a,b,c,d,i,j;int graphdriver=DETECT;int graphmode=0;initgraph(&graphdriver,&graphmode," ");cleardevice();setcolor(RGB(0,255,0));setfillstyle(WHITE);polygon(x,y,60,5,0.);a=100;b=100;c=RGB(0,255,0);d=RGB(255,0,255);BoundaryFill4(a,b,c,d);getch();closegraph();}实验结果八连通的实现程序代码:#include<graphics.h>#include<conio.h>#include<time.h>#include <malloc.h>#include <windows.h>#define MaxSize 100typedef struct{int x;int y;}Seed,ElemType;typedef struct{ElemType data[MaxSize];int top; //栈顶指针} SqStack;void InitStack(SqStack *&s){s=(SqStack *)malloc(sizeof(SqStack));s->top=-1;}int StackEmpty(SqStack *s){return(s->top==-1);}int Push(SqStack *&s,ElemType e){if (s->top==MaxSize-1)return 0;s->top++;s->data[s->top]=e;return 1;}int Pop(SqStack *&s,ElemType &e){if (s->top==-1)return 0;e=s->data[s->top];s->top--;return 1;}void floodfill8(int x,int y,int oldcolor,int newcolor) {if(getpixel(x,y)==oldcolor){putpixel(x,y,newcolor);Sleep(2);floodfill8(x,y+1,oldcolor,newcolor);floodfill8(x,y-1,oldcolor,newcolor);floodfill8(x-1,y,oldcolor,newcolor);floodfill8(x+1,y,oldcolor,newcolor);floodfill8(x+1,y+1,oldcolor,newcolor);floodfill8(x+1,y-1,oldcolor,newcolor);floodfill8(x-1,y+1,oldcolor,newcolor);floodfill8(x-1,y-1,oldcolor,newcolor);}}void main(){int a,b,c,d,i,j;int graphdriver=DETECT;int graphmode=0;initgraph(&graphdriver,&graphmode," "); cleardevice();setfillstyle(RGB(255,255,255));setcolor(GREEN);int points[]={320,200,270,290,370,290}; fillpoly(3,points);rectangle(500,420,100,100);a=RGB(255,255,255);b=RGB(255,0,0);floodfill8(320,240,a,b);c=RGB(0,0,0);d=RGB(0,0,255);floodfill8(320,180,c,d);getch();closegraph();}实验结果:2、结果分析:通过以上各算法运行结果分析与对比可知:1.四连通算法的缺点是有时不能通过狭窄区域,因而不能填满多边形。
基于扫描种子线算法的多边形区域填充实现
![基于扫描种子线算法的多边形区域填充实现](https://img.taocdn.com/s3/m/aec5fd5732687e21af45b307e87101f69e31fbcb.png)
基于扫描种⼦线算法的多边形区域填充实现 本学期算法课上我们学习了计算⼏何的基础内容,在课后的深⼊了解学习中我发现,计算⼏何仅仅是算法世界⼀个重要分⽀——计算机图形学的基础部分之⼀,计算机图形学还有很多其他⾮常有趣的算法,例如直线⽣成、圆⽣成、椭圆⽣成。
⽽在本学期进⾏java项⽬实践的过程中,我也遇到了⼀个和计算机图形学息息相关的问题,那就是如何实现windows⾃带画图软件中的⼯具油漆桶?⽹上的开源画图代码基本上均只实现了其他简单的绘制⼯具。
为此,在查阅⼤量相关资料后,我学习到,种⼦填充算法可以很好地实现多边形区域填充,并⽤其中效果最好的基于栈的扫描线种⼦填充算法实现了画板中的油漆桶⼯具。
找到特定的算法,搞懂原理并写出算法的程序代码,在这个过程中,我深刻地认识到了算法的⽆处不在,也深切地感受到算法的乐趣,感受到⽤算法解决问题后的成就感。
简要介绍下算法的原理,实现⾮⽮量图形区域填充常⽤的种⼦填充算法根据对图像区域边界定义⽅式以及对点的颜⾊修改⽅式不同可分为注⼊填充算法(Flood Fill Algorithm)和边界填充算法(Boundary Fill Algorithm)。
两者的核⼼都是递归加搜索,即从指定的种⼦点开始,向上、下、左、右、左上、左下、右上和右下全部⼋个⽅向上搜索,逐个像素进⾏处理,直到遇到边界。
两者的区别仅在于Flood Fill Algorithm不强调区域的边界,它只是从指定位置开始,将所有联通区域内某种指定颜⾊的点都替换成另⼀种颜⾊,即实现颜⾊替换的功能;⽽边界填充算法与注⼊填充算法递归的结束条件不⼀样,Boundary Fill Algorithm强调边界的存在,只要是边界内的点,⽆论是什么颜⾊,都替换成指定的颜⾊。
但是在实际项⽬中,使⽤递归算法效率太低,为了消除递归,有⼀种更为常⽤的改进算法,即扫描线种⼦填充算法。
它通过沿竖直扫描线填充像素段,⼀段⼀段地来处理8-联通的相邻点,这样算法处理过程中就只需要将每个竖直像素段的起始点位置压⼊⼀个特殊的栈,⽽不需要像递归算法那样将当前位置周围尚未处理的所有相邻点都压⼊堆栈,从⽽节省了堆栈空间,本实例采⽤的就是结合泛洪填充算法(或者说注⼊填充算法)的扫描线种⼦填充算法。
实验2:多边形区域扫描线填充或种子填充
![实验2:多边形区域扫描线填充或种子填充](https://img.taocdn.com/s3/m/a379063f376baf1ffc4fadb8.png)
实验2:多边形区域扫描线填充或种子填充计科102 蓝广森 1007300441一、实验目的通过实验,进一步理解和掌握几种常用多边形填充算法的基本原理掌握多边形区域填充算法的基本过程掌握在C/C++环境下用多边形填充算法编程实现指定多边形的填充。
二、实验内容及要求实现多边形区域扫描线填充的有序边表算法,并将实现的算法应用于任意多边形的填充,要求多边形的顶点由键盘输入或鼠标拾取,填充要准确,不能多填也不能少填。
要求掌握边形区域扫描线填充的有序边表算法的基本原理和算法设计,画出算法实现的程序流程图,使用C或者VC++实现算法,并演示。
三、实验原理种子填充算法又称为边界填充算法。
其基本思想是:从多边形区域的一个内点开始,由内向外用给定的颜色画点直到边界为止。
如果边界是以一种颜色指定的,则种子填充算法可逐个像素地处理直到遇到边界颜色为止。
种子填充算法常用四连通域和八连通域技术进行填充操作。
四向连通填充算法:a)种子像素压入栈中;b)如果栈为空,则转e);否则转c);c)弹出一个像素,并将该像素置成填充色;并判断该像素相邻的四连通像素是否为边界色或已经置成多边形的填充色,若不是,则将该像素压入栈;d)转b);e)结束。
扫描线填充算法的基本过程如下:当给定种子点(x,y)时,首先填充种子点所在扫描线上的位于给定区域的一个区段,然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。
反复这个过程,直到填充结束。
区域填充的扫描线算法可由下列四个步骤实现:(1)初始化:堆栈置空。
将种子点(x,y)入栈。
(2)出栈:若栈空则结束。
否则取栈顶元素(x,y),以y作为当前扫描线。
(3)填充并确定种子点所在区段:从种子点(x,y)出发,沿当前扫描线向左、右两个方向填充,直到边界。
分别标记区段的左、右端点坐标为xl和xr。
(4)并确定新的种子点:在区间[xl,xr]中检查与当前扫描线y上、下相邻的两条扫描线上的象素。
案例9 区域八邻接点种子填充算法
![案例9 区域八邻接点种子填充算法](https://img.taocdn.com/s3/m/8b1c0c14ba1aa8114431d9e7.png)
总结
八邻接点种子填充算法的种子像素可以位于区域的上方 多边形内或下方多边形内,填充过程不同,但都可以获得一 致的填充效果。
(a)多边形
(b)连接点放大效果图 图9-1八连通域
效果图
图9-2 效果图
原理算法
(1)调用颜色对话框读取填充色。 (2)绘制多边形区域。 (3)设置默认边界色为黑色,默认种子色为蓝色。 (4)鼠标选择种子的像素的坐标(x0,y0)位置,执行x=x0±1与 y=y0±1操作,判断x或y是否到达客户区边界。如果x或y到达客户区边 界,给出“种子不在图形之内”的警告信息,重新选择种子像素的位 置。 (5)将多边形区域内的种子像素入栈。 (6)如果栈不为空,将栈顶像素出栈,用种子色绘制出栈像素。 (7)按左、左上、上、右上、右、右下、下、左下顺序搜索出栈像素 的八个邻接点像素。如果相邻像素的颜色不是边界色并且不是种子色 ,将其入栈,否则丢弃。 (8)重复步骤(6),直到栈为空。
程序代码
填充函数 while(pHead->pNext!=NULL)//如果栈不为空 { CP2 PopPoint; Pop(PopPoint); pDC->SetPixelV(Round(PopPoint.x),Round(PopPoint.y),SeedClr); Left.x=PopPoint.x-1;//搜索出栈结点的左方像素 Left.y=PopPoint.y; PixelClr=pDC->GetPixel(Round(Left.x),Round(Left.y)); if(BoundaryClr!=PixelClr && SeedClr!=PixelClr)//不是边界色并且未置成填充色 Push(Left);//左方像素入栈 LeftTop.x=PopPoint.x-1; LeftTop.y=PopPoint.y+1;//搜索出栈结点的左上方像素 PixelClr=pDC->GetPixel(Round(LeftTop.x),Round(LeftTop.y));
区域填充算法
![区域填充算法](https://img.taocdn.com/s3/m/ae00d205f68a6529647d27284b73f242326c315b.png)
区域填充算法⼀、区域填充概念区域:指已经表⽰成点阵形式的填充图形,是象素的集合。
区域填充:将区域内的⼀点(常称种⼦点)赋予给定颜⾊,然后将这种颜⾊扩展到整个区域内的过程。
区域填充算法要求区域是连通的,因为只有在连通区域中,才可能将种⼦点的颜⾊扩展到区域内的其它点。
1、区域有两种表⽰形式1. 内点表⽰:枚举出区域内部的所有象素内部所有象素着同⼀个颜⾊边界像素着与内部象素不同的颜⾊。
2. 边界表⽰:枚举出区域外部的所有象素边界上的所有象素着同⼀个颜⾊内部像素着与边界象素不同的颜⾊。
2、区域连通1. 四向连通区域:从区域上⼀点出发可通过上、下、左、右四个⽅向移动的组合,在不越出区域的前提下,到达区域内的任意象素。
2. ⼋向连通区域:从区域上⼀点出发可通过上、下、左、右、左上、右上、左下、右下⼋个⽅向移动的组合,在不越出区域的前提下,到达区域内的任意象素。
3. 四连通与⼋连通区域的区别连通性:四连通可以看作⼋连通的⾃⼰,但是对边界有要求⼆、简单种⼦填充算法1、基本思想给定区域G⼀种⼦点(x, y),⾸先判断该点是否是区域内的⼀点,如果是,则将该点填充为新的颜⾊,然后将该点周围的四个点(四连通)或⼋个点(⼋连通)作为新的种⼦点进⾏同样的处理,通过这种扩散完成对整个区域的填充。
这⾥给出⼀个四连通的种⼦填充算法(区域填充递归算法),使⽤【栈结构】来实现原理算法原理如下:种⼦像素⼊栈,当【栈⾮空】时重复如下三步:2、算法代码这⾥给出⼋连通的种⼦填充算法的代码: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);}}}3、OpenCV实现import cv2def seed_fill(img):ret, img = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY_INV) label = 100stack_list = []h, w = img.shapefor i in range(1, h-1, 1):for j in range(1, w-1, 1):if (img[i][j] == 255):img[i][j] = labelstack_list.append((i, j))while len(stack_list) != 0:cur_i = stack_list[-1][0]cur_j = stack_list[-1][1]img[cur_i][cur_j] = labelstack_list.remove(stack_list[-1])# 四邻域,可改为⼋邻域if (img[cur_i-1][cur_j] == 255):stack_list.append((cur_i-1, cur_j))if (img[cur_i][cur_j-1] == 255):stack_list.append((cur_i, cur_j-1))if (img[cur_i+1][cur_j] == 255):stack_list.append((cur_i+1, cur_j))if (img[cur_i][cur_j+1] == 255):stack_list.append((cur_i, cur_j+1))cv2.imwrite('./result.jpg', img)cv2.imshow('img', img)cv2.waitKey()if __name__ == '__main__':img = cv2.imread('./test.jpeg', 0)seed_fill(img)4、简单种⼦填充算法的优点和缺点优点:1. 该算法也可以填充有孔区域缺点:1. 有些像素会多次⼊栈,降低算法效率,栈结构占空间2. 递归执⾏,算法简单,但效率不⾼,区域内每⼀像素都要进/出栈,费时费内存3. 改进算法,减少递归次数,提⾼效率三、扫描线种⼦填充算法⽬标:减少递归层次适⽤于边界表⽰的4连通区间1、基本思想在任意不间断区间中只取⼀个种⼦像素(不间断区间指在⼀条扫描线上⼀组相邻元素),填充当前扫描线上的该段区间;然后确定与这⼀区段相邻的上下两条扫描线上位于区域内的区段,并依次把它们保存起来,反复进⾏这个过程,直到所保存的各个区段都填充完毕。
实验三 区域填充原理
![实验三 区域填充原理](https://img.taocdn.com/s3/m/b41bf200eff9aef8941e0637.png)
实验三区域填充原理实验目的掌握二维区域填充的填充算法;实验环境计算机、Turbo C、C++等其他语言程序设计环境实验学时2学时,必做实验。
实验内容1.二维封闭区域的种子填充算法和扫描线种子填充算法;2.熟悉多边形扫描线填充算法;内点表示四连通种子填充算法(漫水法)参考代码:#include<graphics.h>void floodfill4(int x,int y,int oldcolor,int newcolor){if(getpixel(x,y)==oldcolor){putpixel(x,y,newcolor);delay(20000);floodfill4(x,y+1,oldcolor,newcolor);floodfill4(x,y-1,oldcolor,newcolor);floodfill4(x-1,y,oldcolor,newcolor);floodfill4(x+1,y,oldcolor,newcolor);}}main(){int a,b,c,d,i,j;int graphdriver=DETECT, graphmode=0;initgraph(&graphdriver,&graphmode," ");cleardevice();setcolor(14);rectangle(100,100,150,150);for(i=101;i<150;i++)for(j=101;j<150;j++){ putpixel(i,j,4);delay(1000);}a=120; b=110; c=4; d=2;floodfill4(a,b,c,d);getch();closegraph();}边界表示的4连通区域的种子填充算法:#include<stdio.h>;#include<graphics.h>;void BoundaryFill4(int x,int y,int boundarycolor,int newcolor) {if(getpixel(x,y)!=boundarycolor&getpixel(x,y)!=newcolor) {putpixel(x,y,newcolor);delay(20000);BoundaryFill4(x,y+1,boundarycolor,newcolor);BoundaryFill4(x,y-1,boundarycolor,newcolor);BoundaryFill4(x-1,y,boundarycolor,newcolor);BoundaryFill4(x+1,y,boundarycolor,newcolor);}}main() {int a,b,c=14,d,i,j;int graphdriver=DETECT,graphmode=0;initgraph(&graphdriver,&graphmode," ");cleardevice();setcolor(c);rectangle(100,100,150,150);for(i=101;i<150;i++)for(j=101;j<150;j++) { putpixel(i,j,4); delay(1000); } a=120; b=130; d=2;BoundaryFill4(a,b,c,d);getch();closegraph();}扫描线种子填充算法参考代码:#include<graphics.h>#include<stdio.h>#include<stdlib.h>#define bordercolor 15#define backcolor 0#define seedcolor 4#define fillcolor 10typedef struct Point{int x;int y;}point;typedef struct Stack{point *base;point *top;}*stack;void initstack(stack s){(*s).base=(point*)malloc(sizeof(point));if(!(*s).base)exit(1);(*s).top=(*s).base;}void push(stack s,point p){*((*s).top)=p;(*s).top++;}int stackempty(stack s){if((*s).top==(*s).base)return(1);else return(0);}point pop(stack s){(*s).top--;return(*((*s).top));}void drawgraphics(){int a[10]={100,140,260,80,300,200,160,240,100,140}; drawpoly(5, a);/*circle(200,200,150);*/}point produceseed(){point p;p.x=200;p.y=200;return(p);}void intostack(stack s,int y0,int xl,int xr){int x,y;point tm;for(x=xl,y=y0;x<=xr&&x<getmaxx();x++){if((x!=xr&&getpixel(x,y)==backcolor&&getpixel(x+1,y)!=backcolor)||(x==xr&&getpixel(x,y)==backcolor)){tm.x=x;tm.y=y;push(s,tm);putpixel(x,y,seedcolor);}if(x==xr&&getpixel(x,y)==backcolor)break;}}void fillgraphics(){int xl=0,xr=getmaxx(),x,y;point seed;stack s=NULL;seed=produceseed();putpixel(seed.x,seed.y,seedcolor);getch();initstack(s);push(s,seed);while(!stackempty(s)){seed=pop(s);for(x=seed.x,y=seed.y;getpixel(x,y)==backcolor||getpixel(x,y)==seedcolor;x++) {putpixel(x,y,fillcolor);}xr=x-1;for(x=seed.x-1,y=seed.y;getpixel(x,y)==backcolor||getpixel(x,y)==seedcolor;x--) {putpixel(x,y,fillcolor);}xl=x+1;intostack(s,seed.y+1,xl,xr);intostack(s,seed.y-1,xl,xr);getch();}}void main(){int gdriver ,gmode ;gdriver = DETECT;initgraph(&gdriver , &gmode ,"" );drawgraphics();fillgraphics();outtextxy(180,20,"Scan line filling graphics finished!"); getch();closegraph();}多边形扫描线填充算法参考代码:/* Note:扫描线填充算法*/#include <graphics.h>#include <conio.h>#include <math.h>#define MAXPOINT 20typedef struct {int y_top;float x_int;int delta_y;float x_cps;}E_ENTRY;void putin_sl(int entry,int x1,int y1,int x2,int y2,int next_y); void sortonby(int n);void updatefl(int count,int scan);void swap(E_ENTRY *x,E_ENTRY *y);void sortonx(int entry,int first_s);void processx(int first_s,int last_s);void drawline(int scan,int x_int_c,int index);void updatesl();E_ENTRY sides[MAXPOINT];int x[MAXPOINT]={0,210,240,230,350,380,340,200,180,150}; int y[MAXPOINT]={0,410,370,200,410,340,140,180,120,300}; int s_count,first_s,last_s,scan,bottom_s,x_int_c;main(){int driver,mode;int v_count=9;driver=DETECT;initgraph(&driver,&mode,"");setcolor(3);fillarea(v_count,x,y);getch();closegraph();}fillarea(int count){sortonby(count);first_s=1;last_s=1;for(scan=sides[1].y_top;scan>bottom_s;scan--){updatefl(count,scan);processx(first_s,last_s);drawline(scan,x_int_c,first_s);updatesl();}}void putin_sl(int entry,int x1,int y1,int x2,int y2,int next_y) {int maxy;float x2_temp,xch_temp;xch_temp=(float)(x2-x1)/(float)(y2-y1);x2_temp=x2;if((y2>y1)&&(y2<next_y)){y2--;x2_temp-=xch_temp;}else{if((y2<y1)&&(y2>next_y)){y2++;x2_temp+=xch_temp;}}maxy=(y1>y2)?y1:y2;while((entry>1)&&(maxy>sides[entry-1].y_top)){sides[entry]=sides[entry-1];entry--;}sides[entry].y_top=maxy;sides[entry].delta_y=abs(y2-y1)+1;if(y1>y2)sides[entry].x_int=x1;elsesides[entry].x_int=x2_temp;sides[entry].x_cps=xch_temp;}void sortonby(int n){int k,x1,y1;s_count=0;y1=y[n];x1=x[n];bottom_s=y[n];for(k=1;k<n+1;k++){if(y1!=y[k]){s_count++;putin_sl(s_count,x1,y1,x[k],y[k],y[k+1]);}else{/* line((short)x1,480-(short)y1,(short)x[k],480-(short)y1);*/moveto((short)x1,480-(short)y1);lineto((short)x[k],480-(short)y1);}if(y[k]<bottom_s) bottom_s=y[k];y1=y[k];x1=x[k];}}void updatefl(int count,int scan){while((sides[last_s+1].y_top>scan)&&(last_s<count))last_s++;while(sides[first_s].delta_y==0) first_s++;}void swap(E_ENTRY *x,E_ENTRY *y){int i_temp;float f_temp;i_temp=x->y_top;x->y_top=y->y_top;y->y_top=i_temp;f_temp=x->x_int;x->x_int=y->x_int;y->x_int=f_temp;i_temp=x->delta_y;x->delta_y=y->delta_y;y->delta_y=i_temp;f_temp=x->x_cps;x->x_cps=y->x_cps;y->x_cps=f_temp;}void sortonx(int entry,int first_s){while((entry>first_s)&&(sides[entry].x_int<sides[entry-1].x_int)) {swap(&sides[entry],&sides[entry-1]);entry--;}}void processx(int first_s,int last_s){int k;x_int_c=0;for(k=first_s;k<last_s+1;k++){if(sides[k].delta_y>0){x_int_c++;sortonx(k,first_s);}}}void drawline(int scan,int x_int_c,int index){int k,x,x1,x2;for(k=1;k<(int)(x_int_c/2+1.5);k++){while(sides[index].delta_y==0)index++;x1=(int)(sides[index].x_int+0.5);index++;while(sides[index].delta_y==0)index++;x2=(int)(sides[index].x_int+0.5);/*line((short)x1,480-(short)scan,(short)x2,480-(short)scan);*/ moveto((short)x1,480-(short)scan);lineto((short)x2,480-(short)scan);index++;}}void updatesl(){int k;for(k=first_s;k<last_s+1;k++){if(sides[k].delta_y>0){sides[k].delta_y--;sides[k].x_int-=sides[k].x_cps;}}}。
八邻接点种子填充算法编程
![八邻接点种子填充算法编程](https://img.taocdn.com/s3/m/09705d05bf1e650e52ea551810a6f524ccbfcbe6.png)
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]
区域填充算法的实现
![区域填充算法的实现](https://img.taocdn.com/s3/m/0c79a807326c1eb91a37f111f18583d049640f1e.png)
区域填充算法的实现实现区域填充算法的一种常见方法是使用递归。
以下是一个使用递归实现的区域填充算法的伪代码:1. 定义函数fillPixel(x, y, targetColor, fillColor):-如果像素点(x,y)的颜色与目标颜色相同,将其颜色修改为填充颜色。
-否则,返回。
2. 定义函数regionFill(x, y, targetColor, fillColor):-如果像素点(x,y)的颜色与目标颜色相同,返回。
- 否则,调用fillPixel(x, y, targetColor, fillColor)。
- 递归调用regionFill(x-1, y, targetColor, fillColor)。
- 递归调用regionFill(x+1, y, targetColor, fillColor)。
- 递归调用regionFill(x, y-1, targetColor, fillColor)。
- 递归调用regionFill(x, y+1, targetColor, fillColor)。
3. 调用regionFill(seedX, seedY, targetColor, fillColor)。
在上述算法中,fillPixel函数用于将特定颜色填充到像素点(x, y)。
regionFill函数使用递归的方式遍历相邻的像素点,并对目标颜色的像素点调用fillPixel函数。
seedX和seedY表示种子像素点的坐标,targetColor表示目标颜色,fillColor表示填充颜色。
实现区域填充算法时还需要考虑以下几个问题:1.像素点的表示:图像可以由二维数组表示,其中每个元素表示一个像素点的颜色。
2.填充颜色选择:填充颜色可以由RGB值表示,或者在预定义的颜色集合中选择。
3.边界处理:对于位于图像边界上的种子像素点,需要特殊处理以防止数组越界错误。
4.递归终止条件:填充算法使用递归,需要定义递归终止的条件,以防止无限递归。
区域填充算法
![区域填充算法](https://img.taocdn.com/s3/m/ed1ea940e45c3b3567ec8b7e.png)
7
9 9
9
对边界和内点表示的八连通区域的填充,只要将上述算法的对四 个像素点填充改为八个像素点即可。 四连通区域种子填充算法的缺点是有时不能通过狭窄区域区域, 因而不能填满多边形。八连通算法的缺点是有时会填出多边形的 边界。由于填不满比涂出更容易补救,因此四连通算法比八连通 算法用得更多。
(3)扫描线种子填充算法
(2)内点表示的四连通区域种子填充算法
基本思想:从多边形内部任一点(像素)出发,按照“右 上左下”的顺序判断相邻像素,若是区域内的像素,则对 其填充,并重复上述过程,直至所有像素填充完毕。 可以使用栈结构来实现该算法,种子像素入栈,档栈非空, 重复执行下面操作: 1)栈顶像素出栈; 2)将出栈像素置成多边形填充的颜色;
基本思想:从多边形内部任一点(像素)出发,按照 “右上左下”的顺序判断相邻像素,若不是边界像素 且没被填充过,则对其填充,并重复上述过程,直至 所有像素填充完毕。 可以使用栈结构来实现该算法,种子像素入栈,档栈 非空,重复执行下面操作: 1)栈顶像素出栈; 2)将出栈像素置成多边形填充的颜色; 3)按“右上左下”的顺序检查与出栈像素相邻的四个 像素,若其中某个像素不在边界上且未置成多边形色, 则把该像素入栈。
扫描线算法分析(举例分析)
基本思想:在任意不间断的区间中只取一个像素(不 间断区间指一条扫描线上的一组相邻元素),填充当 前扫描线上的该段区间,然后确定与这一段相邻的上 下两条扫描线位于区域内的区段,并依次把它们保存 起来,反复进行这个过程,指导所有保存的每个区段 都填充完毕。
(3)扫描线种子填充算法
种子像素入栈,当栈非空时,重复以下步骤: (1)栈顶像素出栈 (2)沿扫描线对出栈像素的左右像素进行填充, 直到遇到边界像素为止 (3)将上述区间内最左、最右像素记为xl 和xr (4)在区间[xl ,xr]中检查与当前扫描线相邻的上 下两条扫描线是否全为边界像素、或已填充 的像素,若为非边界、未填充的像素,则把 每一区间的最右像素取为种子像素入栈
计算机图形学四连通区域种子填充算法实验
![计算机图形学四连通区域种子填充算法实验](https://img.taocdn.com/s3/m/dc0f800af121dd36a32d82e5.png)
计算机图形学四连通区域种子填充算法实验————————————————————————————————作者: ————————————————————————————————日期:ﻩ《计算机图形学实验》报告任课教师:钱文华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);后的结果如下图:实验总结:通过多组数据的测试,知道了上面算法的正确,普适性。
第三讲区域填充
![第三讲区域填充](https://img.taocdn.com/s3/m/33871783783e0912a3162a90.png)
s.push(Point(x,y)); while(!s.empty()){
p=s.pop(); SetPixel(p.x ,p.y ,newvalue); if ((GetPixel(p.x,p.y-1) != boundaryvalue) &&(GetPixel(p.x,p.y-1) !=newvalue))
八连通区域 四连通区域
4.区域的连通性 (1)四连通 (2)八连通
5.种子填充算法 利用区域的连通性进行区域填充,除了需要
区域应该明确定义外,还需要事先给定一个区域 内部象素,这个象素称为种子。
做区域填充时,要对光栅网格进行遍历,找 出由种子出发能达到而又不穿过边界的所有象素。
这种利用连通性的填充,其主要优点是不受 区域不规则性的影响,主要缺点是需要事先知道 一个内部象素。
s.push(Point(p.x-1,p.y)); if ((GetPixel(p.x+1,p.y) != boundaryvalue) &&(GetPixel(p.x+1,p.y) !=newvalue))
s.push(Point(p.x+1,p.y)); } }
(3)扫描线种子填充算法(适用于边界定义的四 连通区域)
if(flag==1)
{ 1 s.push(Point(xid,y));
flag=0;
} //检查当前填充行是否被中断,若被中断,寻找左方第一个可填
充象素
//判断当前点是否为边界点//判断当前点是否为已填充点
填充算法实验报告
![填充算法实验报告](https://img.taocdn.com/s3/m/1a3b527c5627a5e9856a561252d380eb629423eb.png)
填充算法实验报告实验报告:填充算法研究与实验1. 实验目的填充算法在计算机图形学中有着广泛的应用,并且对于计算机图形学的发展有着重要意义。
本次实验旨在通过对填充算法的研究与实验,了解填充算法的原理和应用,掌握填充算法的基本实现方法,实现简单的填充效果。
2. 实验背景填充算法是计算机图形学中的一种常用算法,用于将指定区域进行填充。
填充算法可以应用于图像的编辑、区域选择、图像渲染等方面。
常见的填充算法包括区域种子填充算法、扫描线填充算法等。
3. 实验内容本次实验主要研究和实现了区域种子填充算法和扫描线填充算法。
区域种子填充算法是指通过指定一个待填充的种子点,在其周围的区域进行填充。
扫描线填充算法是指通过扫描图像的每一行,在特定条件下对像素进行填充。
在实验中,我们首先实现了区域种子填充算法。
通过在待填充的区域中选择一个点作为种子点,然后从指定点出发,通过递归或栈的方式对相邻的像素进行着色,直到遇到与起始点像素颜色不同的像素为止,从而完成填充效果。
其次,我们实现了扫描线填充算法。
这种算法的核心是扫描图像的每一行,在每一行上找到待填充区域的边界并将其记录下来,然后根据边界的位置对每一个像素进行填充。
我们采用了活性边表和扫描线转换算法来实现扫描线填充算法。
4. 实验结果通过实验我们成功实现了区域种子填充算法和扫描线填充算法,在输入指定的区域和种子点后,程序能够快速地对指定区域进行填充,生成了良好的填充效果。
5. 实验分析区域种子填充算法是一种简单且直观的填充算法,但对于复杂区域的填充效果并不理想。
它的主要缺点是可能导致栈溢出或填充效果不均匀,因此在实际应用中不太常用。
相比之下,扫描线填充算法具有更好的填充效果和效率。
其使用了活性边表和扫描线转换算法,可以在进行每一行的扫描时快速地找到边界并进行填充。
但该算法无法很好地处理较复杂的几何形状,例如存在凹陷和自相交的区域。
6. 实验总结通过本次实验,我们深入学习了填充算法的基本原理和实现方法,并成功实现了区域种子填充算法和扫描线填充算法。
区域填充算法
![区域填充算法](https://img.taocdn.com/s3/m/06d7b2ac18e8b8f67c1cfad6195f312b3169ebc9.png)
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
计算机图形学 区域填充算法的实现
![计算机图形学 区域填充算法的实现](https://img.taocdn.com/s3/m/93d2042dccbff121dd36837b.png)
实验四区域填充算法的实现班级 08信计学号 67姓名张洪伟分数一、实验目的和要求:1. 理解区域的表示和类型;2.实现区域填充的扫描线算法;3.WIN-TC 图形编程模板实现编程结果并保存。
二、实验内容:在任意不间断区间中只取一个种子像素(不间断区间指在一条扫描线上一组相邻元素),填充当前扫描线上的该段区间;然后确定与这一区段相邻的上下两条扫描线上位于区域内的区段,并依次把它们保存起来,反复进行这个过程,直到所保存的每个区段都填充完毕。
1. 确定种子区段:从种子点出发,沿当前扫描线向左右两个方向填充直到边界。
用三元组(y,xLeft,xRight)记录此区段。
2.初始化:将堆栈设为空,将种子区段压入堆栈。
3.出栈:若堆栈为空,算法结束;否则取栈顶元素,以纵坐标为y的扫描线为当前扫描线,[xLeft,xRight]为搜索区间。
4.进栈:分别确定与当前扫描线相邻的上下两条扫描线与区段(y,xLeft,xRight)连通的位于给定区域内的区段。
如果有这样的区段,填充并将它们的信息压入堆栈,返回步骤3。
三、实验结果分析1该实验先用fillellipse(100,100,60,40) 画出实心椭圆,然后用如上算法填充,代码如下:setcolor(5);fillellipse(300,250,60,40);ScanLineFill(300,250,15,5);此算法还能填充带边框的多边形,如下代码填充一个矩形区域,oldColor 为背景色0:rectangle(100,20,200,50);ScanLineFill(125,30,0,5);如下代码填充带孔的四连通区域:bar(100,80,150,180);bar(150,80,200,90);bar(200,80,250,180);bar(150,130,200,180);ScanLineFill(110,150,15,2);对于每一个待填充的区段,只需压栈一次,因此扫描线算法的效率提高了很多。
区域填充种子算法实现
![区域填充种子算法实现](https://img.taocdn.com/s3/m/3753647f302b3169a45177232f60ddccda38e6f7.png)
区域填充种子算法实现实验三区域填充种子算法实现实验目的:1、熟练在Visual C++中程序实现及调试的能力。
2、通过程序的设计熟练区域填充种子算法过程;3、掌握堆栈在数据结构中的应用实验内容:1、visual c++中菜单的修改,点的输入及鼠标函数的控制;2、复习数据结构中堆栈的建立,入栈,出栈等函数;3、实现整个多边形的区域填充种子算法,与扫描转换算法进行区分;实验步骤:预处理:多边形点列的输入,存储于数组中P[100],种子点的输入,确定为point(x,y)确定多边形的边界色(旧画笔色),初始色(背景色),填充色(新画笔色);数据结构的建立:建立堆栈,包括数组stack[100],及一个指标top,用来指向当前堆栈的最外面的栈口的元素。
步骤:1、堆栈置为空,top=0;2、将初始的种子点point进栈,push(x,y);3、填色堆栈非空即top>0时,一直循环下列步骤取栈顶的元素,出栈pop(x,y),savex=x;从当前点开始沿当前扫描线往右检验,若有未填新色的,则填色。
然后同样往左检验。
当前扫描线俩个方向都检查完后,检验上一条扫描线y=y+1; 若有未填新色的,则把所有未填新色区间的右端点压入堆栈。
同理检验下一条扫描线y=y-2;实验指导:一、在实验二的基础上进行编程;(1)引入实验二代码scanline.dsw二、编辑菜单资源选中窗口左边栏的“ResourceView ”,其中的“Menu ”,双击“IDR_MAINFRAME ”,右边即为菜单,在菜单上空处双击,出项如图所示窗口,其中弹出不选中;如上,同样创建其余菜单项。
(如下表);三、添加消息处理函数由菜单的“查看”,“建立类向导”,打开ClassWizard (也可CTRL+W )为应用程序添加与菜单项相关的消息处理函数,ClassName 栏选中CScanLineView 类,根据表建立。
输入菜单项名称,(如显示多边形)双击,出现如下窗口四、程序结构代码 1、添加全局变量在CScanLineView.h 文件中相应位置添加如下代码:(红体为需加入代码)// Implementation public:CPoint P[100], pt, stack[100]; int top, flag , num ;说明: pt 定义为全局变量,为种子点坐标; stack[100]为堆栈;top 为堆栈的最外的元素的位子; flag 为指标,判别flag=1时鼠标左键按下可取种子点。
算法系列之十二:多边形区域填充算法--扫描线种子填充算法
![算法系列之十二:多边形区域填充算法--扫描线种子填充算法](https://img.taocdn.com/s3/m/e348663c2bf90242a8956bec0975f46527d3a709.png)
算法系列之⼗⼆:多边形区域填充算法--扫描线种⼦填充算法1.3扫描线种⼦填充算法1.1和1.2节介绍的两种种⼦填充算法的优点是⾮常简单,缺点是使⽤了递归算法,这不但需要⼤量栈空间来存储相邻的点,⽽且效率不⾼。
为了减少算法中的递归调⽤,节省栈空间的使⽤,⼈们提出了很多改进算法,其中⼀种就是扫描线种⼦填充算法。
扫描线种⼦填充算法不再采⽤递归的⽅式处理“4-联通”和“8-联通”的相邻点,⽽是通过沿⽔平扫描线填充像素段,⼀段⼀段地来处理“4-联通”和“8-联通”的相邻点。
这样算法处理过程中就只需要将每个⽔平像素段的起始点位置压⼊⼀个特殊的栈,⽽不需要象递归算法那样将当前位置周围尚未处理的所有相邻点都压⼊堆栈,从⽽可以节省堆栈空间。
应该说,扫描线填充算法只是⼀种避免递归,提⾼效率的思想,前⾯提到的注⼊填充算法和边界填充算法都可以改进成扫描线填充算法,下⾯介绍的就是结合了边界填充算法的扫描线种⼦填充算法。
扫描线种⼦填充算法的基本过程如下:当给定种⼦点(x, y)时,⾸先分别向左和向右两个⽅向填充种⼦点所在扫描线上的位于给定区域的⼀个区段,同时记下这个区段的范围[xLeft, xRight],然后确定与这⼀区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。
反复这个过程,直到填充结束。
扫描线种⼦填充算法可由下列四个步骤实现:(1) 初始化⼀个空的栈⽤于存放种⼦点,将种⼦点(x, y)⼊栈;(2) 判断栈是否为空,如果栈为空则结束算法,否则取出栈顶元素作为当前扫描线的种⼦点(x, y),y是当前的扫描线;(3) 从种⼦点(x, y)出发,沿当前扫描线向左、右两个⽅向填充,直到边界。
分别标记区段的左、右端点坐标为xLeft和xRight;(4) 分别检查与当前扫描线相邻的y - 1和y + 1两条扫描线在区间[xLeft, xRight]中的像素,从xLeft开始向xRight⽅向搜索,若存在⾮边界且未填充的像素点,则找出这些相邻的像素点中最右边的⼀个,并将其作为种⼦点压⼊栈中,然后返回第(2)步;这个算法中最关键的是第(4)步,就是从当前扫描线的上⼀条扫描线和下⼀条扫描线中寻找新的种⼦点。
Opengl的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现
![Opengl的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现](https://img.taocdn.com/s3/m/652d3b33bdd126fff705cc1755270722192e59e5.png)
Opengl的不规则图形的4联通种⼦递归填充和扫描线种⼦递归填充算法实现实验题⽬:不规则区域的填充算法实验⽬的:验证不规则区域的填充算法实验内容:利⽤VC与OpenGL,实现不规则区域的填充算法。
1、必做:实现简单递归的不规则区域填充算法。
2、选做:针对简单递归算法栈空间占⽤太⼤的缺点,进⾏改进,实现基于扫描线的种⼦填充算法实验要求:n 将坐标系⽹格在屏幕上画出来,每个像素点占据⼀个格点,⽤⼀个⼩实⼼圆圈表⽰。
n ⽤⿏标点击的⽅式,绘制不规则区域的边界。
n 种⼦填充算法,可⽤4联通或8联通任选⼀种。
以下是我⽤c++ 实现的⽅式去实现2种填充算法#include <iostream>#include <vector>#include <stack>#include <iterator>#include "glut.h"using namespace std;//////////////////////////#define WIDTH 400#define HEIGHT 400#define SUBWIDTH 20#define SUBHEIGHT 20/////////////////////////class tile // 基于open gl 的坐标系{public:enum _toolEnum{_sideLength=10}; // 边长tile(unsigned int x=0,unsigned int y=0):_x(x),_y(y){_state = 0;}void draw(){// 画出初始tile(根据不同_state,⽤不同的颜⾊)// glClear(GL_COLOR_BUFFER_BIT);if (_state == 0) // ⽆⾊{glColor3f(255 ,255 ,255);}else if(_state == 1) // 红⾊{glColor3f(255,0 ,0);}else if(_state == 2) // 绿⾊{glColor3f(0 ,255 ,0);}glBegin(GL_POINTS);glVertex2i(_x*20+10,_y*20+10);glEnd();glFlush();}inline void op_side() // 设置成边界红⾊{_state = 1;draw();}inline void op_padding() // 设置成填充绿⾊{_state = 2;draw();}public:unsigned int _x; // 瓷砖的横向索引unsigned int _y; // 瓷砖的纵向索引int _state; // 0代表⽆⾊初始状态,1代表红⾊边框,2代表绿⾊内填充容};class tileLayer{public:tileLayer(unsigned int h=20,unsigned int v=20):_hTileNum(h),_vTileNum(v){init();}void init(){for (int i=0;i<_vTileNum;i++){vector<tile> tmpVec;for (int j=0;j<_hTileNum;j++){tmpVec.push_back(tile(j,i)); // 注意是 j,icout<<j<<","<<i<<"\t";}_vecTile.push_back(tmpVec);cout<<endl;}}void recursive_pad(GLint index_X, GLint index_Y) // 参数是索引{// 在这计算是哪个为种⼦点。
区域填充算法区域填充算法
![区域填充算法区域填充算法](https://img.taocdn.com/s3/m/9d7515d1dc88d0d233d4b14e852458fb770b38b2.png)
区域填充算法区域填充算法
下面将介绍两种常见的区域填充算法:扫描线填充算法和种子填充算法。
1. 扫描线填充算法(Scanline Fill Algorithm):
-扫描线填充算法基于扫描线的原理,从图像的上方向下扫描,对每条扫描线上的像素进行填充。
-算法流程如下:
-选择一个初始扫描线,例如选择图像的最上面一条扫描线;
-遍历该扫描线上的每一个像素,判断是否需要填充该像素;
-如果需要填充,则向区域内部延伸扫描线,同时判断该扫描线上的相邻像素是否需要填充;
-一直延伸扫描线,直到整个区域被填充完毕。
-扫描线填充算法的优点是简单、易于实现,但是算法的效率较低,在处理大尺寸区域时耗时较长。
2. 种子填充算法(Seed Fill Algorithm):
-种子填充算法基于种子点的概念,选择一个起始点作为种子点,然后根据预设的填充规则进行填充。
-算法流程如下:
-选择一个起始点作为种子点,将该点填充上颜色;
-判断该种子点的相邻像素是否需要填充,如果需要则将其填充;
-一直延伸填充,直到整个区域被填充完毕。
-种子填充算法的优点是效率较高,能够处理较大的区域,但是需要选择合适的填充规则,否则可能会导致填充区域不准确或者出现漏填的情况。
以上两种区域填充算法在实际应用中会根据具体的场景和需求选择合适的算法进行使用。
在实际实现时,还需要考虑一些特殊情况,如图像边界处理、扫描顺序等,以确保算法的正确性和效率。
计算机图形学四连通区域种子填充算法实验
![计算机图形学四连通区域种子填充算法实验](https://img.taocdn.com/s3/m/d6f99e50f121dd36a22d82c9.png)
《计算机图形学实验》报告任课教师:钱文华2016年春季学期实验:四连通区域种子填充算法实验时间:2016年12月8日实验地点:信息学院2204实验目的:掌握种子填充算法的原理,并会用种子填充算法和opengl并结合使用c++语言编写程序绘制多边形。
实验原理:种子填充算法又称为边界填充算法。
其基本思想是:从多边形区域的一个内点开始,由内向外用给定的颜色画点直到边界为止。
如果边界是以一种颜色指定的,则种子填充算法可逐个像素地处理直到遇到边界颜色为止.内点的检测条件:if(interiorColor!=borderColor&&interiorColor!=fillColor)。
种子填充算法常用四连通域和八连通域技术进行填充操作。
从区域内任意一点出发,通过上、下、左、右四个方向到达区域内的任意像素。
用这种方法填充的区域就称为四连通域;这种填充方法称为四向连通算法。
从区域内任意一点出发,通过上、下、左、右、左上、左下、右上和右下八个方向到达区域内的任意像素.用这种方法填充的区域就称为八连通域;这种填充方法称为八向连通算法。
一般来说,八向连通算法可以填充四向连通区域,而四向连通算法有时不能填充八向连通区域。
四向连通填充算法:a) 种子像素压入栈中;b) 如果栈为空,则转e);否则转c);c) 弹出一个像素,并将该像素置成填充色;并判断该像素相邻的四连通像素是否为边界色或已经置成多边形的填充色,若不是,则将该像素压入栈;d) 转b);e) 结束。
四连通填充算法利用到了递归的思想。
本实验只包括四连通填充算法程序代码:#include〈glut。
h>#include〈stdlib.h〉#include〈math。
h>#include〈windows。
h〉void init(void){ glClearColor(1。
0,1.0,1。
0,0。
0); glMatrixMode(GL_PROJECTION);gluOrtho2D(0。
基本图形处理技术-区域填充1扫描线种子填充
![基本图形处理技术-区域填充1扫描线种子填充](https://img.taocdn.com/s3/m/045d592f482fb4daa58d4b11.png)
• int CSampleseedfillView::stackpop() • { • int val; • val=stack[stack_top]; • stack_top=stack_top-1; • return val; • }
步骤5:编写扫描线填充算法
• void CSampleseedfillView::floodfill4(int x, int y, COLORREF oldcolor, COLORREF newcolor) { CDC * pDC=GetDC(); int xl,xr,x0,xnextspan,yu,yd; bool spanNeedFill; //将栈清空 setstackempty(); //种子入栈 stackpush(x); stackpush(y);
• • • • • • •
int CSampleseedfillView::isstackempty() { if (stack_top>0) return 1; else return 0; }
• void CSampleseedfillView::stackpush(int p_xy) • { • stack_top+=1; • stack[stack_top]=p_xy; • }
• 步骤3:在构造函数中,对变量和栈初始化; CSampleseedfillView::CSampleseedfillView() { // TODO: add construction code here stack_top=0; FillColor=RGB(0,0,0); }
• 步骤4:编写成员函数程序 void CSampleseedfillView::setstackempty() { int i; for(i=0;i<=stack_top;i++) stack[i]=0; stack_top=0; }
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三区域填充种子算法实现
实验目的:
1、熟练在Visual C++中程序实现及调试的能力。
2、通过程序的设计熟练区域填充种子算法过程;
3、掌握堆栈在数据结构中的应用
实验内容:
1、visual c++中菜单的修改,点的输入及鼠标函数的控制;
2、复习数据结构中堆栈的建立,入栈,出栈等函数;
3、实现整个多边形的区域填充种子算法,与扫描转换算法进行区分;
实验步骤:
预处理:多边形点列的输入,存储于数组中P[100],种子点的输入,确定为point(x,y)
确定多边形的边界色(旧画笔色),初始色(背景色),填充色(新画笔色);
数据结构的建立:建立堆栈,包括数组stack[100],及一个指标top,用来指向当前堆栈的最外面的栈口的元素。
步骤:1、堆栈置为空,top=0;
2、将初始的种子点point进栈,push(x,y);
3、填色堆栈非空即top>0时,一直循环下列步骤
取栈顶的元素,出栈pop(x,y),savex=x;
从当前点开始沿当前扫描线往右检验,若有未填新色的,则填色。
然后同样往左检验。
当前扫描线俩个方向都检查完后,检验上一条扫描线y=y+1; 若有未填新色的,则把所有未填新色区间的右端点压入堆栈。
同理检验下一条扫描线y=y-2;
实验指导:
一、 在实验二的基础上进行编程 ;
(1) 引入实验二代码
scanline.dsw
二、 编辑菜单资源
选中窗口左边栏的“ResourceView ”,其中的“Menu ”,双击“IDR_MAINFRAME ”,右边即为菜单,在菜单上空处双击,出项如图所示窗口,其中弹出不选中;
如上,同样创建其余菜单项。
(如下表);
三、 添加消息处理函数
由菜单的“查看”,“建立类向导”,打开ClassWizard (也可CTRL+W )为应用程序添加与菜单项相关的消息处理函数,ClassName 栏选中CScanLineView 类,根据表建立。
输入菜单项名称,(如显示多边形)
双击,出现如下窗口
四、 程序结构代码 1、
添加全局变量
在CScanLineView.h 文件中相应位置添加如下代码:(红体为需加入代码)
// Implementation public:
CPoint P[100], pt, stack[100]; int top, flag , num ;
说明: pt 定义为全局变量,为种子点坐标; stack[100]为堆栈;
top 为堆栈的最外的元素的位子; flag 为指标,判别flag=1时鼠标左键按下可
取种子点。
2、 调用函数的建立。
如下图所示,右键点击左边栏的CScanLineView 类,选中“Add Member Function ”
;
出现如下所示窗口,
按下列表格重复输入函数,后确定;
3、主程序生成,在CScanLineView.cpp文件相应位置添加如下代
码。
(注意大小写,及符号)
文件最上面一长串蓝体字下面加入:
#define oldcolor RGB(0,0,0)
#define newcolor RGB(255,0,0)
CScanLineView::CScanLineView()
{
num=0;
flag=0;
}
void CScanLineView::OnLButtonDown(UINT nFlags, CPoint point) //鼠标映射函数{
CDC *pdc=GetDC();
if(flag==1) { pt=point;
pdc->FillSolidRect(point.x-3,point.y-3,3,3,newcolor);
flag=0; num=0;
}
else { num++; P[num]=point;
pdc->FillSolidRect(point.x-3,point.y-3,3,3,oldcolor);
if(num!=1) { pdc->MoveTo(P[num-1]); pdc->LineTo(point); }
}
CView::OnLButtonDown(nFlags, point);
}
/////////////////////
void CScanLineView::OnScanLine()
{
CDC *pdc=GetDC();
书中P29页代码;
}
void CScanLineView::setstackempty()
{
top=0;
}
void CScanLineView::stackpush(seed pt)
{
stack[top+1]=pt;
top++;
}
bool CScanLineView::isstackempty()
{
if(top==0) return TRUE;
else return FALSE;
}
void CScanLineView::stackpop()
{
pt=stack[top];
top--;
}
void CScanLineView::Ongetseed()
{
flag=1;
}
说明:书29页代码中,所有的drawpixel改为pdc->SetPixel 画笔使用:
CPen RenPen,*OldPen;
RedPen.CreatePen(PS_SOLID,1,RGB(255,0,0));
OldPen=pdc->SetlectObject(&RedPen);
…….
Pdc->SellectObject(OldPen);
RedPen.DelectObject();
VC中自带的多边形填充函数pdc->Polygon(…);。