【编程】图像的轮廓提取和跟踪算法(转贴)

终于可以睡觉鸟啊,写一个函数写了那么久,55555
编程真的不好受啊,特意帖出来作为留念,oh yeah
^_^,这个也是【原创】的,发在这里合适吧
 
BOOL WINAPI EdgeDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
 // 指向源图像的指针
 LPSTR lpSrc;
 
 // 指向缓存图像的指针
 LPSTR lpDst;
 
 // 指向缓存DIB图像的指针
 LPSTR lpNewDIBBits;
 HLOCAL hNewDIBBits;
 //循环变量
 long i;
 long j;
 unsigned char n,e,s,w,ne,se,nw,sw;
 //像素值
 unsigned char pixel;
 // 图像每行的字节数
 LONG lLineBytes;
 // 计算图像每行的字节数
 lLineBytes = WIDTHBYTES(lWidth * 8);
 
//==================================对图像进行轮廓提取================================
 // 暂时分配内存,以保存新图像
 hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
 if (hNewDIBBits == NULL)
 {
  // 分配内存失败
  return FALSE;
 }
 
 // 锁定内存
 lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
 // 初始化新分配的内存,设定初始值为255
 lpDst = (char *)lpNewDIBBits;
 memset(lpDst, (BYTE)255, lLineBytes * lHeight);
 for(j = 1; j  {
  for(i = 1;i   {
   
   // 指向源图像倒数第j行,第i个象素的指针   
   lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
   
   // 指向目标图像倒数第j行,第i个象素的指针   
   lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
   
   //取得当前指针处的像素值,注意要转换为unsigned char型
   pixel = (unsigned char)*lpSrc;
   //目标图像中非白的像素值全部变成黑色
   if(pixel != 255)
    *lpSrc = (unsigned char)0;

  }
 }

 for(j = 1; j  {
  for(i = 1;i   {
   
   // 指向源图像倒数第j行,第i个象素的指针   
   lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
   
   // 指向目标图像倒数第j行,第i个象素的指针   
   lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
   
   //取得当前指针处的像素值,注意要转换为unsigned char型
   pixel = (unsigned char)*lpSrc;

   if(pixel == 0)
   {
    *lpDst = (unsigned char)0;
    nw = (unsigned char)*(lpSrc + lLineBytes -1);
    n  = (unsigned char)*(lpSrc + lLineBytes );
    ne = (unsigned char)*(lpSrc + lLineBytes +1);
    w = (unsigned char)*(lpSrc -1);
    e = (unsigned char)*(lpSrc +1);
    sw = (unsigned char)*(lpSrc - lLineBytes -1);
    s  = (unsigned char)*(lpSrc - lLineBytes );
    se = (unsigned char)*(lpSrc - lLineBytes +1);
    //如果相邻的八个点都是黑点
    if(nw+n+ne+w+e+sw+s+se==0)
    {
     *lpDst = (unsigned char)255;
    }                             
   }
  }
 }
 // 复制腐蚀后的图像
 memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
 // 释放内存
 LocalUnlock(hNewDIBBits);
 LocalFree(hNewDIBBits);
 

//==================================对图像进行轮廓跟踪================================

        //是否找到起始点及回到起始点
 bool bFindStartPoint;
 //是否扫描到一个边界点
 bool bFindPoint;
 //起始边界点与当前边界点
 Point StartPoint,CurrentPoint;
 //八个方向和起始扫描方向
 int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
 int BeginDirect;
 // 暂时分配内存,以保存新图像
 hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
 if (hNewDIBBits == NULL)
 {
  // 分配内存失败
  return FALSE;
 }
 
 // 锁定内存
 lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
 // 初始化新分配的内存,设定初始值为255
 lpDst = (char *)lpNewDIBBits;
 memset(lpDst, (BYTE)255, lLineBytes * lHeight);
 //先找到最左上方的边界点
 bFindStartPoint = false;
 for (j = 0;j < lHeight && !bFindStartPoint;j++)
 {
  for(i = 0;i < lWidth && !bFindStartPoint;i++)
  {
   // 指向源图像倒数第j行,第i个象素的指针   
   lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
   
   //取得当前指针处的像素值,注意要转换为unsigned char型
   pixel = (unsigned char)*lpSrc;
   
   if(pixel == 0)
   {
    bFindStartPoint = true;
    StartPoint.Height = j;
    StartPoint.Width = i;
    // 指向目标图像倒数第j行,第i个象素的指针   
    lpDst = (char *)lpNewDIBBits + lLineBytes * j + i; 
    *lpDst = (unsigned char)0;
   }  
  }
 }
 //由于起始点是在左下方,故起始扫描沿左上方向
 BeginDirect = 0;
 //跟踪边界
 bFindStartPoint = false;
 //从初始点开始扫描
 CurrentPoint.Height = StartPoint.Height;
 CurrentPoint.Width = StartPoint.Width;
 while(!bFindStartPoint)
 {
  bFindPoint = false;
  while(!bFindPoint)
  {
   //沿扫描方向查看一个像素
   lpSrc = (char *)lpDIBBits + lLineBytes* ( CurrentPoint.Height + Direction[BeginDirect][1])
    + (CurrentPoint.Width + Direction[BeginDirect][0]);
   pixel = (unsigned char)*lpSrc;
   if(pixel == 0)
   {
    bFindPoint = true;
    CurrentPoint.Height = CurrentPoint.Height + Direction[BeginDirect][1];
    CurrentPoint.Width = CurrentPoint.Width + Direction[BeginDirect][0];
    if(CurrentPoint.Height == StartPoint.Height && CurrentPoint.Width == StartPoint.Width)
    {
     bFindStartPoint = true;
    }
    lpDst = (char *)lpNewDIBBits + lLineBytes* CurrentPoint.Height + CurrentPoint.Width;
    *lpDst = (unsigned char)0;
    //扫描的方向逆时针旋转两格
    BeginDirect--;
    if(BeginDirect == -1)
     BeginDirect = 7;
    BeginDirect--;
    if(BeginDirect == -1)
     BeginDirect = 7;
   }
   else
   {
    //扫描方向顺时针旋转一格
    BeginDirect++;
    if(BeginDirect == 8)
     BeginDirect = 0;
   }
  }
 }
 // 复制腐蚀后的图像
 memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
 // 释放内存
 LocalUnlock(hNewDIBBits);
 LocalFree(hNewDIBBits);
 

 // 返回
 return TRUE; 
}
 

你可能感兴趣的:(【编程】图像的轮廓提取和跟踪算法(转贴))