⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 watersheddoc.cpp

📁 分水岭算法
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	{
		if (!rginfoarr[i].isflag)
		{
			counttemp ++;
		}
	}
	
	rgnum = counttemp;
	
	delete [] neiarr; neiarr = NULL;
}


BOOL CWaterShedDoc::LuvToRgb(FLOAT *luvData, INT width, INT height, BYTE *rgbData)
{
	if (NULL == rgbData)
	{
		CString tempstr;
		tempstr.Format("传入内存未分配,在MyColorSpace::RGBtoHSV");
		AfxMessageBox(tempstr,NULL,MB_OK);
		return FALSE;		
	}
	
	int i,j;
	INT r,g,b;
	FLOAT l, u, v;
	unsigned long pos;
	
	for(i=0;i<height;i++)
	{
		for (j=0;j<width;j++)
		{
			pos = (i*width+j) * 3;
			l = luvData[pos];
			u = luvData[pos+1];
			v = luvData[pos+2];
			
			Luv2Rgb(l, u, v, r, g, b);
			rgbData[pos] = b;
			rgbData[pos+1] = g;
			rgbData[pos+2] = r;			
		}
	}
	return TRUE;
}

BOOL CWaterShedDoc::Luv2Rgb(FLOAT l, FLOAT u, FLOAT v, INT &r, INT &g, INT &b)
{
	if(l<0.1)
	{
		r = g = b =0;
	}
	else
	{
		float my_x, my_y, my_z;
		if(l < 8.0)
			my_y = (FLOAT) ( Yn * l / 903.3 );
		else
			my_y = (FLOAT) ( Yn * pow((l + 16.0) / 116.0, 3) );
		
		float u_prime = u / (13 * l) + Un_prime;
		float v_prime = v / (13 * l) + Vn_prime;
		
		my_x = 9 * u_prime * my_y / (4 * v_prime);
		my_z = (12 - 3 * u_prime - 20 * v_prime) * my_y / (4 * v_prime);
		
		r =int((RGB[0][0]*my_x + RGB[0][1]*my_y + RGB[0][2]*my_z)*255.0);
		g =int((RGB[1][0]*my_x + RGB[1][1]*my_y + RGB[1][2]*my_z)*255.0);
		b =int((RGB[2][0]*my_x + RGB[2][1]*my_y + RGB[2][2]*my_z)*255.0);
		
		if(r>255) r=255;
		else if(r<0) r=0;
		
		if(g>255) g=255;
		else if(g<0) g=0;
		
		if(b>255) b=255;
		else if(b<0) b=0;
	}
	
	return TRUE;
}

//刷新当前点的所有相邻区;
void CWaterShedDoc::AddNeiOfCur(INT curid, INT left, INT right, INT up, INT down, INT *flag, CString *neiarr)
{
	INT leftid, rightid, upid, downid;
	leftid = rightid = upid = downid = curid;
	if (left>=0)
	{
		leftid = flag[left];
		if (leftid!=curid)
		{
			//邻点属于另一区, 加邻域点信息;
			AddNeiRgn(curid, leftid, neiarr);
		}
	}
	if (right>0)
	{
		rightid = flag[right];
		if (rightid!=curid)
		{
			//邻点属于另一区, 加邻域点信息;
			AddNeiRgn(curid, rightid, neiarr);
		}
	}
	if (up>=0)
	{
		upid = flag[up];
		if (upid!=curid)
		{
			//邻点属于另一区, 加邻域点信息;
			AddNeiRgn(curid, upid, neiarr);
		}
	}
	if (down>0)
	{
		downid = flag[down];
		if (downid!=curid)
		{
			//邻点属于另一区, 加邻域点信息;
			AddNeiRgn(curid, downid, neiarr);
		}
	}
}

void CWaterShedDoc::AddNeiRgn(INT curid, INT neiid, CString *neiarr)
//增加neiid为curid的相邻区
{
	CString tempneis = neiarr[curid];//当前的相邻区;
	CString toaddstr;
	toaddstr.Format("%d ", neiid);
	
	INT temppos = tempneis.Find(toaddstr, 0);
	while (temppos>0 && neiarr[curid].GetAt(temppos-1)!=' ')
	{
		temppos = neiarr[curid].Find(toaddstr, temppos+1);
	}
	
	if ( temppos<0 )
	{
		//当前相邻区中没有tempneis,则加入
		neiarr[curid] += toaddstr;
	}
}

//找到idint最终所合并到的区号;
int CWaterShedDoc::FindMergedRgn(INT idint, INT *mergearr)
{
	INT outid = idint;
	while ( mergearr[outid] > 0 )
	{
		outid = mergearr[outid];
	}
	return outid;
}

