小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

種子填充-區(qū)域增長(zhǎng)算法

 啟蒙彩魂 2011-04-05
區(qū)域增長(zhǎng)的算法實(shí)現(xiàn): 1)根據(jù)圖像的不同應(yīng)用選擇一個(gè)或一組種 子,它或者是最亮或最暗的點(diǎn),或者是位 于點(diǎn)簇中心的點(diǎn) 2...通過(guò)像素集合的區(qū)域增長(zhǎng) 算法實(shí)現(xiàn): 區(qū)域A 區(qū)域B 種子像素增長(zhǎng).3)增長(zhǎng)的規(guī)則 4)
結(jié)束條件.

*************************************************************************
*
* \\函數(shù)名稱:
*   RegionGrow()
*
* \\輸入?yún)?shù):
*   CDib * pDib     - 指向CDib類的指針,含有原始圖象信息
*   unsigned char * pUnRegion  - 指向區(qū)域生長(zhǎng)結(jié)果的指針
*
* \\返回值:
*   無(wú)
*
* \\說(shuō)明:
*   pUnRegion指針指向的數(shù)據(jù)區(qū)存儲(chǔ)了區(qū)域生長(zhǎng)的結(jié)果,其中1(邏輯)表示
*  對(duì)應(yīng)象素為生長(zhǎng)區(qū)域,0表示為非生長(zhǎng)區(qū)域
*   區(qū)域生長(zhǎng)一般包含三個(gè)比較重要的問(wèn)題:
*  1. 種子點(diǎn)的選取
*  2. 生長(zhǎng)準(zhǔn)則
*  3. 終止條件
*  可以認(rèn)為,這三個(gè)問(wèn)題需要具體分析,而且每個(gè)問(wèn)題解決的好壞直接關(guān)系到
*  區(qū)域生長(zhǎng)的結(jié)果。
*  本函數(shù)的種子點(diǎn)選取為圖像的中心,生長(zhǎng)準(zhǔn)則是相鄰象素的象素值小于
*  nThreshold, 終止條件是一直進(jìn)行到再?zèng)]有滿足生長(zhǎng)準(zhǔn)則需要的象素時(shí)為止
*
*************************************************************************
*/
void RegionGrow(CDib * pDib, unsigned char * pUnRegion, int nThreshold)
{
 static int nDx[]={-1,0,1,0};
 static int nDy[]={0,1,0,-1};
 // 遍歷圖象的縱坐標(biāo)
// int y;
 // 遍歷圖象的橫坐標(biāo)
// int x;
 // 圖象的長(zhǎng)寬大小
 CSize sizeImage  = pDib->GetDimensions();
 int nWidth   = sizeImage.cx  ;
 int nHeight   = sizeImage.cy  ;
 // 圖像在計(jì)算機(jī)在存儲(chǔ)中的實(shí)際大小
 CSize sizeImageSave = pDib->GetDibSaveDim();
 // 圖像在內(nèi)存中每一行象素占用的實(shí)際空間
 int nSaveWidth = sizeImageSave.cx;
 // 初始化
 memset(pUnRegion,0,sizeof(unsigned char)*nWidth*nHeight);
 // 種子點(diǎn)
 int nSeedX, nSeedY;
 // 設(shè)置種子點(diǎn)為圖像的中心
 nSeedX = nWidth /2 ;
 nSeedY = nHeight/2 ;
 // 定義堆棧,存儲(chǔ)坐標(biāo)
 int * pnGrowQueX ;
 int * pnGrowQueY ;
 
 // 分配空間
 pnGrowQueX = new int [nWidth*nHeight];
 pnGrowQueY = new int [nWidth*nHeight];
 // 圖像數(shù)據(jù)的指針
 unsigned char *  pUnchInput =(unsigned char * )pDib->m_lpImage;
 
 // 定義堆棧的起點(diǎn)和終點(diǎn)
 // 當(dāng)nStart=nEnd, 表示堆棧中只有一個(gè)點(diǎn)
 int nStart ;
 int nEnd   ;
 //初始化
 nStart = 0 ;
 nEnd   = 0 ;
 // 把種子點(diǎn)的坐標(biāo)壓入棧
 pnGrowQueX[nEnd] = nSeedX;
 pnGrowQueY[nEnd] = nSeedY;
 // 當(dāng)前正在處理的象素
 int nCurrX ;
 int nCurrY ;
 // 循環(huán)控制變量
 int k ;
 // 圖象的橫縱坐標(biāo),用來(lái)對(duì)當(dāng)前象素的4鄰域進(jìn)行遍歷
 int xx;
 int yy;
 while (nStart<=nEnd)
 {
  // 當(dāng)前種子點(diǎn)的坐標(biāo)
  nCurrX = pnGrowQueX[nStart];
  nCurrY = pnGrowQueY[nStart];    
  // 對(duì)當(dāng)前點(diǎn)的4鄰域進(jìn)行遍歷
  for (k=0; k<4; k++)
  {
   // 4鄰域象素的坐標(biāo)
   xx = nCurrX+nDx[k];
   yy = nCurrY+nDy[k];
  
   // 判斷象素(xx,yy) 是否在圖像內(nèi)部
   // 判斷象素(xx,yy) 是否已經(jīng)處理過(guò)
   // pUnRegion[yy*nWidth+xx]==0 表示還沒(méi)有處理
   // 生長(zhǎng)條件:判斷象素(xx,yy)和當(dāng)前象素(nCurrX,nCurrY) 象素值差的絕對(duì)值
   if ( (xx < nWidth) && (xx>=0) && (yy<nHeight) && (yy>=0)
        && (pUnRegion[yy*nWidth+xx]==0)  && abs(pUnchInput[yy*nSaveWidth+xx] - pUnchInput[nCurrY*nSaveWidth+nCurrX])<nThreshold )
   {
    // 堆棧的尾部指針后移一位
    nEnd++;
    // 象素(xx,yy) 壓入棧
    pnGrowQueX[nEnd] = xx;
    pnGrowQueY[nEnd] = yy;
    // 把象素(xx,yy)設(shè)置成邏輯1(255)
    // 同時(shí)也表明該象素處理過(guò)
    pUnRegion[yy*nWidth+xx] = 255 ;
   }
  }
  nStart++;
 }
 // 釋放內(nèi)存
 delete []pnGrowQueX;
 delete []pnGrowQueY;
    pnGrowQueX = NULL ;
 pnGrowQueY = NULL ;
}

