www.pudn.com > segmentaion.rar > waterseg.cpp, change:2007-03-01,size:53539b


#include "stdafx.h" 
#include "WaterSeg.h" 
 
int nChannels; 
 
int WaterSeg(unsigned char** originalImage,unsigned char** maskImage, int width, int height, int nC, int winSize,  int isColor,int* Label)  
{ 
	int** GradientImage; 
	char** SeedImage; 
	int** LabelImage; 
	int* ChannelLabel[3]; 
	CString str; 
	nChannels=nC; 
	int SegNum; 
 
	unsigned char* imageReconstr=new unsigned char [width*height]; 
	unsigned char* marker=new unsigned char [width*height]; 
 
 
	for (int n=0; n0; i--)  
		{ 
			delete [] SeedImage[i-1]; 
			delete [] LabelImage[i-1];		 
			delete [] GradientImage[i-1]; 
		} 
		delete [] GradientImage; 
		delete [] SeedImage; 
		delete [] LabelImage; 
	} 
 
	 
	if (isColor==1) 
	{ 
		SegNum=LabelFusion(ChannelLabel,width, height,Label); 
	} 
	else 
	{ 
		ChannelLabel[1]=ChannelLabel[0]; 
		ChannelLabel[2]=ChannelLabel[0]; 
		SegNum=LabelFusion(ChannelLabel,width, height,Label); 
	} 
 
 
 
// Release data 
 
	for (int n=nChannels; n>0; n--) 
	{ 
		delete [] ChannelLabel[n-1]; 
	} 
	delete [] imageReconstr; 
	delete [] marker; 
 
	return SegNum; 
} 
 
void getBoundary(int* src,unsigned char* dst,int width, int height) 
{ 
	int neighbors[4]; 
	for (int i=0; i<(height*width); i++) 
	{ 
		getFourNeighbor(i, width, height, neighbors); 
		if (src[i]>src[neighbors[0]] || src[i]>src[neighbors[1]] ||  
			src[i]>src[neighbors[2]] || src[i]>src[neighbors[3]]  ) 
			dst[i]=255; 
		else 
			dst[i]=0; 
	} 
} 
 
void getGradient(unsigned char* src, unsigned char* dst, int width, int height) 
{ 
	char hx[8]={2,1,0,-1,-2,-1,0,1}; 
	char hy[8]={0,-1,-2,-1,0,1,2,1}; 
	int* Ix=new int [width*height]; 
	int* Iy=new int [width*height]; 
	unsigned char** src1=new unsigned char* [height+2]; 
	for (int i=0; i0.5) 
			Ix[i]++; 
//		Ix[i] = (Ix[i] < 181) ? Ix[i] : 181; 
 
		if (Ix[i] > maxVal)  
		{ 
            maxVal = Ix[i]; 
		}  
	} 
 
 
    for (int i=0; i0; i--)  
	{ 
		delete [] src1[i-1]; 
	} 
	delete [] Ix; 
	delete [] Iy; 
	delete [] src1; 
 
} 
 
 
void LabelToRgb(int* Label,int LabelNum, char* Lrgb, int width, int height) 
{ 
	LabelNum++; 
	char* index = new char [LabelNum*3];  
//	int step=Lrgb->widthStep; 
	const int ColorLevel=8; 
 
	 
    for(int i=0; i SeX; 
	vector  SeY; 
	winSize=(winSize-1)/2; 
	for (int i=-winSize; i<=winSize; i++) 
	{ 
		for (int j=-winSize; j<=winSize; j++) 
		{ 
			if ( i*i+j*j<=winSize*winSize ) 
			{	 
				SeX.push_back(i); 
				SeY.push_back(j); 
			} 
		} 
	} 
	 
//  opening by reconstruction  
	unsigned char* Ie=new unsigned char [width*height]; 
	imErode(src, Ie, width, height, &SeX, &SeY); 
	imReconstruct(src,Ie,width, height); 
	unsigned char* Iobr=Ie; 
	 
//  closing by reconstruction  
	unsigned char* Iobrd=Iobrcbr; 
	 
	for (int i=0; i marker2[i]) ? marker[i] : marker2[i]; 
		marker[i]= (marker[i] < markerDilate[i]) ? marker[i] : markerDilate[i]; 
	} 
	 
	SeX.clear(); 
	SeY.clear(); 
	delete [] Ie; 
	delete [] markerDilate; 
 
} 
 
void imErode(unsigned char* src, unsigned char* dst, int width, int height, vector * SeX, vector * SeY) 
{ 
	int SeSize=SeX->size(); 
	for (int j=0; jat(k); 
				int neighborY=j+SeY->at(k); 
				if (neighborX>=0 && neighborX=0 && neighborY* SeX, vector * SeY) 
{ 
	int SeSize=SeX->size(); 
	for (int j=0; jat(k); 
				int neighborY=j+SeY->at(k); 
				if (neighborX>=0 && neighborX=0 && neighborY src[p]) ? maxGrayLevel : src[p]; 
				} 
			} 
			dst[j*width+i]=maxGrayLevel; 
		} 
	} 
} 
 
 
void imReconstruct(unsigned char* I, unsigned char* J, int width, int height) 
// I: mask image, and J: marker image 
{	 
	int numElements=height*width; 
	int neighbor[8]; 
	int maxPixel; 
	int p; 
	int Jp, Jq, Iq; 
 
	queue que; 
	 
	for (p = 0; p < numElements; p++) 
    { 
        // "Let p be the current pixel" 
        // "J(p) <- (max{J(q),q member_of N_G_plus(p) union {p}}) ^ I(p)" 
 
        // Find the maximum value of the (y,x) pixel 
        // plus all the pixels in the "plus" neighborhood  
        // of (y,x). 
 
        maxPixel = J[p]; 
		getTrailingNeighbor(p, width, height, neighbor); 
        for (int i = 0; i < 4; i++) 
        { 
            if (neighbor[i]!=-1) 
			if (J[neighbor[i]] > maxPixel) 
            { 
                maxPixel = J[neighbor[i]]; 
            } 
        } 
 
        // Now set the (y,x) pixel of image J to the minimum 
        // of maxPixel and the (y,x) pixel of image I. 
 
        J[p] = (maxPixel < I[p]) ? maxPixel : I[p]; 
	} 
 
    // Second pass,  Scan D_I in antiraster order (lower-right to upper-left, 
    // along the columns): 
 
 
    for (p = numElements - 1; p >= 0; p--) 
    { 
        // "Let p be the current pixel" 
        // "J(p) <- (max{J(q),q member_of N_G_minus(p) union {p}}) ^ I(p)" 
 
        // Find the maximum value of the (y,x) pixel 
        // plus all the pixels in the "minus" neighborhood  
        // of (y,x). 
 
        maxPixel = J[p]; 
		getLeadingNeighbor(p, width, height, neighbor); 
        for (int i = 0; i < 4; i++) 
        { 
            if (neighbor[i]!=-1) 
			if (J[neighbor[i]] > maxPixel) 
            { 
                maxPixel = J[neighbor[i]]; 
            } 
        } 
     
 
        // Now set the (y,x) pixel of image J to the minimum 
        // of maxPixel and the (y,x) pixel of image I. 
 
        J[p] = (maxPixel < I[p]) ? maxPixel : I[p]; 
         
        // "If there exists q member_of N_G_minus(p)  
        // such that J(q) < J(p) and J(q) < I(q), then fifo_add(p)" 
 
        for (int i = 0; i < 4; i++) 
        { 
            if (neighbor[i]!=-1) 
			if ((J[neighbor[i]] < J[p]) && 
                (J[neighbor[i]] < I[neighbor[i]])) 
            { 
                que.push(p); 
                break; 
            } 
        } 
    } 
 
    // "Propagation step: 
    // While fifo_empty() is false" 
 
    while (!(que.empty())) 
    { 
        // "p <= fifo_first()" 
 
        p = que.front(); 
		que.pop(); 
		Jp = J[p]; 
 
        // "For every pixel q member_of N_g(p):" 
 
		getNeighbor(p, width, height, neighbor); 
             
        for (int i = 0; i <8; i++) 
		{ 
             
            // "If J(q) < J(p) and I(q) ~= J(q), then 
            //  J(q) <- min{J(p),I(q)} 
            //  fifo_add(q)" 
 
            if (neighbor[i]!=-1) 
			{ 
				Jq = J[neighbor[i]]; 
				Iq = I[neighbor[i]]; 
				if ((Jq < Jp) && (Iq != Jq)) 
				{ 
					J[neighbor[i]] = (Jp < Iq) ? Jp : Iq; 
					que.push(neighbor[i]); 
				} 
            } 
        } 
    } 
} 
 
 
 
void getRegMax(unsigned char* F, unsigned char* BW,int width, int height) 
{ 
    stack  stk; 
 
	int num_elements=width*height; 
    int p; 
    int pp; 
    int val; 
    bool found; 
	int neighbor[8]; 
	 
    // Initialize output to all ones. 
    for (p = 0; p < num_elements; p++) 
        BW[p] = 255; 
	 
 
    // Scan F in raster order. "For each pixel p in G" 
    for (p = 0; p < num_elements; p++) 
    { 
        //"If pixel p hasn't already been processed" 
        if (BW[p] != 0) 
        { 
            // See if any neighbors of p have a higher intensity. 
            found = false; 
			getNeighbor(p, width, height, neighbor); 
            for (int i = 0; i < 8; i++) 
            { 
                if (neighbor[i]!=-1) 
				if (F[neighbor[i]] > F[p]) 
                { 
                    found = true; 
					break; 
                } 
            } 
                         
            // "If there is a neighbor q such that F[q] > F[p] ..." 
            if (found) 
            { 
                //"... then set all BW pixels connected to p and having 
                // the same intensity to 0." 
                val = F[p]; 
                stk.push(p); 
                BW[p] = 0; 
	 
                while (!(stk.empty())) 
                { 
                    pp = stk.top(); 
					stk.pop(); 
                    getNeighbor(pp, width, height, neighbor); 
					for (int i = 0; i < 8; i++) 
                    { 
						if (neighbor[i]!=-1) 
                        if ((BW[neighbor[i]] != 0) && (F[neighbor[i]] == val)) 
                        { 
                            stk.push(neighbor[i]); 
                            BW[neighbor[i]] = 0; 
                        } 
                    } 
                } 
            } 
        } 
    } 
} 
 
 
void getNeighbor(int center, int width, int height, int* neighbor) 
{ 
	//       3  2  1 
	//		  \ | / 
	//       4- C -0 
	//		  / | \ 
	//       5  6  7 
	neighbor[0]=center+1; 
	neighbor[1]=center-width+1; 
	neighbor[2]=center-width; 
	neighbor[3]=center-width-1; 
	neighbor[4]=center-1; 
	neighbor[5]=center+width-1; 
	neighbor[6]=center+width; 
	neighbor[7]=center+width+1; 
	 
	if (center=width*(height-1)) { 
		neighbor[5]=-1; 
		neighbor[6]=-1; 
		neighbor[7]=-1; 
	} 
 
	if (center==(center/width*width)) { 
		neighbor[3]=-1; 
		neighbor[4]=-1; 
		neighbor[5]=-1; 
	} 
 
	if (center==(center/width*width+width-1)) { 
		neighbor[7]=-1; 
		neighbor[0]=-1; 
		neighbor[1]=-1; 
	} 
} 
 
