这里介绍区域标记算法,所谓区域标记就是把连续区域作同一个标记,常见的四邻域标记算法和八邻域标记算法。现在就介绍它们的基本思想。 1、 四邻域标记算法:
2) 如果此点四邻域中的最左有点,最上没有点,则标记此点为最左点的值;如果此点四邻域中的最左没有点,最上有点,则标记此点为最上点的值。 3) 如果此点四邻域中的最左有点,最上都有点,则标记此点为这两个中的最小的标记点,并修改大标记为小标记。 2、 八邻域标记算法: 1) 判断此点八邻域中的最左,左上,最上,上右点的情况。 如果都没有点,则表示一个新的区域的开始。 2) 如果此点八邻域中的最左有点,上右都有点,则标记此点为这两个中的最小的标记点,并修改大标记为小标记。 3) 如果此点八邻域中的左上有点,上右都有点,则标记此点为这两个中的最小的标记点,并修改大标记为小标记。 4) 否则按照最左,左上,最上,上右的顺序,标记此点为四个中的一个。 注意:在这个过程中也可以求出每个不同标记点的数量,矩形区域。
3、实例 /* l 函数说明:把I[off]的连续区域的标识为num,并求出其区域矩形 l 参数说明:I,为图像数组,off为坐标偏移量,num为标记,rect为标记的矩形范围 l 返回值:int,为标记是num的点数。 */ int FillAreaFlag(LPBYTE I,int off,int num,CRect& rect) { bool bNew; int m,n,i,j,k,nDot=1,offset,offtemp,yMin; int dxy[8],x,y; dxy[0]=-ImageWidth-1; dxy[1]=-ImageWidth; dxy[2]=-ImageWidth+1; dxy[3]=-1; dxy[4]=1; dxy[5]=ImageWidth-1; dxy[6]=ImageWidth; dxy[7]=ImageWidth+1;
rect.left=65535; rect.right=-1; rect.bottom=65535; rect.top=-1; if(I[off]>0 && I[off]!=num) { I[off]=num; x=off%ImageWidth; y=off/ImageWidth; if(x<rect.left) rect.left=x; if(x>rect.right) rect.right=x; if(y<rect.bottom) rect.bottom=y; if(y>rect.top) rect.top=y; } else return 0;
for(i=y; i<ImageHeight; i++) { bNew=false; yMin=i; for(j=0; j<ImageWidth; j++) { offset=i*ImageWidth+j; if(I[offset]==num) { for(k=0; k<8; k++) { if(i==0 && k<=2) continue; if(i==ImageHeight-1 && k>=5) continue; if(j==0 && (k==0 || k==3 || k==5)) continue; if(j==ImageWidth-1 && (k==2 || k==4 || k==7)) continue; offtemp=offset+dxy[k]; if(I[offtemp]>0 && I[offtemp]!=num) { I[offtemp]=num; nDot++; m=offtemp/ImageWidth; n=offtemp%ImageWidth; if(n < rect.left) rect.left=n; if(n > rect.right) rect.right=n; if(m < rect.bottom) rect.bottom=m; if(m > rect.top) rect.top=m; y=offtemp/ImageWidth; if(y<=yMin) { yMin=y; if(!bNew) bNew=true; } } } } } if(bNew) { i=yMin-1; } } return nDot; } |
区域标记算法
最新推荐文章于 2020-10-30 18:53:21 发布