分水岭算法源代码及其分析和注释
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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
//临时种子队列
queue
//保存所有标记区域种子队列的数组,里面放的是种子队列的指针
vector
int* array;
//指向种子队列的指针
queue
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 //加入到队列数组中,对应的是本标记号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)//下方若为可生长点则加为新种子 {