void getNeighborReorder(int center, int width, int height, int* neighbor) 
{ 
	//       5  1  4 
	//		  \ | / 
	//       2- C -0 
	//		  / | \ 
	//       6  3  7 
	neighbor[0]=center+1; 
	neighbor[4]=center-width+1; 
	neighbor[1]=center-width; 
	neighbor[5]=center-width-1; 
	neighbor[2]=center-1; 
	neighbor[6]=center+width-1; 
	neighbor[3]=center+width; 
	neighbor[7]=center+width+1; 
	 
	if (center=width*(height-1)) { 
		neighbor[6]=-1; 
		neighbor[3]=-1; 
		neighbor[7]=-1; 
	} 
 
	if (center==(center/width*width)) { 
		neighbor[5]=-1; 
		neighbor[2]=-1; 
		neighbor[6]=-1; 
	} 
 
	if (center==(center/width*width+width-1)) { 
		neighbor[7]=-1; 
		neighbor[0]=-1; 
		neighbor[4]=-1; 
	} 
} 
 
void getFourNeighbor(int center, int width, int height, int* neighbor) 
{ 
	//       *  1  * 
	//		  \ | / 
	//       2- C -0 
	//		  / | \ 
	//       *  3  * 
	neighbor[0]=center+1; 
	neighbor[1]=center-width; 
	neighbor[2]=center-1; 
	neighbor[3]=center+width; 
	 
	if (center=width*(height-1)) { 
		neighbor[3]=-1; 
	} 
 
	if (center==(center/width*width)) { 
		neighbor[2]=-1; 
	} 
 
	if (center==(center/width*width+width-1)) { 
		neighbor[0]=-1; 
	} 
} 
 
