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

📄 dlgclusterpatternrecog.cpp

📁 模式识别的作业代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	// TODO: Add your control notification handler code here
	int i;
	
	UpdateData(TRUE);
    
	if(m_nClassNumber>MAXIMIZE_CLASSNUM)
	{
		m_nClassNumber=MAXIMIZE_CLASSNUM;
		UpdateData(FALSE);
	}

	//设置初始聚类中心
	if(m_bFirst)
	{
		m_arrClusterCenterBackup.SetSize(m_nClassNumber);
		SetInitialClusterCenter(m_arrClusterCenterBackup);
		
		m_bFirst=false;
	}


	//调整初始分类中心
	m_arrClusterCenter.RemoveAll();
	m_arrClusterCenter.SetSize(m_nClassNumber);
	
	SetInitialClusterCenter(m_arrClusterCenter);
	
//	int nMin=min(m_arrClusterCenterBackup.GetSize(),m_nClassNumber);
//	for(i=0;i<nMin;i++)
//	{   //优化,可以加快下次迭代收敛的速度
//		m_arrClusterCenter[i]=m_arrClusterCenterBackup[i];
//	}

	//调整分类中心的备份
	m_arrClusterCenterBackup.RemoveAll();
	m_arrClusterCenterBackup.SetSize(m_nClassNumber);
//	for(i=0;i<m_nClassNumber;i++)
//	{   
//		m_arrClusterCenterBackup[i]=m_arrClusterCenter[i];
//	}
	
	

	//设定/修改分类矩阵
	m_matrixClassTag.Init(m_lImagePixelNumber,m_nClassNumber);

	((CButton*)GetDlgItem(IDC_BUTTON_PR_RECOGNIZE))->EnableWindow(TRUE);
	

	//绘制坐标轴及像素点坐标
	Draw2DimetionAxis(m_lpTabDC,m_nWhichColorNoUse);

	//随机产生各种分类的颜色
    tagRGBVal rgb;
	m_arrCenterColor.RemoveAll();
	m_arrCenterColor.SetSize(m_nClassNumber);
	double tmp;
	for (int j=0;j<m_nClassNumber;j++)
	{
		srand( (unsigned)time( NULL ) );
		rgb.R=rand() % 255;
		for(i=0;i<1000;i++) tmp=sqrt(sin(1.0));
		srand( (unsigned)time( NULL ) );
		rgb.G=rand() % 255;
		for(i=0;i<1000;i++) tmp=sqrt(sin(1.0));
		srand( (unsigned)time( NULL ) );
		rgb.B=rand() % 255;
		for(i=0;i<1000;i++) tmp=sqrt(sin(1.0));
		
		m_arrCenterColor.SetAt(j,rgb);
	}

	return;
}


//设置聚类中心的初始值
bool CDlgClusterPatternRecog::SetInitialClusterCenter(RGBValArray& arrClusterCenter)
{
	int nCenterNumber=arrClusterCenter.GetSize();
	
	if(nCenterNumber<=0)
		return FALSE;

	//这里随机指定聚类中心
	tagRGBVal rgb;
//	BYTE R,G,B;
			
	CImageSysZLF01App * lpCurrentApp=(CImageSysZLF01App *)AfxGetApp();
	CImageSysZLF01Doc * pDoc=lpCurrentApp->GetCurDocument();
	HDIB hDIB=pDoc->GetHDIB();
	
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
	int cxDIB = (int) ::DIBWidth(lpDIB);
	int cyDIB = (int) ::DIBHeight(lpDIB);


	int x,y;
	for(int i=0;i<nCenterNumber;i++)
	{
		//随机方式

		if(m_lCenterInitialMethod==CLUSTERING_INITIAL_CENTER_RANDOM)
		{
			srand( (unsigned)time( NULL ) );	
			x=rand() % m_nImageShowWidth;
			srand( (unsigned)time( NULL ) );
			y=rand() % m_nImageShowHeight;			
		}
		else
		{
			//顺序产生
//			x=cxDIB/2-i;y=cyDIB/2-1;

			x=i;y=1;

		}
		
		
		GetPrimitiveImageColorValue(x*y, rgb);        
		
//		rgb.R=rgb.G=rgb.B=0;
		
		arrClusterCenter.SetAt(i,rgb);
	}
	
	return true;
		
}


//聚类算法: K-平均值
//识别、更新显示
void CDlgClusterPatternRecog::OnButtonPrRecognize() 
{
	long i,j;
	int  nClass;  //类别
	long lNumber; //一类中的样本点数
	int  nTag;
	int K=1;      //当前迭代的步数
	double RSS=MAXIMIZE_RSS;   //误差平方和	
	tagRGBVal rgb;//当前颜色值
	tagSumOfDistance  sumrgb; //一类样本的和
	long x,y,z;//计算误差平方和用
	CString str;

	// 显示等待光标
	BeginWaitCursor();
	
	for(K=1;K<=m_nIterativeNumber;K++)
	{
	
		if(RSS<=(double)m_nThreshold)
		{				
			break;
		}

		//判断每个元素的所属类别
		for(i=0;i<m_lImagePixelNumber;i++)
		{
			GetPrimitiveImageColorValue(i,rgb);	
			
			nClass=JudgeSampleClass(rgb);

			//修改类别矩阵
			for(j=0;j<m_nClassNumber;j++)
			{
				m_matrixClassTag.SetElement(i,j,0);
			}
			m_matrixClassTag.SetElement(i,nClass,1);
		}


		//绘制识别后的图象
		//1:修改用于显示的图象
		ModifyImageWithClassInfo();
		//2:绘制新图 
		DrawRecognizedImage();
		

		m_nCurrentIterate=K;
		UpdateData(FALSE);
		GetDlgItem(IDC_EDIT4)->SendMessage(WM_PAINT);

		//修改聚类中心
		//1: 保存上一步的聚类中心
		for(i=0;i<m_nClassNumber;i++)
		{   
			m_arrClusterCenterBackup[i]=m_arrClusterCenter[i];
		}
		//2: 计算新聚类中心
		for(j=0;j<m_nClassNumber;j++)
		{   
			sumrgb.X=0;sumrgb.Y=0;sumrgb.Z=0;
			lNumber=1;
			
			for(i=0;i<m_lImagePixelNumber;i++)
			{
				nTag=int(m_matrixClassTag.GetElement(i,j));
				if(nTag==1)
				{
					GetPrimitiveImageColorValue(i,rgb);	

					sumrgb.X=sumrgb.X+(double)rgb.R;
					sumrgb.Y=sumrgb.Y+(double)rgb.G;
					sumrgb.Z=sumrgb.Z+(double)rgb.B;

					lNumber++;
				}
			}
			
			//计算中心
			rgb.R=(BYTE)(sumrgb.X/lNumber);
			rgb.G=(BYTE)(sumrgb.Y/lNumber);
			rgb.B=(BYTE)(sumrgb.Z/lNumber);
			
			m_arrClusterCenter[j]=rgb;
		}


		//更新坐标图中聚类中心的位置
		DrawClusterCnterWhenUpdate();


		//计算误差平方和
		RSS=0;
		for(j=0;j<m_nClassNumber;j++)
		{   
			x=m_arrClusterCenter[j].R-m_arrClusterCenterBackup[j].R;
			y=m_arrClusterCenter[j].G-m_arrClusterCenterBackup[j].G;
			z=m_arrClusterCenter[j].B-m_arrClusterCenterBackup[j].B;

			RSS=RSS+sqrt(pow(x,2)+pow(y,2)+pow(z,2));
		}

	} //主循环结束

	//绘制坐标图中聚类中心的分类信息
	DrawCCenterDisplayInfo();

	if(K>=m_nIterativeNumber)
	{
		AfxMessageBox("循环到达上限,未收敛!");
	}

	if(RSS<=(double)m_nThreshold)
	{				
		str.Format("迭代收敛!  迭代次数K=%d",K);
		AfxMessageBox(str);

	}

   	// 恢复正常光标
	EndWaitCursor();

}


