基于8临域的边界跟踪代码Word文件下载.docx
《基于8临域的边界跟踪代码Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于8临域的边界跟踪代码Word文件下载.docx(13页珍藏版)》请在冰豆网上搜索。
i++)
chaincode[i]=0;
for(j=0;
j<
2;
j++)
trace[i][j]=0;
}
//begin,let'
sfirstlookattheoriginaldataand,atthesametime,clearborderarray:
for(i=0;
Size_of_Array;
{
cout<
<
setw(6)<
f[i][j];
border[i][j]=0;
}
endl;
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;
case2:
case3:
j=j-1;
case4:
{j=j-1;
case5:
{i=i+1;
j=j-1;
case6:
case7:
//判断dir方向指向的点是否为1,如果不为1,要按逆时针方向增加方向码dir的数值;
while(f[i][j]!
=1)
//
dir=(dir+1)%8;
i=pn_1x;
j=pn_1y;
//坐标复原,以便重新根据当前增加的方向码决定该方向的坐标i,j;
if(flag==1)//这个判断只进行一次,以后由于标记flag改变,就不再需要记录了。
p1x=i;
p1y=j;
//pnx=i;
//pny=j;
flag=0;
count=count+1;
border[i][j]=1;
//border数组记录行走的轨迹;
//还需要使用一个二为维数组依次记录行走的坐标
//当前坐标,作为while结束条件判断
pnx=i;
pny=j;
//存储方向码
chaincode[count-1]=dir;
//cout<
p0x<
"
"
p0y<
p1x<
p1y<
pn_1x<
pn_1y<
pnx<
pny<
共计"
count<
个链码"
//画出表示边界的矩阵
表示边界的矩阵:
for(i=0;
border[i][j];
//输出边界跟踪的初始点坐标位置:
cout<
边界跟踪的初始点坐标位置:
("
"
)"
//输出表示边界的方向码:
count;
setw(4)<
chaincode[count];
//输出表示边界的坐标:
输出表示边界的坐标"
i++)//没有输出最后一个点坐标
trace[i][0]<
trace[i][1]<
;
/*八邻域边界跟踪算法
利用点的八邻域信息,
选择下一个点作为边界点,
这个算法需要选择一个开始点,
可以选择图像上是目标点,在最上,最左的点。
然后查看它的八邻域的点,从右
下方
45°
的位置开始寻找,如果是目标点,将沿顺时针
90°
作为下一次寻找的
方向,如果不是,则逆时针
继续寻找,一旦找到重复上面的过程。
*/
voidVessDibTrack(HDIBhdib,vector<
POINT>
&
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);
//计算图像每行的字节数
//寻找开始点,最右,最下
//先行,后列
POINTstartPt,currPt;
for(i=0;
cyDIB;
++i)
for(j=0;
cxDIB;
++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<
cyDIB&
NextPt.y>
NextPt.y<
cxDIB)
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;
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;
//当前点的坐标
};
//CArray<
EdgePoint,EdgePoint&
>
TraceArray;
//获取位图的宽,高,以及每行字节数
intnWidth=m_nWidth;
intnHeight=m_nHeight;
intnByteWidth=BYTE_PER_LINE(m_nWidth,m_nBitCount);
//循环变量
//开辟一块新的空间并初始化
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;
j<
nHeight-1&
!
bFindStartPoint;
j++)
for(i=1;
i<
nWidth-1&
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;
//跟踪边界
CurrentPoint.Height=StartPoint.Height;
CurrentPoint.Width=StartPoint.Width;
intindex=0;
memset(nVerct,0,9999);
bFindStartPoint)
//从起始点一直找边界,直到再次找到起始点为止
bFindPoint=false;
bFindPoint)
//沿扫描方向,这里是左上方向获取一个像素
pixel=*(m_lpBits+nWidth*(CurrentPoint.Height+Direction[BeginDirect][1])+
CurrentPoint.Width+Direction[BeginDirect][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)
//将轮廓在新的位图中标示出来
*(pData+nWidth*CurrentPoint.Height+CurrentPoint.Width)=0;
//扫描的方向逆时针旋转两格
//为什么?
因为逆时针旋转三格的象素绝对不是边界,不然当前点就不会是边界。
BeginDirect--;
if(BeginDirect==-1)
BeginDirect=7;
else
//扫描方向顺时针旋转一格
BeginDirect++;
if(BeginDirect==8)
BeginDirect=0;
//边界跟踪时,边界点数
m_nNumNode=index;
memcpy(m_lpBits,pData,nByteWidth*nHeight);
deletepData;
returnTRUE;