图像八方向链码的边界跟踪算法

源自:http://blog.sina.com.cn/s/blog_6b41baed0100nmps.html


//于八方向链码的边界跟踪代码,其中nVerct数组存储的是边界点的矢量方向,Coordinate存储的是边界点的坐标。
BOOL CDib::PickBoundary(BYTE* nVerct,int (*Coordinate)[2])
{
if(NULL == m_lpBits)
   return FALSE;

struct EdgePoint
{
   BYTE nCurrenVerct;        //当前矢量,即在轮廓跟踪中的前一个搜索方向
   CPoint CurrenPoint;       //当前点的坐标
};

//CArray <EdgePoint,EdgePoint&> TraceArray;

//获取位图的宽,高,以及每行字节数
int nWidth=m_nWidth;
int nHeight=m_nHeight;
int nByteWidth=BYTE_PER_LINE(m_nWidth,m_nBitCount);


//循环变量
int i,j;

//开辟一块新的空间并初始化
BYTE *pData=new BYTE[nByteWidth*nHeight];
memset(pData,255,nByteWidth*nHeight);

//像素值
unsigned char pixel;

//是否找到起始点及回到起始点
bool bFindStartPoint;

//是否扫描到一个边界点
bool bFindPoint;

typedef struct
{
   int Width;
   int Height;
}Position;

//起始边界点与当前边界点
Position StartPoint,CurrentPoint;

//八个方向和起始扫描方向,依次是左上方、上方、右上方、右方、右下方、下方、左下方和左方。
int Direction[8][2]={ {-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0} };
int BeginDirect;


//先找到最左下方的边界点
bFindStartPoint = false;
for (j = 1;j < nHeight-1 && !bFindStartPoint;j++)
{
   for(i = 1;i < nWidth-1 && !bFindStartPoint;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;

int index=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);
delete pData;

return TRUE;
}


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值