//从原始图象取得颜色值
void CDlgClusterPatternRecog::GetPrimitiveImageColorValue(long Index, tagRGBVal& rgb)
{
	CImageSysZLF01App * lpCurrentApp=(CImageSysZLF01App *)AfxGetApp();
    CImageSysZLF01Doc * pDoc=lpCurrentApp->GetCurDocument();
	LPSTR lImagePrimitive=pDoc->m_pPrimitiveImage;

	LPSTR lpDBitsData=FindDIBBits(lImagePrimitive);
	
	LPSTR lpSrc=lpDBitsData+Index*3;
    
	//注意读取得顺序!  zlf  050329
	rgb.B=(BYTE)*lpSrc;
	rgb.G=(BYTE)*(lpSrc+1);
	rgb.R=(BYTE)*(lpSrc+2);

//	rgb.R=(BYTE)*lpSrc;
//	rgb.G=(BYTE)*(lpSrc+1);
//	rgb.B=(BYTE)*(lpSrc+2);


}


//判断样本的所属类别
int CDlgClusterPatternRecog::JudgeSampleClass(tagRGBVal rgb)
{
	long   Dis; //度量
	double minDis;//最小度量
	int i; 
	int ThisClass;

	minDis=MAXIMIZE_DISTANCE;
	for(i=0;i<m_nClassNumber;i++)
	{
        Dis=GetTwoSamplePointDistance(rgb,m_arrClusterCenter[i]);
		if(Dis<minDis)
		{
			minDis=Dis;

			ThisClass=i;
		}
	}

	return ThisClass;	
	
}

//得到两个样本点之间的距离
long CDlgClusterPatternRecog::GetTwoSamplePointDistance(tagRGBVal P1, tagRGBVal P2)
{
	//欧氏距离
	long x,y,z;
	long Dis;

	x=P1.R-P2.R;
	y=P1.G-P2.G;
	z=P1.B-P2.B;

	Dis=(LONG)sqrt(pow(x,2)+pow(y,2)+pow(z,2));

	return Dis;
}

//修改用于显示用的图象
void CDlgClusterPatternRecog::ModifyImageWithClassInfo()
{
	tagRGBVal rgb;
	int i,j;
	int nTag;

	//取得每个类的代表颜色
	//这里取聚类中心的颜色
	for(i=0;i<m_lImagePixelNumber;i++)
	{
		for(j=0;j<m_nClassNumber;j++)
		{   
			nTag=int(m_matrixClassTag.GetElement(i,j));
			if(nTag==1)
			{
				rgb=m_arrClusterCenter[j];

				//用得到的颜色值修改
				SetImageColorValue(i,rgb);
				break;
			}
			
		}

	}

}


void CDlgClusterPatternRecog::SetImageColorValue(long Index, tagRGBVal rgb)
{
	LPSTR lpSrc=m_lImageData+Index*3;
    
	//注意读取得顺序! 
	*lpSrc    =rgb.B;
	*(lpSrc+1)=rgb.G;
	*(lpSrc+2)=rgb.R;
	
//	*lpSrc    =rgb.R;
//	*(lpSrc+1)=rgb.G;
//	*(lpSrc+2)=rgb.B;
}

//绘制识别后的图象
void CDlgClusterPatternRecog::DrawRecognizedImage()
{
	CPaintDC dc(this); // device context for painting
    CImageSysZLF01App * lpCurrentApp=(CImageSysZLF01App *)AfxGetApp();
    CImageSysZLF01Doc * pDoc=lpCurrentApp->GetCurDocument();
	ASSERT_VALID(pDoc);
    
	// 获取DIB
	HDIB hDIB = pDoc->GetHDIB();
	 
	// 判断DIB是否为空
	// 判断DIB是否为空
	if (hDIB != NULL)
	{
		//获取: DIB宽度,高度
		LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
		int cxDIB = (int) ::DIBWidth(lpDIB);
		int cyDIB = (int) ::DIBHeight(lpDIB);
		::GlobalUnlock((HGLOBAL) hDIB);
		
		CRect rcDIB=CRect(0,0,cxDIB,cyDIB);
		
		::PaintDIB((HDC)dc.m_hDC, &m_rectImage, pDoc->GetHDIB(),&rcDIB, pDoc->GetDocPalette());
	}
	
	this->GetActiveWindow()->InvalidateRect(&m_rectImage,TRUE);
	
}