void getTrailingNeighbor(int center, int width, int height, int* neighbor) 
{ 
	//       2  1  0 
	//		  \ | / 
	//       3- C -* 
	//		  / | \ 
	//       *  *  * 
	neighbor[0]=center-width+1; 
	neighbor[1]=center-width; 
	neighbor[2]=center-width-1; 
	neighbor[3]=center-1; 
	 
	if (center=width*(height-1)) { 
		neighbor[0]=-1; 
		neighbor[1]=-1; 
		neighbor[2]=-1; 
	} 
	 
	if (center==(center/width*width)) { 
		neighbor[0]=-1; 
	} 
 
	if (center==(center/width*width+width-1)) { 
		neighbor[2]=-1; 
		neighbor[3]=-1; 
	} 
} 
 
 
int Watershed(int **OriginalImage, char **SeedImage, int **LabelImage, int row, int col) 
{ 
	 
	int Num=0; 
	int i,j; 
 
	vector SeedCounts; 
	queue que; 
	vector* > qu; 
	 
	int* array; 
	queue *uu; 
	POINT temp; 
 
	 
 
	for(i=0;i[256]; 
				qu.push_back(uu); 
				temp.x=i; 
				temp.y=j; 
				que.push(temp); 
 
				 
				LabelImage[i][j]=Num; 
				SeedImage[i][j]=127; 
 
				while(!que.empty()) 
				{ 
					up=down=right=left=0; 
					upleft=upright=downleft=downright=0; 
					temp=que.front(); 
					m=temp.x; 
					n=temp.y; 
					que.pop(); 
					 
 
					if(m>0) 
					{ 
						if(SeedImage[m-1][n]==1) 
						{ 
							temp.x=m-1; 
							temp.y=n; 
							que.push(temp); 
 
							LabelImage[m-1][n]=Num; 
							SeedImage[m-1][n]=127; 
						}else 
						{ 
							up=1; 
						} 
					} 
 
					 
					if(m>0&&n>0) 
					{ 
						if(SeedImage[m-1][n-1]==1) 
						{ 
							temp.x=m-1; 
							temp.y=n-1; 
							que.push(temp); 
							LabelImage[m-1][n-1]=Num; 
							SeedImage[m-1][n-1]=127; 
						}else 
						{ 
							upleft=1; 
						} 
					} 
					 
					 
					 
					if(m0&&n<(col-1)) 
 
					{ 
						if(SeedImage[m-1][n+1]==1) 
						{ 
							temp.x=m-1; 
							temp.y=n+1; 
							que.push(temp); 
							LabelImage[m-1][n+1]=Num; 
							SeedImage[m-1][n+1]=127; 
						}else 
						{ 
							upright=1; 
						} 
					} 
 
					if(n>0) 
					{ 
						if(SeedImage[m][n-1]==1) 
						{ 
							temp.x=m; 
							temp.y=n-1; 
							que.push(temp); 
							LabelImage[m][n-1]=Num; 
							SeedImage[m][n-1]=127; 
						}else 
						{ 
							left=1; 
						} 
					} 
					 
					if(m<(row-1)&&n>0) 
					{ 
						if(SeedImage[m+1][n-1]==1) 
						{ 
							temp.x=m+1; 
							temp.y=n-1; 
							que.push(temp); 
							LabelImage[m+1][n-1]=Num; 
							SeedImage[m+1][n-1]=127; 
						}else 
						{ 
							downleft=1; 
						} 
					} 
 
					 
					if(up||down||right||left|| 
						upleft||downleft||upright||downright) 
					{ 
						 
						temp.x=m; 
						temp.y=n; 
						qu[Num-1][OriginalImage[m][n]].push(temp); 
						SeedCounts[Num-1][OriginalImage[m][n]]++; 
					} 
					 
 
 
				} 
			} 
		} 
	} 
 
	 
	bool actives; 
	int WaterLevel; 
	for(WaterLevel=0;WaterLevel<256;WaterLevel++) 
	{ 
		actives=true; 
		while(actives) 
		{ 
			actives=false; 
			for(i=0;i0) 
				{ 
					SeedCounts[i][WaterLevel]--; 
					temp=qu[i][WaterLevel].front(); 
					qu[i][WaterLevel].pop(); 
					m = temp.x; 
					n = temp.y; 
					if(m>0) 
					{ 
						if(!LabelImage[m-1][n]) 
						{ 
							temp.x=m-1; 
							temp.y=n; 
							LabelImage[m-1][n]=i+1; 
 
							if(OriginalImage[m-1][n]<=WaterLevel) 
							{ 
								qu[i][WaterLevel].push(temp); 
							} 
							else 
							{ 
								qu[i][OriginalImage[m-1][n]].push(temp); 
								SeedCounts[i][OriginalImage[m-1][n]]++; 
							} 
						} 
					} 
 
					if(m0) 
					{ 
						if(!LabelImage[m][n-1]) 
						{ 
							temp.x=m; 
							temp.y=n-1; 
							LabelImage[m][n-1]=i+1; 
 
							if(OriginalImage[m][n-1]<=WaterLevel) 
							{ 
								qu[i][WaterLevel].push(temp); 
							} 
							else 
							{ 
								qu[i][OriginalImage[m][n-1]].push(temp); 
								SeedCounts[i][OriginalImage[m][n-1]]++; 
							} 
						} 
					} 
				} 
				SeedCounts[i][WaterLevel]=qu[i][WaterLevel].size(); 
			} 
			} 
		} 
	} 
	while(!qu.empty()) 
	{ 
		uu=qu.back(); 
		delete[] uu; 
		qu.pop_back(); 
	} 
	while(!SeedCounts.empty()) 
	{ 
		array=SeedCounts.back(); 
		delete[] array; 
		SeedCounts.pop_back(); 
	} 
 
	return(Num); 
} 
 
