区域标记算法
cndg 2006-4-15
这里介绍区域标记算法,所谓区域标记就是把连续区域作同一个标记,常见的四邻域标记算法和八邻域标记算法。现在就介绍它们的基本思想。
1、 四邻域标记算法:
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;
}