?? cluster.cpp
字號:
// Cluster.cpp: implementation of the CCluster class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "mode.h"
#include "Cluster.h"
#include "math.h"
#include "DlgInfor.h"
#include "DlgMohu.h"
#include "DlgFuzzyDistance.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
const int MAX=1000;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCluster::CCluster()
{
centernum=0;
patternnum=0;
m_pattern=NULL;
m_center=NULL;
}
CCluster::~CCluster()
{
}
//***********************************************************//
//函數(shù)名稱 GetFeature()
//參數(shù) void
//返回值 void
//函數(shù)功能 將含有數(shù)據(jù)的圖像標(biāo)號、分割、編號及提取特征值,
// 特征值存入數(shù)組m_pattern中。
//************************************************************//
void CCluster::GetFeature()
{
////////////////////以下對數(shù)據(jù)區(qū)域標(biāo)號whx/////////////////////
BYTE * p_temp;
int stop;
int i,j;
int counter;//記錄相互獨(dú)立的連通區(qū)域的個數(shù);
int present;//記錄當(dāng)前點(diǎn)的值1,2,...,counter.
height=GetHeight();//圖像高
wide=GetWidth();//圖像寬,
stop=0;
counter=0;
p_temp=new BYTE[wide*height];//開辟一個臨時內(nèi)存區(qū)
memset(p_temp,255,wide*height);//置白
//從左到右、從上到下標(biāo)號
const int T=5;//T為閾值,RGB值小于該閾值被認(rèn)為是黑,
for(i=0; i<wide; i++)//將第零行置白
*(m_pData+(height-1)*wide+i)=255;
for(j=0;j<height;j++)//將第零列置白
*(m_pData+(height-j-1)*wide)=255;
for( j=1;j<height-1;j++) // 從第一行開始搜索
{
if(stop==1)//判斷連通區(qū)是否太多
break;
for( i=1;i<wide-1;i++) // 從第一列開始搜索
{
if(counter>255)
{
AfxMessageBox("連通區(qū)數(shù)目太多,請減少樣品個數(shù)");
stop=1;
return;
}
if(*(m_pData+(height-j-1)*wide+i)<T)//若當(dāng)前點(diǎn)為黑點(diǎn)
{
if(*(m_pData+(height-j-1+1)*wide+i+1)<T)//若當(dāng)前點(diǎn)的右上點(diǎn)為黑點(diǎn)
{
*(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1+1)*wide+i+1);//當(dāng)前點(diǎn)標(biāo)號應(yīng)該與右上點(diǎn)相同
present=*(p_temp+(height-j-1+1)*wide+i+1);//記錄當(dāng)前點(diǎn)的標(biāo)號
if(*(m_pData+(height-j-1)*wide+i-1)<T && *(p_temp+(height-j-1)*wide+i-1)!=present)//左前與右上點(diǎn)都為黑且標(biāo)號不同
{
int temp=*(p_temp+(height-j-1)*wide+i-1);//記錄左前點(diǎn)的標(biāo)號
if (present>temp)//當(dāng)前點(diǎn)標(biāo)號記錄兩者中的較小值
{
present=temp;
temp=*(p_temp+(height-j-1+1)*wide+i+1);
}
counter--;//合并左前和右上標(biāo)號,標(biāo)號總數(shù)減一
for(int m=1;m<=height-1;m++)
for(int n=1;n<=wide-1;n++)
{
if(*(p_temp+(height-m-1)*wide+n)==temp)//將較大標(biāo)號該成較小標(biāo)號
{
*(p_temp+(height-m-1)*wide+n)=present;
}
else if (*(p_temp+(height-m-1)*wide+n)>temp)//將較大標(biāo)號以后的所有標(biāo)號減一,以保持標(biāo)號的連續(xù)性
{
*(p_temp+(height-m-1)*wide+n)-=1;
}
}
}//end//左前
if( *(m_pData+(height-j-1+1)*wide+i-1)<T && *(p_temp+(height-j-1+1)*wide+i-1)!=present)//左上與右上點(diǎn)都為黑且標(biāo)號不同
{
counter--;//合并左上和右上標(biāo)號,標(biāo)號總數(shù)減一
int temp=*(p_temp+(height-j-1+1)*wide+i-1);//記錄左上點(diǎn)的值
if (present<temp)//當(dāng)前點(diǎn)標(biāo)號記錄兩者中的較小值
{
temp=present;
present=*(p_temp+(height-j-1+1)*wide+i-1);
}
for(int m=1;m<=height-1;m++)
for(int n=1;n<=wide-1;n++)
{
if(*(p_temp+(height-m-1)*wide+n)==present)//將較大標(biāo)號該成較小標(biāo)號
{
*(p_temp+(height-m-1)*wide+n)=temp;
}
else if (*(p_temp+(height-m-1)*wide+n)>present)//將較大標(biāo)號以后的所有標(biāo)號減一,以保持標(biāo)號的連續(xù)性
{
*(p_temp+(height-m-1)*wide+n)-=1;
}
}
present=temp;
}//end//左上
}
else if(*(m_pData+(height-j-1+1)*wide+i)<T)//當(dāng)前點(diǎn)黑,右上不為黑,正上為黑
{
*(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1+1)*wide+i);//當(dāng)前標(biāo)號=正上標(biāo)號
present=*(p_temp+(height-j-1+1)*wide+i);
}
else if(*(m_pData+(height-j-1+1)*wide+i-1)<T)//左上
{
*(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1+1)*wide+i-1);
present=*(p_temp+(height-j-1+1)*wide+i-1);
}
else if(*(m_pData+(height-j-1)*wide+i-1)<T)//左前
{
*(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1)*wide+i-1);
present=*(p_temp+(height-j-1)*wide+i-1);
}
else//產(chǎn)生新標(biāo)號
{
++counter;
present=counter;
*(p_temp+(height-j-1)*wide+i)=present;
}
}//end if
}// 列
}//end 行
// //////////////////////以上對數(shù)據(jù)區(qū)域標(biāo)號//////////////////////////
//////////////////////以下獲得各個樣品所在位置及編號///////////////////
patternnum=counter;//樣品總數(shù)
if (m_pattern!=NULL)
delete []m_pattern;
m_pattern=new Pattern[patternnum];
for( i=0;i<patternnum;i++)
{
m_pattern[i].index=i+1;
m_pattern[i].category=0;
m_pattern[i].lefttop.x=wide;
m_pattern[i].lefttop.y=height;
m_pattern[i].rightbottom.x=0;
m_pattern[i].rightbottom.y=0;
}
for(int t=1;t<=patternnum;t++)//記錄每個樣品(獨(dú)立連通區(qū)域)的左上、右下點(diǎn)坐標(biāo)
{
for(int j=1;j<height-1;j++)//搜索整幅圖像
for(int i=1;i<wide-1;i++)
{
if(*(p_temp+(height-j-1)*wide+i)==t)
{
if (m_pattern[t-1].lefttop.x>i)//get the lefttop point
m_pattern[t-1].lefttop.x=i;
if (m_pattern[t-1].lefttop.y>j)
m_pattern[t-1].lefttop.y=j;
if (m_pattern[t-1].rightbottom.x<i)//get the rightbottom point
m_pattern[t-1].rightbottom.x=i;
if (m_pattern[t-1].rightbottom.y<j)
m_pattern[t-1].rightbottom.y=j;
}
}
}
delete []p_temp;
//////////////////////以下獲得所有樣品特征放入m_pattern中//////////////////////////////
for ( i=0;i<patternnum;i++)//=patternnum
{
CalFeature(&m_pattern[i]);//調(diào)用函數(shù)計(jì)算第i號模板的值
}
//////////////////////以上獲得所有樣品特征放入m_pattern中//////////////////////////////
}
/***********************************************************
*函數(shù)名稱 CalFeature(CCluster::Pattern *m_pattern)
*參數(shù) CCluster::Pattern *m_pattern
*返回值 void
*函數(shù)功能 計(jì)算樣品m_pattern的特征值,存入m_pattern->feature中
*************************************************************/
void CCluster::CalFeature(CCluster::Pattern *m_pattern)
{
int w,h,count;
int i,j;
w=(int)(m_pattern->rightbottom.x-m_pattern->lefttop.x)/N;//特征值中每個特征的寬
h=(int)(m_pattern->rightbottom.y-m_pattern->lefttop.y)/N;//特征值中每個特征的高
for ( j=0;j<N;j++)//col
{
for ( i=0;i<N;i++)//line
{
count=0;//每個特征內(nèi)黑點(diǎn)的個數(shù)
for(int m= height-m_pattern->rightbottom.y+h*j;m<height-m_pattern->rightbottom.y+h*j+h;m++)//col
for (int n=m_pattern->lefttop.x+i*w; n<m_pattern->lefttop.x+i*w+w; n++)//line
if (*(m_pData+m*wide+n)==0)
count++;
m_pattern->feature[j*N+i]=(double)count/(double)(w*h);
}
}
}
/*********************************************************
*函數(shù)名稱 CalCenter(CCluster::Center *pcenter)
*參數(shù) CCluster::Center *pcenter
*返回值 void
*函數(shù)功能 計(jì)算中心pcenter的特征值(本類所有樣品的均值),及樣品個數(shù)
************************************************************/
void CCluster::CalCenter(CCluster::Center *pcenter)
{
double temp[N*N];//臨時存儲中心的特征值
int a=0;//記錄該類中元素個數(shù)
for (int i=0;i<N*N;i++)//中心清空
temp[i]=0;
for (i=0;i<patternnum;i++)
if (m_pattern[i].category==pcenter->index)//累加中心所有樣品
{
a++;
for (int j=0;j<N*N;j++)
temp[j]+=m_pattern[i].feature[j];
}
pcenter->patternnum=a;
for ( i=0;i<N*N;i++)
if(a!=0)
{
pcenter->feature[i]=(double)(temp[i]/(double)a);//取均值
}
else
{
pcenter->feature[i]=temp[i];
}
}
/***********************************************************
*函數(shù)名稱 GetDistance( CCluster::Pattern pattern1, CCluster::Pattern pattern2, const int distype)
*參數(shù) CCluster::Pattern pattern1 樣品1
* CCluster::Pattern pattern2 樣品2
* const int distype 距離模式 1:歐氏距離;2:夾角余弦距離;
* 3:特征是二值時的夾角余弦距離;4:具有二值特征的Tanimoto測度
*返回值 double
*函數(shù)功能 計(jì)算樣品1和樣品2間的距離,距離模式由參數(shù)distype給定
*************************************************************/
double CCluster::GetDistance( CCluster::Pattern pattern1, CCluster::Pattern pattern2, const int distype)
{
double result;
result=0;
if (distype==1)//歐氏距離
{
for (int i=0; i<N*N; i++)
result+=(pattern1.feature[i]-pattern2.feature[i])*(pattern1.feature[i]-pattern2.feature[i]);
return (double)sqrt(result);
}
else if (distype==2)//夾角余弦
{
double a,b1,b2;
a=0;
b1=0;
b2=0;
for (int i=0; i<N*N; i++)
{
a+=pattern1.feature[i]*pattern2.feature[i];
b1+=pattern1.feature[i]*pattern1.feature[i];
b2+=pattern2.feature[i]*pattern2.feature[i];
}
if (b2*b1!=0)
result=a/sqrt(b1*b2);
else
{
return -1;
}
return (1-result);
}
else if (distype==3)//二值夾角余弦
{
int *t1,*t2;
int a,b1,b2;
a=0;b1=0;b2=0;
t1=new int [N*N];
t2=new int [N*N];
for(int i=0; i<N*N; i++)
{
t1[i]=pattern1.feature[i]>0.2? 1:0;
t2[i]=pattern2.feature[i]>0.2? 1:0;
}
for ( i=0; i<N*N; i++)
{
a+=t1[i]*t2[i];
b1+=t1[i]*t1[i];
b2+=t2[i]*t2[i];
}
delete []t1;
delete []t2;
if (b2*b1!=0)
result=(double)(a/sqrt(b1*b2));
else
{
return -1;
}
return (1-result);
}
else if (distype==4)//Tanimoto
{
int *t1,*t2;
int a,b1,b2;
a=0;b1=0;b2=0;
t1=new int [N*N];
t2=new int [N*N];
for(int i=0; i<N*N; i++)
{
t1[i]=pattern1.feature[i]>0.2? 1:0;
t2[i]=pattern2.feature[i]>0.2? 1:0;
}
for ( i=0; i<N*N; i++)
{
a+=t1[i]*t2[i];
b1+=t1[i]*t1[i];
b2+=t2[i]*t2[i];
}
delete []t1;
delete []t2;
if ((b2*b1-a)!=0)
result=(double)(a/(b1+b2-a));
else
{
return -1;
}
return (1-result);
}
else
return -1;
}
/***************************************************************
*函數(shù)名稱 GetDistance(CCluster::Pattern pattern, CCluster::Center center, const int distype)
*參數(shù) CCluster::Pattern pattern 樣品
* CCluster::Center center 中心
* const int distype 距離模式 1:歐氏距離;2:夾角余弦距離;
* 3:特征是二值時的夾角余弦距離;
* 4:具有二值特征的Tanimoto測度
*返回值 double
*函數(shù)功能 計(jì)算樣品和聚類中心間的距離,距離模式由distype給定
************************************************************/
double CCluster::GetDistance(CCluster::Pattern pattern, CCluster::Center center, const int distype)
{
double result;
result=0;
if (distype==1)//歐氏距離
{
for (int i=0; i<N*N; i++)
result+=(pattern.feature[i]-center.feature[i])*(pattern.feature[i]-center.feature[i]);
return (double)sqrt(result);
}
else if (distype==2)//夾角余弦
{
double a,b1,b2;
a=0;
b1=0;
b2=0;
for (int i=0; i<N*N; i++)
{
a+=pattern.feature[i]*center.feature[i];
b1+=pattern.feature[i]*pattern.feature[i];
b2+=center.feature[i]*center.feature[i];
}
if (b2*b1!=0)
result=a/sqrt(b1*b2);
else
{
return -1;
}
return (1-result);
}
else if (distype==3)//二值夾角余弦
{
int *t1,*t2;
int a,b1,b2;
a=0;b1=0;b2=0;
t1=new int [N*N];
t2=new int [N*N];
for(int i=0; i<N*N; i++)
{
t1[i]=pattern.feature[i]>0.2? 1:0;
t2[i]=center.feature[i]>0.2? 1:0;
}
for ( i=0; i<N*N; i++)
{
a+=t1[i]*t2[i];
b1+=t1[i]*t1[i];
b2+=t2[i]*t2[i];
}
delete []t1;
delete []t2;
if (b2*b1!=0)
result=a/sqrt(b1*b2);
else
{
return -1;
}
return (1-result);
}
else if (distype==4)//Tanimoto
{
int *t1,*t2;
int a,b1,b2;
a=0;b1=0;b2=0;
t1=new int [N*N];
t2=new int [N*N];
for(int i=0; i<N*N; i++)
{
t1[i]=pattern.feature[i]>0.2? 1:0;
t2[i]=center.feature[i]>0.2? 1:0;
}
for ( i=0; i<N*N; i++)
{
a+=t1[i]*t2[i];
b1+=t1[i]*t1[i];
b2+=t2[i]*t2[i];
}
delete []t1;
delete []t2;
if ((b2*b1-a)!=0)
result=(double)(a/(b1+b2-a));
else
{
return -1;
}
return (1-result);
}
else
return -1;
}
/*************************************************************
*函數(shù)名稱 GetDistance(CCluster::Center mCenter1,CCluster::Center mCenter2,int distype)
*參數(shù) CCluster::Center mCenter1 中心1
* CCluster::Center mCenter2 中心2
* const int distype 距離模式 1:歐氏距離;2:夾角余弦距離;
* 3:特征是二值時的夾角余弦距離;
* 4:具有二值特征的Tanimoto測度
*返回值 double
*函數(shù)功能 計(jì)算兩個聚類中心間的距離,距離模式由distype給定
*************************************************************/
double CCluster::GetDistance(CCluster::Center mCenter1,CCluster::Center mCenter2,int distype)
{
double result;
result=0;
if (distype==1)//歐氏距離
{
for ( int m=0;m<N*N;m++)
result+=(mCenter1.feature[m]-mCenter2.feature[m])*(mCenter1.feature[m]-mCenter2.feature[m]);
return (double)sqrt(result);
}
else if (distype==2)//夾角余弦
{
double a,b1,b2;
a=0;
b1=0;
b2=0;
for (int i=0; i<N*N; i++)
{
a+=mCenter1.feature[i]*mCenter2.feature[i];
b1+=mCenter1.feature[i]*mCenter1.feature[i];
b2+=mCenter2.feature[i]*mCenter2.feature[i];
}
if (b2*b1!=0)
result=a/sqrt(b1*b2);
else
{
return -1;
}
return (1-result);
}
else if (distype==3)//二值夾角余弦
{
int *t1,*t2;
int a,b1,b2;
a=0;b1=0;b2=0;
t1=new int [N*N];
t2=new int [N*N];
for(int i=0; i<N*N; i++)
{
t1[i]=mCenter1.feature[i]>0.2? 1:0;
t2[i]=mCenter2.feature[i]>0.2? 1:0;
}
for ( i=0; i<N*N; i++)
{
a+=t1[i]*t2[i];
b1+=t1[i]*t1[i];
b2+=t2[i]*t2[i];
}
delete []t1;
delete []t2;
if (b2*b1!=0)
result=(double)(a/sqrt(b1*b2));
else
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -