📄 watersheddoc.cpp
字号:
{
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 + -