基于8临域的边界跟踪代码.docx
《基于8临域的边界跟踪代码.docx》由会员分享,可在线阅读,更多相关《基于8临域的边界跟踪代码.docx(13页珍藏版)》请在冰豆网上搜索。
![基于8临域的边界跟踪代码.docx](https://file1.bdocx.com/fileroot1/2022-12/7/440e997a-cad8-4550-8f6c-5dc3d8a2ee7a/440e997a-cad8-4550-8f6c-5dc3d8a2ee7a1.gif)
基于8临域的边界跟踪代码
#include
#include
#defineNumberOfPossiblePoints64
#defineSize_of_Array8
voidmain()
{
intf[Size_of_Array][Size_of_Array]=
{0,0,0,0,0,0,0,0,
0,0,1,1,0,0,0,0,
0,0,1,1,0,0,0,0,
0,1,1,1,1,0,0,0,
0,0,1,1,1,1,0,0,
0,0,1,1,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
intborder[Size_of_Array][Size_of_Array];//也用0,1表示,border数组记录行走的轨迹;
int
trace[NumberOfPossiblePoints][2];
//还需要使用一个二为维数组依次记录行走的坐标
intchaincode[NumberOfPossiblePoints];//存储方向码
intdir;
inti,j;
intflag;
intcount;
intp0x,p0y;//初始点坐标
intp1x,p1y;//记录找到的第二个点的坐标
intpn_1x,pn_1y,pnx,pny;//用来记录目标坐标
//Initializationforsomearrays:
for(i=0;i{
chaincode[i]=0;
for(j=0;j<2;j++)
trace[i][j]=0;
}
//begin,let'sfirstlookattheoriginaldataand,atthesametime,clearborderarray:
for(i=0;i{
for(j=0;j{
cout<border[i][j]=0;
}
cout<}
count=0;
flag=1;
dir=7;//根据算法,确定首先查找下一个边界点的方向
//findtheinitialpoint(pixel)whosevalueisnotzero.
p0x=1;p0y=2;
i=p0x;
j=p0y;
border[i][j]=1;
trace[count][0]=i;trace[count][1]=j;
//repeat
//为了使循环正常进行下去,必须要求行走的步数超过1,否则由于
//第一步找到p0,p1点后,由于这是对于最后pn-1,pn点赋值为p0和p1的坐标,循环退出。
//在while循环条件中增加对于count的判断,当count小于2的时候,不应该结束。
while
(count<2||(pn_1x!
=p0x)||(pn_1y!
=p0y)||(pnx!
=p1x)||(pny!
=p1y))
{
//记录行走的坐标,进行do-while循环的结束条件判断使用
//如果记录的边界点为:
p0,p1,....pn-1,pn(假如有n+1个边界点,p0为初始点,n>=2)
//则:
当pn-1==p0,同时pn==p1时结束边界跟踪
//
pn_1x=i;//记录倒数第二个点的i坐标
pn_1y=j;//记录倒数第二个点的j坐标
if(dir%2==0)
dir=(dir+7)%8;
else
dir=(dir+6)%8;
switch(dir)//根据当前的方向dir确定该方向的新的坐标i,j
{
case0:
{j=j+1;break;}
case1:
{i=i-1;j=j+1;break;}
case2:
{i=i-1;break;}
case3:
{i=i-1;j=j-1;break;}
case4:
{j=j-1;break;}
case5:
{i=i+1;j=j-1;break;}
case6:
{i=i+1;break;}
case7:
{i=i+1;j=j+1;break;}
}
//判断dir方向指向的点是否为1,如果不为1,要按逆时针方向增加方向码dir的数值;
while(f[i][j]!
=1)
{
//
dir=(dir+1)%8;
i=pn_1x;
j=pn_1y;//坐标复原,以便重新根据当前增加的方向码决定该方向的坐标i,j;
switch(dir)//根据当前的方向dir确定该方向的新的坐标i,j
{
case0:
{j=j+1;break;}
case1:
{i=i-1;j=j+1;break;}
case2:
{i=i-1;break;}
case3:
{i=i-1;j=j-1;break;}
case4:
{j=j-1;break;}
case5:
{i=i+1;j=j-1;break;}
case6:
{i=i+1;break;}
case7:
{i=i+1;j=j+1;break;}
}
}
if(flag==1)//这个判断只进行一次,以后由于标记flag改变,就不再需要记录了。
{
p1x=i;
p1y=j;
//pnx=i;
//pny=j;
flag=0;
}
count=count+1;
border[i][j]=1;//border数组记录行走的轨迹;
//还需要使用一个二为维数组依次记录行走的坐标
trace[count][0]=i;trace[count][1]=j;
//当前坐标,作为while结束条件判断
pnx=i;
pny=j;
//存储方向码
chaincode[count-1]=dir;
//cout<"<}
cout<<"共计"<//画出表示边界的矩阵
cout<<"表示边界的矩阵:
"<for(i=0;i{
for(j=0;jcout<cout<}
//输出边界跟踪的初始点坐标位置:
cout<<"边界跟踪的初始点坐标位置:
("<//输出表示边界的方向码:
for(i=0;icout<cout<//输出表示边界的坐标:
cout<<"输出表示边界的坐标"<for(i=0;icout<<"("<cout<}
/*八邻域边界跟踪算法
利用点的八邻域信息,
选择下一个点作为边界点,
这个算法需要选择一个开始点,
可以选择图像上是目标点,在最上,最左的点。
然后查看它的八邻域的点,从右
下方
45°的位置开始寻找,如果是目标点,将沿顺时针
90°作为下一次寻找的
方向,如果不是,则逆时针
45°继续寻找,一旦找到重复上面的过程。
*/
voidVessDibTrack(HDIBhdib,vector&pt)//八邻域
{
unsignedchar*lpSrc;
LPSTRlpDIB=(LPSTR):
:
GlobalLock((HGLOBAL)hdib);
intcxDIB=(int):
:
DIBWidth(lpDIB);//SizeofDIB-x
intcyDIB=(int):
:
DIBHeight(lpDIB);//SizeofDIB-y
LPSTRlpDIBBits=:
:
FindDIBBits(lpDIB);
longlLineBytes=WIDTHBYTES(cxDIB*8);//计算图像每行的字节数
//寻找开始点,最右,最下
//先行,后列
inti,j;
POINTstartPt,currPt;
for(i=0;i{
for(j=0;j{
lpSrc=(unsignedchar*)lpDIBBits+
lLineBytes*(cyDIB-1-i)+j;
if(*lpSrc==0)//是黑点
{
startPt.x=i;
startPt.y=j;
//停止条件
i=cyDIB;
j=cxDIB;
}
}
}
//设置方向数组
//intdirection[8][2]={{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0}};
intdirection[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
intstartDirect
BOOLFindStartPoint=FALSE;
BOOLFindPoint=FALSE;
//开始跟踪
currPt.x=startPt.x;
currPt.y=startPt.y;
POINTNextPt
intNextPtValue;
startDirect=0;
intcnt=0;
while(!
FindStartPoint&&cnt<100000)
{
FindPoint=FALSE;
pt.push_back(currPt);
while(!
FindPoint)
{
//沿预定方向扫描,寻找下一个点
NextPt.x=currPt.x+direction[startDirect][1];
NextPt.y=currPt.y+direction[startDirect][0];
lpSrc=(unsignedchar*)lpDIBBits+lLineBytes*(cyDIB-1-NextPt.x)+NextPt.y;
//NextPtValue=GetPiexValue(hdib,NextPt.x,NextPt.y);
NextPtValue=*lpSrc;
if(NextPtValue==0&&NextPt.x>=0&&NextPt.x=0&&NextPt.y{
FindPoint=TRUE;
currPt.x=NextPt.x;
currPt.y=NextPt.y;
if(currPt.x==startPt.x&&currPt.y==startPt.y)
{
FindStartPoint=TRUE;
}
startDirect=startDirect-2;
if(startDirect<0)startDirect=startDirect+8;
}
else
{
startDirect=startDirect+1;
if(startDirect>=8)startDirect=startDirect-8;
}
}
cnt++;
}
:
:
GlobalUnlock((HGLOBAL)hdib);
}
//于八方向链码的边界跟踪代码,其中nVerct数组存储的是边界点的矢量方向,Coordinate存储的是边界点的坐标。
BOOLCDib:
:
PickBoundary(BYTE*nVerct,int(*Coordinate)[2])
{
if(NULL==m_lpBits)
returnFALSE;
structEdgePoint
{
BYTEnCurrenVerct;//当前矢量,即在轮廓跟踪中的前一个搜索方向
CPointCurrenPoint;//当前点的坐标
};
//CArrayTraceArray;
//获取位图的宽,高,以及每行字节数
intnWidth=m_nWidth;
intnHeight=m_nHeight;
intnByteWidth=BYTE_PER_LINE(m_nWidth,m_nBitCount);
//循环变量
inti,j;
//开辟一块新的空间并初始化
BYTE*pData=newBYTE[nByteWidth*nHeight];
memset(pData,255,nByteWidth*nHeight);
//像素值
unsignedcharpixel;
//是否找到起始点及回到起始点
boolbFindStartPoint;
//是否扫描到一个边界点
boolbFindPoint;
typedefstruct
{
intWidth;
intHeight;
}Position;
//起始边界点与当前边界点
PositionStartPoint,CurrentPoint;
//八个方向和起始扫描方向,依次是左上方、上方、右上方、右方、右下方、下方、左下方和左方。
intDirection[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
intBeginDirect;
//先找到最左下方的边界点
bFindStartPoint=false;
for(j=1;jbFindStartPoint;j++)
{
for(i=1;ibFindStartPoint;i++)
{
//取得当前指针处的像素值
pixel=*(m_lpBits+nWidth*j+i);
if(pixel==0)
{
bFindStartPoint=true;
StartPoint.Height=j;
StartPoint.Width=i;
//指向目标图像倒数第j行,第i个象素的指针
*(pData+nWidth*j+i)=0;
}
}
}
//由于起始点是在左下方,故起始扫描沿左上方向
BeginDirect=0;
//跟踪边界
bFindStartPoint=false;
CurrentPoint.Height=StartPoint.Height;
CurrentPoint.Width=StartPoint.Width;
intindex=0;
memset(nVerct,0,9999);
while(!
bFindStartPoint)
{
//从起始点一直找边界,直到再次找到起始点为止
bFindPoint=false;
while(!
bFindPoint)
{
//沿扫描方向,这里是左上方向获取一个像素
pixel=*(m_lpBits+nWidth*(CurrentPoint.Height+Direction[BeginDirect][1])+
CurrentPoint.Width+Direction[BeginDirect][0]);
if(pixel==0)
{
bFindPoint=true;
//存储边界点的矢量方向
nVerct[index]=(BYTE)BeginDirect;
//存储边界点的坐标
Coordinate[index][0]=CurrentPoint.Width;
Coordinate[index][1]=CurrentPoint.Height;
index++;
CurrentPoint.Width=CurrentPoint.Width+Direction[BeginDirect][0];
CurrentPoint.Height=CurrentPoint.Height+Direction[BeginDirect][1];
//如果一圈以后找到了起始点,那么边界寻找完成
if(CurrentPoint.Height==StartPoint.Height&&
CurrentPoint.Width==StartPoint.Width)
{
bFindStartPoint=true;
}
//将轮廓在新的位图中标示出来
*(pData+nWidth*CurrentPoint.Height+CurrentPoint.Width)=0;
//扫描的方向逆时针旋转两格
//为什么?
因为逆时针旋转三格的象素绝对不是边界,不然当前点就不会是边界。
BeginDirect--;
if(BeginDirect==-1)
BeginDirect=7;
BeginDirect--;
if(BeginDirect==-1)
BeginDirect=7;
}
else
{
//扫描方向顺时针旋转一格
BeginDirect++;
if(BeginDirect==8)
BeginDirect=0;
}
}
}
//边界跟踪时,边界点数
m_nNumNode=index;
memcpy(m_lpBits,pData,nByteWidth*nHeight);
deletepData;
returnTRUE;
}