int CWaterShedDoc::FindNearestNei(INT curid, CString neistr, MyRgnInfo *rginfoarr, INT *mergearr)
//寻找neistr中与curid最接近的区,返回该区id号;
{
	INT outid = -1;
	DOUBLE mindis = 999999;
	FLOAT cl, cu, cv;
	cl = rginfoarr[curid].l;//当前区的LUV值;
	cu = rginfoarr[curid].u;
	cv = rginfoarr[curid].v;
	
	CString tempstr = neistr;//用于本函数内部处理;
	while (tempstr.GetLength()>0)
	{
		INT pos = tempstr.Find(" ");
		ASSERT(pos>=0);
		CString idstr = tempstr.Left(pos);
		tempstr.Delete(0, pos+1);
		
		INT idint = (INT) strtol(idstr, NULL, 10);
		//判断该区是否已被合并,若是,则一直找到该区当前的区号;
		idint = FindMergedRgn(idint, mergearr);
		if (idint==curid)
		{
			continue;//这个邻区已被合并到当前区,跳过;
		}
		FLOAT tl, tu, tv;
		tl = rginfoarr[idint].l;//当前处理的邻区的LUV值;
		tu = rginfoarr[idint].u;
		tv = rginfoarr[idint].v;
		DOUBLE tempdis = pow(tl-cl, 2) 
			+ pow(tu-cu, 2) + pow(tv-cv, 2);
		if (tempdis<mindis)
		{
			mindis = tempdis;//最大距离和对应的相邻区ID;
			outid = idint;
		}		
	}
	
	return outid;
}

//将nearid合并到curid中去,更新合并后的区信息,并记录该合并;
void CWaterShedDoc::MergeTwoRgn(INT curid, INT nearid, CString *neiarr, MyRgnInfo *rginfoarr, INT *mergearr)
{
	//将区信息中nearid对应项的标记设为已被合并;
	rginfoarr[nearid].isflag = TRUE;
	//更新合并后的LUV信息;
	LONG ptincur = rginfoarr[curid].ptcount;
	LONG ptinnear = rginfoarr[nearid].ptcount;
	DOUBLE curpercent = (FLOAT)ptincur / (FLOAT)(ptincur+ptinnear);
	rginfoarr[curid].ptcount = ptincur + ptinnear;
	rginfoarr[curid].l = (FLOAT) ( curpercent * rginfoarr[curid].l
		+ (1-curpercent) * rginfoarr[nearid].l );
	rginfoarr[curid].u = (FLOAT) ( curpercent * rginfoarr[curid].u
		+ (1-curpercent) * rginfoarr[nearid].u );
	rginfoarr[curid].v = (FLOAT) ( curpercent * rginfoarr[curid].v
		+ (1-curpercent) * rginfoarr[nearid].v );
	//将nearid的邻域加到curid的邻域中去;
	AddBNeiToANei(curid, nearid, neiarr, mergearr);
	//记录该合并;
	mergearr[nearid] = curid;
}

//将nearid的邻域加到curid的邻域中去;
void CWaterShedDoc::AddBNeiToANei(INT curid, INT nearid, CString *neiarr, INT *mergearr)
{
	//先从curid的邻区中把nearid删去;
	/*
	CString tempstr;
	tempstr.Format("%d ", nearid);
	INT temppos = neiarr[curid].Find(tempstr, 0);
	while (temppos>0 && neiarr[curid].GetAt(temppos-1)!=' ')
	{
	temppos = neiarr[curid].Find(tempstr, temppos+1);
	}
	if (temppos>=0)
	{
	//否则邻近区为合并过来的区,忽略;
	neiarr[curid].Delete(temppos, tempstr.GetLength());
	}
	*/
    //将nearid的邻区依次加到curid的邻区中去;
	CString neistr = neiarr[nearid];
	CString curstr = neiarr[curid];
	//一般说来,极小区的邻域应该较少,因此,为着提高合并速度,将
	//curstr加到neistr中去,然后将结果赋给neiarr[curid];
	while ( curstr.GetLength()>0 )
	{
		INT pos = curstr.Find(" ");		
		ASSERT(pos>=0);
		CString idstr = curstr.Left(pos);
        curstr.Delete(0, pos+1);
		INT idint = (INT) strtol(idstr, NULL, 10);
		idint = FindMergedRgn(idint, mergearr);
		idstr += " ";
		if ( (idint == curid) || (idint == nearid) )
		{
			continue;//本区不与本区相邻;
		}else
		{
			if ( neistr.Find(idstr, 0) >= 0 )
			{
				continue;
			}else
			{
				neistr += idstr;//加到邻区中去;
			}
		}		
	}
	neiarr[curid] = neistr;
	/*
	CString toaddneis = neiarr[nearid];
	while (toaddneis.GetLength()>0)
	{
	INT pos = toaddneis.Find(" ");		
	ASSERT(pos>=0);
	CString idstr = toaddneis.Left(pos);
	toaddneis.Delete(0, pos+1);
	INT idint = (INT) strtol(idstr, NULL, 10);
	idint = FindMergedRgn(idint, mergearr);
	idstr += " ";
	if ( (idint == curid) || (idint == nearid) )
	{
	continue;//本区不与本区相邻;
	}else
	{
	if ( neiarr[curid].Find(idstr, 0) >= 0 )
	{
				continue;
				}else
				{
				neiarr[curid] += idstr;//加到邻区中去;
				}
				}		
				}
	*/
}