void CDlgClusterPatternRecog::OnButtonPrRestore() 
{
	// TODO: Add your control notification handler code here
	CImageSysZLF01App * lpCurrentApp=(CImageSysZLF01App *)AfxGetApp();
	
    CImageSysZLF01Doc * pDoc=lpCurrentApp->GetCurDocument();
	
	pDoc->RestorePrimitiveImage();
	
	//绘制原图像
	DrawRecognizedImage();
	
}


//绘制数据点
void CDlgClusterPatternRecog::DrawDataPoint(CDC *pDC, int nWhichNoUse)
{
	int NN=5; //数据间隔
	
	CImageSysZLF01App * lpCurrentApp=(CImageSysZLF01App *)AfxGetApp();
    CImageSysZLF01Doc * pDoc=lpCurrentApp->GetCurDocument();
	LPSTR lpBitsData=::FindDIBBits(pDoc->GetDIBPtr(pDoc->GetHDIB()));

	// 创建画笔对象_红色
	CPen* pPenRed  = new CPen;
	pPenRed->CreatePen(PS_SOLID,2,RGB(0,0,255));
	
	// 选中当前红色画笔,并保存以前的画笔
	CGdiObject* pOldPen = pDC->SelectObject(pPenRed);

	
	//绘制坐标点
	BYTE xv,yv;
	int i;
	int X0,Y0;

	X0=m_ptFigureXY0.x;
	Y0=m_ptFigureXY0.y;

   	pDC->SelectObject(pPenRed);
	switch (nWhichNoUse)
	{
		case COLOR_RED:
			for(i=0;i<m_nImageShowHeight*m_nImageShowWidth;i=i+3*NN)  //这里的3表示当前图像为24位真彩!!!
			{
				xv=*(lpBitsData+i +COLOR_GREEN); //Green
				yv=*(lpBitsData+i +COLOR_BLUE); //Blue

				pDC->MoveTo(X0+xv,Y0-yv);
				pDC->LineTo(X0+xv,Y0-yv);
			}
			break;
		case COLOR_GREEN:
			for(i=0;i<m_nImageShowHeight*m_nImageShowWidth;i=i+3*NN)  
			{
				xv=*(lpBitsData+i +COLOR_RED); //Red
				yv=*(lpBitsData+i +COLOR_BLUE); //Blue

				pDC->MoveTo(X0+xv,Y0-yv);
				pDC->LineTo(X0+xv,Y0-yv);
			}
			break;
		case COLOR_BLUE:
			for(i=0;i<m_nImageShowHeight*m_nImageShowWidth;i=i+3*NN)  
			{
				xv=*(lpBitsData+i +COLOR_RED); //Red
				yv=*(lpBitsData+i +COLOR_GREEN); //Green

				pDC->MoveTo(X0+xv,Y0-yv);
				pDC->LineTo(X0+xv,Y0-yv);
			}
	}

	// 恢复以前的画笔
	pDC->SelectObject(pOldPen);	
		
	// 删除新的画笔
	delete pPenRed;


}


//绘制聚类中心的移动轨迹
void CDlgClusterPatternRecog::DrawClusterCnterWhenUpdate()
{
	CPen* pPen  = new CPen;
//	CPen* pOldPen= new CPen;
//	pDC->SelectObject(pOldPen);	
	
	tagRGBVal rgbpre,rgbthis;//前一次迭代中心,后一次迭代中心

	BYTE xv,yv;
	int X0,Y0;
	X0=m_ptFigureXY0.x;
	Y0=m_ptFigureXY0.y;

	CDC* pDC=m_lpTabDC;
	
	
	for(int i=0;i<m_nClassNumber;i++)
	{
		rgbpre=m_arrClusterCenterBackup[i];
		rgbthis=m_arrClusterCenter[i];
		
		pPen->CreatePen(PS_SOLID,2,RGB(m_arrCenterColor[i].R,m_arrCenterColor[i].G,m_arrCenterColor[i].B));
		pDC->SelectObject(pPen);

		switch (m_nWhichColorNoUse)
		{
			case COLOR_RED:
				xv=rgbpre.G; //Green
				yv=rgbpre.B; //Blue
				pDC->MoveTo(X0+xv,Y0-yv);

				xv=rgbthis.G; //Green
				yv=rgbthis.B; //Blue
				pDC->LineTo(X0+xv,Y0-yv);

				break;
			case COLOR_GREEN:
				xv=rgbpre.R; //Green
				yv=rgbpre.B; //Blue
				pDC->MoveTo(X0+xv,Y0-yv);

				xv=rgbthis.R; //Green
				yv=rgbthis.B; //Blue
				pDC->LineTo(X0+xv,Y0-yv);

				break;
			case COLOR_BLUE:
				xv=rgbpre.R; //Green
				yv=rgbpre.G; //Blue
				pDC->MoveTo(X0+xv,Y0-yv);

				xv=rgbthis.R; //Green
				yv=rgbthis.G; //Blue
				pDC->LineTo(X0+xv,Y0-yv);
		}//END SWITCH

		pPen->DeleteObject();
	
	}

	delete pPen;

}


//绘制坐标图中聚类中心的分类信息
void CDlgClusterPatternRecog::DrawCCenterDisplayInfo()
{
	tagRGBVal rgbthis;
	BYTE xv,yv;
	int X0,Y0;
	CString str;

	X0=m_ptFigureXY0.x;
	Y0=m_ptFigureXY0.y;

	CDC* pDC=m_lpTabDC;

	for(int i=0;i<m_nClassNumber;i++)
	{
		rgbthis=m_arrClusterCenter[i];
		
		switch (m_nWhichColorNoUse)
		{
			case COLOR_RED:
				xv=rgbthis.G; //Green
				yv=rgbthis.B; //Blue
				
				str.Format("%d",i+1);
				pDC->TextOut(X0+xv,Y0-yv,str);

				break;
			case COLOR_GREEN:
				xv=rgbthis.G; 
				yv=rgbthis.B; 
				
				str.Format("%d",i+1);
				pDC->TextOut(X0+xv,Y0-yv,str);

				break;
			case COLOR_BLUE:
				xv=rgbthis.G; 
				yv=rgbthis.B; 
				
				str.Format("%d",i+1);
				pDC->TextOut(X0+xv,Y0-yv,str);

		}//end switch
	
	}

}


void CDlgClusterPatternRecog::OnRadioRandom() 
{
	// TODO: Add your control notification handler code here
	if(m_lCenterInitialMethod==CLUSTERING_INITIAL_CENTER_RANDOM)
		return;

	m_lCenterInitialMethod=CLUSTERING_INITIAL_CENTER_RANDOM;

	((CButton*)GetDlgItem(IDC_BUTTON_PR_RECOGNIZE))->EnableWindow(FALSE);
}

void CDlgClusterPatternRecog::OnRadioSequent() 
{
	// TODO: Add your control notification handler code here
	if(m_lCenterInitialMethod==CLUSTERING_INITIAL_CENTER_SEQUENT)
		return;

	m_lCenterInitialMethod=CLUSTERING_INITIAL_CENTER_SEQUENT;
	((CButton*)GetDlgItem(IDC_BUTTON_PR_RECOGNIZE))->EnableWindow(FALSE);
}

⌨️ 快捷键说明

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