對(duì)于2D圖象的組織增長(zhǎng),使用遞歸也是一種不錯(cuò)的選擇,但需要注意??臻g需要設(shè)大一些。
而在3D數(shù)據(jù)場(chǎng)上,遞歸幾乎是不可行的,棧空間經(jīng)常會(huì)出現(xiàn)溢出的情況,因此不具備實(shí)用性。
2D組織增長(zhǎng)偽代碼如下
組織增長(zhǎng)(Image* pImage, int i, ing j, byte* mask)
{
   if 不滿足增長(zhǎng)條件(pImage, i,j, mask)
       return;
   設(shè)置標(biāo)記(mask, i, j);
   組織增長(zhǎng)(pImage, i-1, j, mask);
   組織增長(zhǎng)(pImage, i+1, j, mask);
   組織增長(zhǎng)(pImage, i, j-1, mask);
   組織增長(zhǎng)(pImage, i, j+1, mask);
}
至于將遞歸程序改為迭代程序,可以看一看《程序設(shè)計(jì)方法學(xué)》
區(qū)域增長(zhǎng)算法遞歸實(shí)現(xiàn)
void RegionGrowTwo(int nSeedX, int nSeedY, BYTE * pUnchInput,BYTE * D, int nWidth, int nHeight, BYTE * pUnRegion,int &iLeft,int & iRight,int & iTop,int & iBottom)
{
  int nDx[] = {-1,1,0,0};
 int nDy[] = {0,0,-1,1}; 
 int k=0;
 int nCurrX ;
 int nCurrY ;
 int xx=0,yy=0;
 nCurrX = nSeedX;
 nCurrY = nSeedY;
 if(nCurrX<iLeft)
  iLeft = nCurrX;
 if(nCurrX>iRight)
  iRight = nCurrX;
 if(nCurrY<iTop)
  iTop = nCurrY;
 if(nCurrY>iBottom)
  iBottom = nCurrY;
 
//  pUnRegion[nCurrY*nWidth+nCurrX] = 255 ;
     // 對(duì)當(dāng)前點(diǎn)的4鄰域進(jìn)行遍歷
     int times = 0;
  for (k=0; k<4; k++)
  {
   // 4鄰域象素的坐標(biāo)
   xx = nCurrX+nDx[k];
   yy = nCurrY+nDy[k];
   // 判斷象素(xx,yy) 是否在圖像內(nèi)部
   // 判斷象素(xx,yy) 是否已經(jīng)處理過(guò)
   // pUnRegion[yy*nWidth+xx]==0 表示還沒(méi)有處理
   // 生長(zhǎng)條件:判斷象素(xx,yy)和當(dāng)前象素(nCurrX,nCurrY) 象素值差的絕對(duì)值
   if ( (xx < nWidth) && (xx>=0) && (yy>=0) && (yy<nHeight)
   && (pUnRegion[yy*nWidth+xx]==0) && (pUnchInput[yy*nWidth+xx]==1))
   {
    // 同時(shí)也表明該象素處理過(guò)
    pUnRegion[yy*nWidth+xx] = 255 ;
    if(xx<iLeft)
     iLeft = xx;
    if(xx>iRight)
     iRight = xx;
    if(yy<iTop)
     iTop = yy;
    if(yy>iBottom)
     iBottom = yy;
                
    RegionGrowTwo(xx,yy,pUnchInput,D,nWidth,nHeight,pUnRegion,iLeft,iRight,iTop,iBottom); 
   }
   else
    times++;
  }
}
/*
*  區(qū)域增長(zhǎng),遞歸實(shí)現(xiàn)
* S,源圖象
  D,目標(biāo)圖象
 ImageWidth,ImageHeight,表示圖象的寬、高
*/
void  RegionGrowOne(BYTE *S,BYTE *D,int ImageWidth,int ImageHeight)
{
 int iLeft=0,iRight=0,iTop=0,iBottom=0;
 int k1,k2,k3,k4,ii1=0,off=0;
 int i=0,j=0;
 LPBYTE lpFlag = new BYTE[ImageWidth*ImageHeight];
 memset(lpFlag,0,ImageWidth*ImageHeight);
 memcpy(D,S,ImageWidth*ImageHeight);
 for (i=0; i<ImageHeight; i++)
 {
  for (j=0; j<ImageWidth; j++)
  {
   if (S[i*ImageWidth+j] == 1 && lpFlag[i*ImageWidth+j] == 0)
   {
    iLeft=65535,iRight=0,iTop=65535,iBottom=0;
    RegionGrowTwo(j,i,S,D,ImageWidth,ImageHeight,lpFlag,iLeft,iRight,iTop,iBottom);
    if((iRight-iLeft)>40 && (iBottom-iTop)>40)  //表示區(qū)域大于40*40時(shí)就畫出邊框
    {
     //畫邊框
     k1 = (iLeft -1 )<0 ?0:(iLeft -1 );
     k2 = (iRight+1)>=ImageWidth?(ImageWidth-1):(iRight+1);
     k3 = (iTop-1)<0?0:(iTop-1);
     k4 = (iBottom+1)>=ImageHeight?(ImageHeight-1):(iBottom+1);
     for(ii1 = k1;ii1 <= k2;ii1++)
     {
      off = ii1 + k3*ImageWidth;
      D[off] = 11;
      off = ii1 + k4*ImageWidth;
      D[off] = 11;
     }
     for(ii1 = k3 ;ii1<=k4;ii1++)
     {
      off = ii1 * ImageWidth + k1;
      D[off] = 11;
      off = ii1 * ImageWidth + k2;
      D[off] = 11;
     }
     /////////////////////////////////////////////////
    }
   }
  }
 
 }
 if(lpFlag!=NULL)
 {
  delete []lpFlag;
  lpFlag = NULL;
 }
}
                                                       標(biāo)準(zhǔn)源碼

BOOL RegionGrow(int nSeedX, int nSeedY, BYTE * pUnchInput,int nWidth, int nHeight, BYTE * pUnRegion,CRect &R)
{
  int nDx[] = {-1,1,0,0};
  int nDy[] = {0,0,-1,1};
 int nSaveWidth = nWidth;
 
 // 定義堆棧,存儲(chǔ)坐標(biāo)
 int * pnGrowQueX ;
 int * pnGrowQueY ;
 // 分配空間
 pnGrowQueX = new int [nWidth*nHeight];
 pnGrowQueY = new int [nWidth*nHeight];
 // 定義堆棧的起點(diǎn)和終點(diǎn)
 // 當(dāng)nStart=nEnd, 表示堆棧中只有一個(gè)點(diǎn)
 int nStart ;
 int nEnd ;
 //初始化
 nStart = 0 ;
 nEnd = 0 ;
 // 把種子點(diǎn)的坐標(biāo)壓入棧
 pnGrowQueX[nEnd] = nSeedX;
 pnGrowQueY[nEnd] = nSeedY;
 // 當(dāng)前正在處理的象素
 int nCurrX ;
 int nCurrY ;
 // 循環(huán)控制變量
 int k ;
 // 圖象的橫縱坐標(biāo),用來(lái)對(duì)當(dāng)前象素的8鄰域進(jìn)行遍歷
 int xx;
 int yy;
 while (nStart<=nEnd)
 {
  // 當(dāng)前種子點(diǎn)的坐標(biāo)
  nCurrX = pnGrowQueX[nStart];
  nCurrY = pnGrowQueY[nStart];
  // 對(duì)當(dāng)前點(diǎn)的4鄰域進(jìn)行遍歷
  for (k=0; k<4; k++)
  {
   // 4鄰域象素的坐標(biāo)
   xx = nCurrX+nDx[k];
   yy = nCurrY+nDy[k];
   // 判斷象素(xx,yy) 是否在圖像內(nèi)部
   // 判斷象素(xx,yy) 是否已經(jīng)處理過(guò)
   // pUnRegion[yy*nWidth+xx]==0 表示還沒(méi)有處理
   // 生長(zhǎng)條件:判斷象素(xx,yy)和當(dāng)前象素(nCurrX,nCurrY) 象素值差的絕對(duì)值
   if ( (xx < nWidth) && (xx>=0) && (yy>=0) && (yy<nHeight)
   && (pUnRegion[yy*nWidth+xx]==0) && (pUnchInput[yy*nSaveWidth+xx]==1))
   {
    // 堆棧的尾部指針后移一位
    nEnd++;
    // 象素(xx,yy) 壓入棧
    pnGrowQueX[nEnd] = xx;
    pnGrowQueY[nEnd] = yy;
    // 把象素(xx,yy)設(shè)置成邏輯1(255)
    // 同時(shí)也表明該象素處理過(guò)
    pUnRegion[yy*nWidth+xx] = 255 ;
   }
  }
  nStart++;
 }
   
 
 //找出區(qū)域的范圍
    int nMinx=pnGrowQueX[0], nMaxx=pnGrowQueX[0], nMiny=pnGrowQueY[0], nMaxy = pnGrowQueY[0];
    for (k=0; k<nEnd; k++)
 {
        if (pnGrowQueX[k] > nMaxx)
             nMaxx = pnGrowQueX[k];
       if (pnGrowQueX[k] < nMinx)
            nMinx = pnGrowQueX[k];
       if (pnGrowQueY[k] > nMaxy)
            nMaxy = pnGrowQueY[k];
       if (pnGrowQueY[k] < nMiny)
           nMiny = pnGrowQueY[k];
 }
    if ((nMaxy - nMiny) > 40 && (nMaxx - nMinx) > 40)
 {
    R.left = nMinx;
    R.right = nMaxx;
    R.top = nMiny;
    R.bottom = nMaxy;
       return TRUE;
 }
    // 釋放內(nèi)存
 delete []pnGrowQueX;
 delete []pnGrowQueY;
 pnGrowQueX = NULL ;
 pnGrowQueY = NULL ;
 return FALSE;
}
//調(diào)用方法
void OnButton(LPBYTE S,int ImageWidth,int ImageHeight)
{
 int i=0,j=0;
CRect rect;
 LPBYTE lpFlag = new BYTE[ImageWidth*ImageHeight];
 memset(lpFlag,0,ImageWidth*ImageHeight);
 for (i=0; i<ImageHeight; i++)
 {
  for (j=0; j<ImageWidth; j++)
  {
   if (S[i*ImageWidth+j] == 1 && lpFlag[i*ImageWidth+j] == 0)
   {
    RegionGrow(j, i, S, ImageWidth, ImageHeight, lpFlag,rect);
   }
  }
 
 }
 if(lpFlag!=NULL)
 {
  delete []lpFlag;
  lpFlag = NULL;
 }
}
 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多