EDN首页   博客首页

日志档案

发表于 2008-8-30 15:15:32

1

标签: 无标签

轮廓检测

源程序如下,其中函数IsContourP用来判断某点是不是边界点。
BOOL Contour(HWND hWnd)
{
 DWORD                 OffBits,BufSize;
    LPBITMAPINFOHEADER  lpImgData;
 LPSTR                   lpPtr;
 HLOCAL                 hTempImgData;
 LPBITMAPINFOHEADER   lpTempImgData;
 LPSTR                   lpTempPtr;
 HDC                     hDc;
 HFILE                   hf;
 LONG                   x,y;
 POINT                   StartP,CurP;
 BOOL                    found;
 int                       i;
 int                  direct[8][2]={{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},
{-1,1},{0,1},{1,1}};

//我们处理的实际上是256级灰度图,不过只用到了0和255两种颜色。
 if( NumColors!=256){
     MessageBox(hWnd,"Must be a mono bitmap with grayscale palette!","Error Message",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;
}
//到位图数据的偏移值
 OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);
 //缓冲区大小
 BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
//为新图缓冲区分配内存
 if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)
    {
     MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|
MB_ICONEXCLAMATION);
        return FALSE;
    }
    lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);   
 lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);
 //新图缓冲区初始化为255
 memset(lpTempImgData,(BYTE)255,BufSize);
 //拷贝头信息
 memcpy(lpTempImgData,lpImgData,OffBits);
 //找到标志置为假
 found=FALSE;
 for (y=0;y<bi.biHeight && !found; y++){
  lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);
  for (x=0;x<bi.biWidth && !found; x++)
   if (*(lpPtr++) ==0) found="TRUE"; //找到了最左上的黑点,一定是个边界点
 }
 if(found){ //如果找到了,才做处理
//从上面的循环退出时,x,y坐标都做了加1的操作。在这里把它们减1,得到起
//始点坐标StartP
  StartP.x=x-1;
  StartP.y=y-1;
  lpTempPtr=(char *)lpTempImgData+(BufSize-
LineBytes-StartP.y*LineBytes)+StartP.x;
  *lpTempPtr=(unsigned char)0; //起始点涂黑
  //右邻点
     CurP.x=StartP.x+1;
  CurP.y=StartP.y;
  lpPtr=(char *)lpImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
  if(*lpPtr!=0){ //若右邻点为白,则找右下邻点
      CurP.x=StartP.x+1;
   CurP.y=StartP.y+1;
   lpPtr=(char *)lpImgData+(BufSize-LineBytes-CurP.y*LineBytes)+CurP.x;
   if(*lpPtr!=0){ //若仍为白,则找下邻点
       CurP.x=StartP.x;
    CurP.y=StartP.y+1;
   }
  else{ //若仍为白,则找左下邻点
       CurP.x=StartP.x-1;
    CurP.y=StartP.y+1;
   }
  }
  while (! ( (CurP.x==StartP.x) &&(CurP.y==StartP.y))){
//知道找到起始点,循环才结束
   lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes
-CurP.y*LineBytes)+CurP.x;
   *lpTempPtr=(unsigned char)0;
   for(i=0;i<8;i++){
//按右,右上,上,左上,左,左下,下,右下的顺序找相邻点
//direct[i]中存放的是该方向x,y的偏移值
    x=CurP.x+direct[i][0];
    y=CurP.y+direct[i][1];
  //lpPtr指向原图数据,lpTempPtr指向新图数据
    lpTempPtr=(char *)lpTempImgData
+(BufSize-LineBytes-y*LineBytes)+x;
    lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+x;
    if( ( (*lpPtr==0)&&(*lpTempPtr!=0) ) ||
( (x==StartP.x) &&(y==StartP.y)))
    //原图中为黑点,且新图中为白点(表示还没搜索过)时才处理
    //另一种可能是找到了起始点
     if(IsContourP(x,y,lpPtr)){ //若是个边界点
      //记住当前点的位置
         CurP.x=x;
      CurP.y=y;
      break;
     }
   }
  }
 }
    if(hBitmap!=NULL)
     DeleteObject(hBitmap);
 hDc=GetDC(hWnd);
 //创立一个新的位图
 hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,
  (LONG)CBM_INIT,(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +
  NumColors*sizeof(RGBQUAD),(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);
 hf=_lcreat("c:\\contour.bmp",0);
 _lwrite(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));
 _lwrite(hf,(LPSTR)lpTempImgData,BufSize);
 _lclose(hf);
 //释放内存和资源
  ReleaseDC(hWnd,hDc);
 LocalUnlock(hTempImgData);
 LocalFree(hTempImgData);
 GlobalUnlock(hImgData);
 return TRUE;
}
//判断某点是不是边界点,参数x,y 为该点的坐标,lpPtr为指向原位图数据的指针
BOOL IsContourP(LONG x,LONG y, char *lpPtr)
{
 int     num,n,w,e,s;
 n=(unsigned char)*(lpPtr+LineBytes); //上邻点
 w=(unsigned char)*(lpPtr-1); //左邻点
 e=(unsigned char)*(lpPtr+1); //右邻点
 s=(unsigned char)*(lpPtr-LineBytes); //下邻点
 num=n+w+e+s;
 if(num==0) //全是黑点,说明是个内部点而不是边界点
  return FALSE;
 return TRUE;
}

系统分类: 资源共享   |   用户分类: 编程技术   |   来源: 转贴   |   【推荐给朋友】   |   【添加到收藏夹】

    阅读(166)    回复(0)  

投一票您将和博主都有获奖机会!