int LabelFusion(int** ChannelLabel, int width, int height, int* LabelImage) 
{ 
	int* BW=0; 
	int num_elements=width*height; 
	int neighbor[4]; 
	int qq; 
	queue que; 
	 
	BW=new int [num_elements]; 
 
    for (int p = 0; p < num_elements; p++) 
	{ 
        if (ChannelLabel[0][p]>0) 
			BW[p] = 0; 
		else 
			BW[p] = 1; 
 
		LabelImage[p]=0; 
	} 
	int totalNum=0; 
 
	for (int p = 0; p < num_elements; p++) 
    { 
		if (BW[p]==0) 
		{ 
			int regionSize=0; 
			totalNum++; 
			que.push(p); 
			BW[p]=1; 
			LabelImage[p]=totalNum; 
			 
			 
			while (!(que.empty())) 
			{ 
				qq=que.front(); 
				que.pop(); 
				getFourNeighbor(qq, width, height, neighbor); 
				for (int i = 0; i <4; i++) 
				{ 
					if (neighbor[i]!=-1 && 
						ChannelLabel[0][qq]==ChannelLabel[0][neighbor[i]] && 
						ChannelLabel[1][qq]==ChannelLabel[1][neighbor[i]] && 
						ChannelLabel[2][qq]==ChannelLabel[2][neighbor[i]] && 
						BW[neighbor[i]]==0) 
 
					{ 
						que.push(neighbor[i]); 
						BW[neighbor[i]]=1; 
						LabelImage[neighbor[i]]=totalNum; 
					} 
				} 
			} 
		} 
	} 
 
	delete [] BW;			 
	return(totalNum); 
} 
 
 
int regionMerge(int* Label,int SegNum, int width, int height, unsigned char** originalImage, int minSegNum,int mergingMethod) 
{ 
	int num_elements=width*height; 
	Node* nod=new Node [SegNum]; 
	int* boundaryMarked=new int [num_elements]; 
 
	for (int i=0; i=0) 
		{ 
			nod[Label[i]].pixelSize++; 
			nod[Label[i]].pixelIndex.push_back(i); 
 
		} 
	} 
 
	// Calculate mean color of nodes 
	for (int i=0; i0) 
				getNodCurv(&nod[n],Label,width,height,boundaryMarked); 
	} 
 
 
	// Initialize links 
	queue linkQue; 
	for (int n=0; n0) 
		{ 
			int neighborNum=labelOfNeighbor(Label,&nod[n],width,height,neighborIndex); 
			for (int i=0; i0) 
	{ 
		while (finalRegionNum>minSegNum) 
		{ 
			// Find target link to perform merging 
			tLinkIndex=minDissimilarIndex(lik, linkNum); 
			nodIndex1=lik[tLinkIndex].nod1; 
			nodIndex2=lik[tLinkIndex].nod2; 
 
			mergeTwoRegions(&lik[tLinkIndex],nod,Label,mergingMethod,width,height,boundaryMarked); 
			finalRegionNum--; 
 
			// Update links 
			lik[tLinkIndex]=lik[linkNum-1]; 
			linkNum--; 
			int neighborNum=0; 
			for (int i=0; i duplicateLinkIndex; 
			for (int i=0; i0) 
				LabelIndex[regionNum-1][j]=Label[nod[j].pixelIndex.front()]; 
			else 
				LabelIndex[regionNum-1][j]=-1; 
		} 
 
		while (finalRegionNum>2) 
		{ 
			// Find target link to perform merging 
			tLinkIndex=minDissimilarIndex(lik, linkNum); 
			nodIndex1=lik[tLinkIndex].nod1; 
			nodIndex2=lik[tLinkIndex].nod2; 
 
			mergeTwoRegions(&lik[tLinkIndex],nod,Label,mergingMethod,width,height,boundaryMarked); 
			finalRegionNum--; 
 
			// Update LabelIndex; 
			for (int j=0; j duplicateLinkIndex; 
			for (int i=0; i=0) 
				{ 
					for (int n=0; n=0) 
				Label[i]=LabelIndex[optRegionNum-1][LabelRecord[i]]; 
			else 
				Label[i]=LabelRecord[i]; 
		} 
 
		for (int i=0; i=0) 
			{ 
				nod[Label[i]].pixelSize++; 
				nod[Label[i]].pixelIndex.push_back(i); 
 
			} 
		} 
 
		// Calculate mean color of nodes 
		for (int i=0; i0) 
				{ 
					DWORD64 sum=0; 
					for (int j=0; j0) 
		{ 
			finalRegionNum++; 
			for	(int i=0; inod1; 
	int nodIndex2=lik->nod2; 
	double BCR; 
 
	// Get color difference 
	for (int j=0; jmeanCurvatureOfMerge),&(lik->curveLengthOfMerge)); 
 
 
		// Compute Boundary Curvature Ratio and dissimilarity of the two nodes 
		BCR=lik->meanCurvatureOfMerge/((nod[nodIndex1].meanCurvature*nod[nodIndex1].curveLength + nod[nodIndex2].meanCurvature*nod[nodIndex2].curveLength)/ 
			(nod[nodIndex1].curveLength+nod[nodIndex2].curveLength)); 
 
		lik->dissimilarity=(float) pow((double) colorDif,BCR)*nod[nodIndex1].pixelSize*nod[nodIndex2].pixelSize/totalSize; 
	} 
	else 
		lik->dissimilarity=((float) colorDif)*nod[nodIndex1].pixelSize*nod[nodIndex2].pixelSize/totalSize; 
 
} 
 
void mergeTwoRegions(Link* lik,Node* nod,int* Label) 
{	 
	int minor=lik->nod1; 
	int major=lik->nod2; 
	 
	// update label image 
	for (int i=0; inod1; 
	int major=lik->nod2; 
 
	// update label image 
	for (int i=0; i 0); 
    int minIndex = 0; 
    for (int i=1; i 0); 
    int minIndex = 0; 
    for (int i=1; ipixelIndex.front()]; 
	int neighborNum=0; 
	bool newNeighbor; 
 
	for (int n=0; npixelSize; n++) 
	{ 
		getFourNeighbor(nod->pixelIndex.at(n), width, height, neighbor); 
		for (int i=0; i<4; i++) 
		{ 
			if (neighbor[i]!=-1) 
				if (Label[neighbor[i]]!=currentRegionLabel && Label[neighbor[i]]>=0) 
				{ 
					newNeighbor=true; 
					for (int j=0; jpixelIndex.front()]; 
	int labelFlag2=Label[nod2->pixelIndex.front()]; 
	deque> bdySegSet; 
	deque bdySeg; 
 
	int startPoint=0; 
	int endPoint=nod1->bdyIndex.size()-1; 
	bool previousNormal=Label[nod1->bdyIndex.front()]!=labelFlag2; 
	if (Label[nod1->bdyIndex.front()]!=labelFlag2 && Label[nod1->bdyIndex.back()]==labelFlag2) 
	{ 
		bdySeg.push_back(nod1->bdyIndex.at(startPoint)); 
		startPoint++; 
		if (startPointbdyIndex.at(startPoint)]!=labelFlag2) 
			{ 
				bdySeg.push_back(nod1->bdyIndex.at(startPoint)); 
				startPoint++; 
			} 
			for (int j=0;j<=1;j++) 
			{ 
				if ((startPoint+j)bdyIndex.at(startPoint+j)]!=labelFlag2) 
					{ 
						bdySeg.push_back(nod1->bdyIndex.at(startPoint+j)); 
					} 
			} 
			bdySegSet.push_back(bdySeg); 
			bdySeg.clear(); 
	} 
	if (Label[nod1->bdyIndex.front()]==labelFlag2 && Label[nod1->bdyIndex.back()]!=labelFlag2) 
	{ 
		bdySeg.push_back(nod1->bdyIndex.at(endPoint)); 
		endPoint--; 
		if (startPointbdyIndex.at(endPoint)]!=labelFlag2) 
			{ 
				bdySeg.push_back(nod1->bdyIndex.at(endPoint)); 
				endPoint--; 
			} 
			for (int j=0;j<=1;j++) 
			{ 
				if (startPoint<(endPoint-j)) 
					if	(Label[nod1->bdyIndex.at(endPoint-j)]!=labelFlag2) 
					{ 
						bdySeg.push_back(nod1->bdyIndex.at(endPoint-j)); 
					} 
			} 
			bdySegSet.push_back(bdySeg); 
			bdySeg.clear(); 
	} 
 
	for (int i=startPoint; i<=endPoint; i++) 
	{ 
		if (Label[nod1->bdyIndex.at(i)]!=labelFlag2) 
		{ 
			if (previousNormal) 
			{ 
				(*curveLength)++; 
				(*meanCurvature)+=nod1->curvature.at(i); 
			} 
			else  
			{ 
				// add one bdySeg; 
				bdySeg.push_back(nod1->bdyIndex.at(i)); 
				if (i+1<=endPoint) 
					if(Label[nod1->bdyIndex.at(i+1)]!=labelFlag2) 
					{ 
						i++; 
						bdySeg.push_back(nod1->bdyIndex.at(i)); 
					} 
					for (int j=1; j<=2; j++) 
					{ 
						if (i+1<=endPoint) 
							if(Label[nod1->bdyIndex.at(i+1)]!=labelFlag2) 
							{ 
								i++; 
								bdySeg.push_back(nod1->bdyIndex.at(i)); 
								(*curveLength)++; 
								(*meanCurvature)+=nod1->curvature.at(i); 
							} 
					} 
					bdySegSet.push_back(bdySeg); 
					bdySeg.clear(); 
 
					previousNormal=true; 
			} 
		} 
		else 
		{ 
			if (previousNormal) 
			{ 
				// add one bdySeg; 
				for (int j=1;j<=2;j++) 
				{ 
					if (i>=j) 
						if	(Label[nod1->bdyIndex.at(i-j)]!=labelFlag2) 
						{ 
							(*curveLength)--; 
							(*meanCurvature)-=nod1->curvature.at(i-j); 
							bdySeg.push_back(nod1->bdyIndex.at(i-j)); 
						} 
				} 
				for (int j=3;j<=4;j++) 
				{ 
					if (i>=j) 
						if	(Label[nod1->bdyIndex.at(i-j)]!=labelFlag2) 
						{ 
							bdySeg.push_back(nod1->bdyIndex.at(i-j)); 
						} 
				} 
				bdySegSet.push_back(bdySeg); 
				bdySeg.clear(); 
 
				previousNormal=false; 
			} 
		} 
	} 
 
	startPoint=0; 
	endPoint=nod2->bdyIndex.size()-1; 
	previousNormal=previousNormal=Label[nod2->bdyIndex.front()]!=labelFlag1;; 
	if (Label[nod2->bdyIndex.front()]!=labelFlag1 && Label[nod2->bdyIndex.back()]==labelFlag1) 
	{ 
		bdySeg.push_back(nod2->bdyIndex.at(startPoint)); 
		startPoint++; 
		if (startPointbdyIndex.at(startPoint)]!=labelFlag1) 
			{ 
				bdySeg.push_back(nod2->bdyIndex.at(startPoint)); 
				startPoint++; 
			} 
			for (int j=0;j<=1;j++) 
			{ 
				if ((startPoint+j)bdyIndex.at(startPoint+j)]!=labelFlag1) 
					{ 
						bdySeg.push_back(nod2->bdyIndex.at(startPoint+j)); 
					} 
			} 
			bdySegSet.push_back(bdySeg); 
			bdySeg.clear(); 
	} 
	if (Label[nod2->bdyIndex.front()]==labelFlag1 && Label[nod2->bdyIndex.back()]!=labelFlag1) 
	{ 
		bdySeg.push_back(nod2->bdyIndex.at(endPoint)); 
		endPoint--; 
		if (startPointbdyIndex.at(endPoint)]!=labelFlag1) 
			{ 
				bdySeg.push_back(nod2->bdyIndex.at(endPoint)); 
				endPoint--; 
			} 
			for (int j=0;j<=1;j++) 
			{ 
				if (startPoint<(endPoint-j)) 
					if	(Label[nod2->bdyIndex.at(endPoint-j)]!=labelFlag1) 
					{ 
						bdySeg.push_back(nod2->bdyIndex.at(endPoint-j)); 
					} 
			} 
			bdySegSet.push_back(bdySeg); 
			bdySeg.clear(); 
	} 
 
 
 
	for (int i=startPoint; i<=endPoint; i++) 
	{ 
		if (Label[nod2->bdyIndex.at(i)]!=labelFlag1) 
		{ 
			if (previousNormal) 
			{ 
				(*curveLength)++; 
				(*meanCurvature)+=nod2->curvature.at(i); 
			} 
			else  
			{ 
				// add one bdySeg; 
				bdySeg.push_back(nod2->bdyIndex.at(i)); 
				if (i+1<=endPoint) 
					if(Label[nod2->bdyIndex.at(i+1)]!=labelFlag1) 
					{ 
						i++; 
						bdySeg.push_back(nod2->bdyIndex.at(i)); 
					} 
					for (int j=1; j<=2; j++) 
					{ 
						if (i+1<=endPoint) 
							if(Label[nod2->bdyIndex.at(i+1)]!=labelFlag1) 
							{ 
								i++; 
								bdySeg.push_back(nod2->bdyIndex.at(i)); 
								(*curveLength)++; 
								(*meanCurvature)+=nod2->curvature.at(i); 
							} 
					} 
					bdySegSet.push_back(bdySeg); 
					bdySeg.clear(); 
 
					previousNormal=true; 
			} 
		} 
		else 
		{ 
			if (previousNormal) 
			{ 
				// add one bdySeg; 
				for (int j=1;j<=2;j++) 
				{ 
					if (i>=j) 
						if	(Label[nod2->bdyIndex.at(i-j)]!=labelFlag1) 
						{ 
							(*curveLength)--; 
							(*meanCurvature)-=nod2->curvature.at(i-j); 
							bdySeg.push_back(nod2->bdyIndex.at(i-j)); 
						} 
				} 
				for (int j=3;j<=4;j++) 
				{ 
					if (i>=j) 
						if	(Label[nod2->bdyIndex.at(i-j)]!=labelFlag1) 
						{ 
							bdySeg.push_back(nod2->bdyIndex.at(i-j)); 
						} 
				} 
				bdySegSet.push_back(bdySeg); 
				bdySeg.clear(); 
 
				previousNormal=false; 
			} 
		} 
	} 
 
	int p1,p2,x1,x2,y1,y2; 
	bool found; 
	while (!bdySegSet.empty()) 
	{ 
		bdySeg=bdySegSet.front(); 
		bdySegSet.pop_front(); 
		p1=bdySeg.front(); 
		x1=p1/width; 
		y1=p1%width; 
		found=false; 
		for (unsigned int i=0; i curvature; 
				for (int j=0; j curvature; 
			for (int j=0; j curveQue; 
	queue> curveSet;  
	int labelFlag=Label[nod->pixelIndex.front()]; 
	nod->meanCurvature=0; 
	nod->curveLength=0; 
	nod->bdyIndex.clear(); 
	nod->curvature.clear(); 
 
 
	for(int n=0; npixelSize; n++) 
	{ 
		isBoundary=checkInsideBoundary(nod->pixelIndex.at(n),labelFlag,Label,width,height); 
		if (isBoundary) 
		{ 
 
 
 
			getFourNeighbor(nod->pixelIndex.at(n), width, height, neighbors); 
			for (int i=0; i<4; i++) 
			{ 
				if (neighbors[i]!=-1) 
				{	 
					// Find starting point 
					isBoundary=checkOutsideBoundary(neighbors[i],labelFlag,Label,width,height); 
					if (isBoundary && boundaryMarked[neighbors[i]]==0) 
					{ 
						startingPt=neighbors[i]; 
						int currentPt = startingPt; 
						curveQue.push_front(currentPt); 
						boundaryMarked[currentPt]=1; 
						found=true; 
 
						// track the curve follow an arbitrary direction 
						while (found) 
						{ 
							found=false; 
							getNeighborReorder(currentPt, width, height, neighbors); 
							for(int k = 0; k<8; k++) 
							{ 
								if (neighbors[k]!=-1) 
									if (boundaryMarked[neighbors[k]]==0) 
									{ 
										isBoundary=checkOutsideBoundary(neighbors[k],labelFlag,Label,width,height); 
										if (isBoundary) 
										{ 
											currentPt=neighbors[k]; 
											curveQue.push_front(currentPt); 
											boundaryMarked[currentPt]=1; 
											found=true; 
											break; 
										} 
									} 
							} 
						} 
 
						// track another direction  
						currentPt=startingPt; 
						do  
						{ 
							found=false; 
							getNeighborReorder(currentPt, width, height, neighbors); 
							for(int k = 0; k<8; k++) 
							{ 
								if (neighbors[k]!=-1) 
									if (boundaryMarked[neighbors[k]]==0) 
									{ 
										isBoundary=checkOutsideBoundary(neighbors[k],labelFlag,Label,width,height); 
										if (isBoundary) 
										{ 
											currentPt=neighbors[k]; 
											curveQue.push_back(currentPt); 
											boundaryMarked[currentPt]=1; 
											found=true; 
											break; 
										} 
									} 
							} 
						} while (found); 
						curveSet.push(curveQue); 
						curveQue.clear(); 
 
					} 
				} 
			} 
		} 
	} 
 
	while (!curveSet.empty()) 
	{ 
		curveQue=curveSet.front(); 
		curveSet.pop(); 
		int boundarySize=curveQue.size(); 
		int* curveX=new int [boundarySize]; 
		int* curveY=new int [boundarySize]; 
 
		for (int i=0; ibdyIndex.push_back(curveQue.at(i)); 
		} 
		getCurvature(curveX,curveY,boundarySize,&(nod->curvature)); 
 
		delete [] curveX; 
		delete [] curveY; 
	} 
 
	for (unsigned int i=0; icurvature.size(); i++) 
		nod->meanCurvature+=nod->curvature.at(i); 
 
	nod->curveLength=nod->curvature.size(); 
	nod->meanCurvature/=nod->curveLength; 
} 
 
bool checkOutsideBoundary(int p, int labelFlag, int* Label, int width, int height) 
{ 
	int neighbors[4]; 
	if (Label[p]==labelFlag) 
		return false; 
 
	getFourNeighbor(p, width, height, neighbors); 
	for(int k = 0; k<4; k++) 
	{ 
		if (neighbors[k]!=-1) 
			if (Label[neighbors[k]]==labelFlag) 
				return true; 
	} 
	return false; 
} 
 
bool checkInsideBoundary(int p, int labelFlag, int* Label, int width, int height) 
{ 
	int neighbors[4]; 
	if (Label[p]!=labelFlag) 
		return false; 
 
	getFourNeighbor(p, width, height, neighbors); 
	for(int k = 0; k<4; k++) 
	{ 
		if (neighbors[k]!=-1) 
			if (Label[neighbors[k]]!=labelFlag) 
				return true; 
	} 
	return false; 
} 
 
 
void getCurvature(int* x, int* y, int size, deque * curvature) 
//x: the array of x-values 
//y: the array of y-values 
//size: the array size 
{ 
	float k; 
 
	if(size>1){ 
		int* xu = new int[size]; 
		int* yu = new int[size]; 
		int* xuu = new int[size]; 
		int* yuu =new int[size]; 
 
		xu[0]=(x[1]-x[0])*2; 
		yu[0]=(y[1]-y[0])*2; 
		xu[size-1]=(x[size-1]-x[size-2])*2; 
		yu[size-1]=(y[size-1]-y[size-2])*2; 
		for(int i=1; ipush_back(k); 
		} 
 
		delete[] xu; 
		delete[] xuu; 
		delete[] yu; 
		delete[] yuu;  
 
 
	} 
	else 
		curvature->push_back(0); 
 
} 
 
void getDCurvature(int* x, int* y, int size, deque * curvature) 
//x: the array of x-values 
//y: the array of y-values 
//size: the array size 
{ 
 
	if(size>1){ 
		int* xu = new int[size]; 
		int* yu = new int[size]; 
		int* xuu = new int[size]; 
		int* yuu = new int[size]; 
		float* k = new float [size];  
 
		xu[0]=(x[1]-x[0])*2; 
		yu[0]=(y[1]-y[0])*2; 
		xu[size-1]=(x[size-1]-x[size-2])*2; 
		yu[size-1]=(y[size-1]-y[size-2])*2; 
		for(int i=1; ipush_back(abs(k[i+1]-k[i])); 
		curvature->push_back(abs(k[0]-k[size-1])); 
 
		delete[] xu; 
		delete[] xuu; 
		delete[] yu; 
		delete[] yuu; 
		delete[] k; 
 
 
	} 
	else 
		curvature->push_back(0); 
 
} 
 
double autoThreshold(double *points, int pointsNum) 
{ 
//	unsigned char *label=new unsigned char [pointsNum]; 
	double thres; 
	double thresUpdate; 
	double s1,s2; 
	int n1,n2; 
 
	s1=0; 
	for (int i=0; i0.0001); 
 
	 
	return thres; 
 
} 
 
int getOptResult(double *interVariance,double *intraVariance, int n) 
{ 
 
	// calculate vector mean 
	double mInter=0; 
	double mIntra=0; 
	double maxInter=0; 
	for (int i=3; imaxInter) 
			maxInter=interVariance[i]; 
	} 
	mInter/=(n-3); 
	mIntra/=(n-3); 
  
	// calculate covariance 
	double v00=0; 
	double v01=0; 
	double v11=0; 
	double d1, d2; 
	for (int i=3; i