#define NearMeasureBias 200.0//判定区域颜色相似的阈值;
void CWaterShedDoc::MergeNearest(INT curid, MyRgnInfo *rginfoarr, CString *neiarr, INT *mergearr)
//合并相似区域;
{
	//依次处理各个邻域,若相似,则合并;
	//CString neistr = neiarr[curid];
	FLOAT cl, cu, cv;
	cl = rginfoarr[curid].l;//当前区的LUV值;
	cu = rginfoarr[curid].u;
	cv = rginfoarr[curid].v;
	BOOL loopmerged = TRUE;//一次循环中是否有合并操作发生,若无,则退出循环;
	
	while (loopmerged)
	{
		loopmerged = FALSE;
		CString tempstr = neiarr[curid];//用于本函数内部处理;
		while (tempstr.GetLength()>0)
		{
			INT pos = tempstr.Find(" ");
			ASSERT(pos>=0);
			CString idstr = tempstr.Left(pos);
			tempstr.Delete(0, pos+1);
			
			INT idint = (INT) strtol(idstr, NULL, 10);
			//判断该区是否已被合并,若是,则一直找到该区当前的区号;
			idint = FindMergedRgn(idint, mergearr);
			if (idint==curid)
			{
				continue;//这个邻区已被合并到当前区,跳过;
			}
			FLOAT tl, tu, tv;
			tl = rginfoarr[idint].l;//当前处理的邻区的LUV值;
			tu = rginfoarr[idint].u;
			tv = rginfoarr[idint].v;
			DOUBLE tempdis = pow(tl-cl, 2) 
				+ pow(tu-cu, 2) + pow(tv-cv, 2);
			if (tempdis<NearMeasureBias)
			{
				MergeTwoRgn(curid, idint, neiarr, rginfoarr, mergearr);
				cl = rginfoarr[curid].l;//当前区的LUV值刷新;
				cu = rginfoarr[curid].u;
				cv = rginfoarr[curid].v;
				loopmerged = TRUE;
			}		
		}
	}
}

//基于表转换,将位图图像数据转换为LUV数据, 修改自D. Comaniciu, P. Meer,
//Robust Analysis of Feature Spaces: Color Image Segmentation 的相应代码

BOOL CWaterShedDoc::RgbtoLuvPcm(BYTE *inDatas, int width, int height, MyLUV *luvbuff)	
{
	int x, y, z, my_temp;
	
	float l_star, u_star, v_star;
	float u_prime, v_prime;
	//register int temp_col, temp_index, temp_ind;
	register int j;//,k;
	
	int a00=XYZ[0][0], a01=XYZ[0][1], a02=XYZ[0][2];
	int a10=XYZ[1][0], a11=XYZ[1][1], a12=XYZ[1][2];
	int a20=XYZ[2][0], a21=XYZ[2][1], a22=XYZ[2][2];
	
	int *A00 = new int[MAXV]; int *A01 = new int[MAXV]; int *A02 = new int[MAXV];
	int *A10 = new int[MAXV]; int *A11 = new int[MAXV]; int *A12 = new int[MAXV];
	int *A20 = new int[MAXV]; int *A21 = new int[MAXV]; int *A22 = new int[MAXV];
	
	for(j=0; j<MAXV; j++)
	{
		A00[j]=a00*j; A01[j]=a01*j; A02[j]=a02*j;
		A10[j]=a10*j; A11[j]=a11*j; A12[j]=a12*j;
		A20[j]=a20*j; A21[j]=a21*j; A22[j]=a22*j;
	}
	
	float *my_pow = new float[MAXV];
	for(j=0; j<MAXV; j++)
		my_pow[j]= (FLOAT) ( 116.0 * pow(j/255.0, 0.3333333) - 16 );
	
	for ( j = 0; j < width*height; j++)
	{
		INT R = inDatas[j*3+2];
		INT G = inDatas[j*3+1];
		INT B = inDatas[j*3];
		
		x = A00[R] + A01[G] + A02[B];
		y = A10[R] + A11[G] + A12[B];
		z = A20[R] + A21[G] + A22[B];
		
		float  tval = (FLOAT) ( y / 2550000.0 ); //Yn==1
		if ( tval >  Lt)  l_star = my_pow[(int)(tval*255+0.5)];
		else  l_star = (FLOAT) ( 903.3 * tval );
		
		my_temp = x + 15 * y + 3 * z;
		if(my_temp)
		{
			u_prime = (float)(x << 2) / (float)(my_temp);
			v_prime = (float)(9 * y) / (float)(my_temp);
		}
		else
		{
			u_prime = 4.0;
			v_prime = (FLOAT) ( 9.0/15.0 );
		}
		
		tval = 13*l_star;
		u_star = tval * (u_prime - Un_prime); // Un_prime = 0.1978
		v_star = tval * (v_prime - Vn_prime); // Vn_prime = 0.4683
		
		luvbuff[j].l = l_star;
		luvbuff[j].u = u_star;
		luvbuff[j].v = v_star;
	}
	
	delete [] my_pow;
	delete [] A22; delete [] A21; delete [] A20;
	delete [] A12; delete [] A11; delete [] A10;
	delete [] A02; delete [] A01; delete [] A00;
	
	return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -