区域生长代码

来源:互联网 发布:淘宝拍摄用什么相机好 编辑:程序博客网 时间:2024/04/27 21:49

/*************************************************************************
*
* //函数名称:
*   RegionGrow()
*
* //输入参数:
*   CDib * pDib     - 指向CDib类的指针,含有原始图象信息
*   unsigned char * pUnRegion  - 指向区域生长结果的指针
*
* //返回值:
*   无
*
* //说明:
*   pUnRegion指针指向的数据区存储了区域生长的结果,其中1(逻辑)表示
*  对应象素为生长区域,0表示为非生长区域
*   区域生长一般包含三个比较重要的问题:
*  1. 种子点的选取
*  2. 生长准则
*  3. 终止条件
*  可以认为,这三个问题需要具体分析,而且每个问题解决的好坏直接关系到
*  区域生长的结果。
*  本函数的种子点选取为图像的中心,生长准则是相邻象素的象素值小于
*  nThreshold, 终止条件是一直进行到再没有满足生长准则需要的象素时为止
*
*************************************************************************
*/
void RegionGrow(CDib * pDib, unsigned char * pUnRegion, int nThreshold)
{
 static int nDx[]={-1,0,1,0};
 static int nDy[]={0,1,0,-1};

 // 遍历图象的纵坐标
// int y;

 // 遍历图象的横坐标
// int x;

 // 图象的长宽大小
 CSize sizeImage  = pDib->GetDimensions();
 int nWidth   = sizeImage.cx  ;
 int nHeight   = sizeImage.cy  ;

 // 图像在计算机在存储中的实际大小
 CSize sizeImageSave = pDib->GetDibSaveDim();

 // 图像在内存中每一行象素占用的实际空间
 int nSaveWidth = sizeImageSave.cx;

 // 初始化
 memset(pUnRegion,0,sizeof(unsigned char)*nWidth*nHeight);

 // 种子点
 int nSeedX, nSeedY;

 // 设置种子点为图像的中心
 nSeedX = nWidth /2 ;
 nSeedY = nHeight/2 ;

 // 定义堆栈,存储坐标
 int * pnGrowQueX ;
 int * pnGrowQueY ;
 
 // 分配空间
 pnGrowQueX = new int [nWidth*nHeight];
 pnGrowQueY = new int [nWidth*nHeight];

 // 图像数据的指针
 unsigned char *  pUnchInput =(unsigned char * )pDib->m_lpImage;
 
 // 定义堆栈的起点和终点
 // 当nStart=nEnd, 表示堆栈中只有一个点
 int nStart ;
 int nEnd   ;

 //初始化
 nStart = 0 ;
 nEnd   = 0 ;

 // 把种子点的坐标压入栈
 pnGrowQueX[nEnd] = nSeedX;
 pnGrowQueY[nEnd] = nSeedY;

 // 当前正在处理的象素
 int nCurrX ;
 int nCurrY ;

 // 循环控制变量
 int k ;

 // 图象的横纵坐标,用来对当前象素的4邻域进行遍历
 int xx;
 int yy;

 while (nStart<=nEnd)
 {
  // 当前种子点的坐标
  nCurrX = pnGrowQueX[nStart];
  nCurrY = pnGrowQueY[nStart];     

  // 对当前点的4邻域进行遍历
  for (k=0; k<4; k++) 
  { 
   // 4邻域象素的坐标
   xx = nCurrX+nDx[k];
   yy = nCurrY+nDy[k];
   
   // 判断象素(xx,yy) 是否在图像内部
   // 判断象素(xx,yy) 是否已经处理过
   // pUnRegion[yy*nWidth+xx]==0 表示还没有处理

   // 生长条件:判断象素(xx,yy)和当前象素(nCurrX,nCurrY) 象素值差的绝对值
   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)设置成逻辑1(255)
    // 同时也表明该象素处理过
    pUnRegion[yy*nWidth+xx] = 255 ;
   }
  }
  nStart++;
 }

 // 释放内存
 delete []pnGrowQueX;
 delete []pnGrowQueY;
    pnGrowQueX = NULL ;
 pnGrowQueY = NULL ;
}

对于2D图象的组织增长,使用递归也是一种不错的选择,但需要注意栈空间需要设大一些。
而在3D数据场上,递归几乎是不可行的,栈空间经常会出现溢出的情况,因此不具备实用性。
2D组织增长伪代码如下

组织增长(Image* pImage, int i, ing j, byte* mask)
{
   if 不满足增长条件(pImage, i,j, mask)
       return;
   设置标记(mask, i, j);
   组织增长(pImage, i-1, j, mask);
   组织增长(pImage, i+1, j, mask);
   组织增长(pImage, i, j-1, mask);
   组织增长(pImage, i, j+1, mask);
}

至于将递归程序改为迭代程序,可以看一看《程序设计方法学》

原创粉丝点击