分水岭算法源代码及其分析和注释

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

/*====================================================================

函数名: Watershed

功能:用标记-分水岭算法对输入图像进行分割

算法实现:无

输入参数说明: OriginalImage --输入图像(灰度图,0~255)

SeedImage --标记图像(二值图,0-非标记,1-标记)

LabelImage --输出图像(1-第一个分割区域,2-第二个分割区域,...)

row --图像行数

col --图像列数

返回值说明:无

====================================================================*/

void WINAPI CDib::Watershed(unsigned char **OriginalImage, char** SeedImage, int **LabelImage, int row, int col)

{

// using namespace std;

//标记区域标识号,从1开始

int Num=0;

int i,j;

//保存每个队列种子个数的数组

vector SeedCounts;

//临时种子队列

queue quetem;

//保存所有标记区域种子队列的数组,里面放的是种子队列的指针

vector*> vque;

int* array;

//指向种子队列的指针

queue *pque;

POINT temp;

for(i=0;i

{

for(j=0;j

LabelImage[i][j]=0;

}

int m,n,k=0;

BOOL up,down,right,left,upleft,upright,downleft,downright;//8 directions...

//预处理,提取区分每个标记区域,并初始化每个标记的种子队列

//种子是指标记区域边缘的点,他们可以在水位上升时向外淹没(或者说生长)

//pan's words:我的理解是梯度值较小的象素点,或者是极小灰度值的点。

for(i=0;i

{

for(j=0;j

{

//如果找到一个标记区域

if(SeedImage[i][j]==1)

{

//区域的标识号加一

Num++;

//分配数组并初始化为零,表示可有256个灰阶

array=new int[256];

ZeroMemory(array,256*sizeof(int));

//种子个数数组进vector,每次扫描则生成一个数组,并用区域标识号来做第一维。灰度级做第二维。

//表示某个盆地区域中某灰阶所对应的点的数目。

SeedCounts.push_back(array);

//分配本标记号的优先队列,256个种子队列,

//表示对应一个灰阶有一个队列,并且每个队列可以存储一个集合的点信息

pque=new queue[256];

//加入到队列数组中,对应的是本标记号Num的

vque.push_back(pque);

//当前点放入本标记区域的临时种子队列中

temp.x=i;

temp.y=j;

quetem.push(temp);

//当前点标记为已处理

LabelImage[i][j]=Num;

SeedImage[i][j]=127;//表示已经处理过

//让临时种子队列中的种子进行生长直到所有的种子都生长完毕

//生长完毕后的队列信息保存在vque中,包括区域号和灰阶,对应点数存储在seedcounts中

while(!quetem.empty())

{

up=down=right=left=FALSE;

upleft=upright=downleft=downright=FALSE;

//队列中取出一个种子

temp=quetem.front();

m=temp.x;

n=temp.y;

quetem.pop();

//注意到127对扫描过程的影响,影响下面的比较,但是不影响while语句中的扫描

if(m>0)

{

//上方若为可生长点则加为新种子

if(SeedImage[m-1][n]==1)

{

temp.x=m-1;

temp.y=n;

quetem.push(temp);//如果这样的话,那么这些标记过的区域将再次在while循环中被扫描到,不会,因为值是127

//新种子点标记为已淹没区域,而且是当前区域,并记录区域号到labelImage

LabelImage[m-1][n]=Num;

SeedImage[m-1][n]=127;

}

else//否则上方为不可生长

{

up=TRUE;

}

}

if(m>0&&n>0)

{

if(SeedImage[m-1][n-1]==1)//左上方若为可生长点则加为新种子

{

temp.x=m-1;

temp.y=n-1;

quetem.push(temp);

//新种子点标记为已淹没区域,即下一个循环中以127来标识不再扫描,而且是当前区域

LabelImage[m-1][n-1]=Num;

SeedImage[m-1][n-1]=127;

}

else//否则左上方为不可生长

{

upleft=TRUE;

}

}

if(m

{

if(SeedImage[m+1][n]==1)//下方若为可生长点则加为新种子

{

相关文档
最新文档