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

📄 inputwnd.cpp

📁 这是有关计算机人工智能方面的资料
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////
/*      工程:手写数字识别系统                                              */
/*      文件: InputWnd.cpp : 实现文件                                      */
/*      功能:输入终端和数据处理类                                          */
/*      作者:陈海艺                                                        */
/*      时间: 2004-6-23                                                    */
/*     Email:Iorikingdom@hotmail.com                                       */
/////////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "手写数字识别系统.h"
#include "InputWnd.h"
#include ".\inputwnd.h"


// CInputWnd

IMPLEMENT_DYNAMIC(CInputWnd,  CWnd)
CInputWnd::CInputWnd()
: m_bTrain(false)
{
	//背景色画刷
	m_brBack.CreateSolidBrush (RGB(255,255,255));

	//方块填充画刷
	m_brSquare.CreateSolidBrush (RGB(255,0,0));

	//网格线画刷
	m_hPen.CreatePen (PS_SOLID,1,RGB(0,192,192));
   	
	m_bInitDraw=false;
	
	//初始化输入矩阵
	for(int i=0;i<LEN;i++)
		for(int j=0;j<LEN;j++)
		{
			m_bArray[i][j]=false;
			m_InputArray[i][j]=0;       
		}
  
}

CInputWnd::~CInputWnd()
{
	if(m_hFile!=INVALID_HANDLE_VALUE)
	{
		if (m_bTrain){
			OVERLAPPED Overlapped={0};
			
			DATA d;
			
			memcpy(d.e ,e,sizeof(E)*10);
			memcpy(&(d.WE),&WE,sizeof(WEIGHT)); 
			
			//把训练过的权值写回文件
			::WriteFile (m_hFile,&d,sizeof(DATA),NULL,&Overlapped);
		}
	   ::CloseHandle(m_hFile);
	}
}

BEGIN_MESSAGE_MAP(CInputWnd, CWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

void CInputWnd::OnPaint()
{
	CPaintDC dc(this); // device context for painting
    
	//重绘信息
	DrawInputWnd(&dc);
	// TODO: 在此处添加消息处理程序代码
	// 不为绘图消息调用 CWnd::OnPaint()
}

// 画出输入框架
bool CInputWnd::DrawInputWnd(CPaintDC *pDC)
{
	
	CBrush *pOldBr=pDC->SelectObject (&m_brBack);
    float sizeHeight=0.0;
	float sizeWidth=0.0;
   	float newsize=0.0;
    
	this->GetClientRect(&m_rectThis);
    sizeHeight=m_rectThis.Height ()/LENF;//求出方块的长
	float x=0.0;
	sizeWidth=m_rectThis.Width ()/LENF;//方块的宽
	float y=0.0;

	if(m_bInitDraw==false){    //看方块是否已经被写上
   
	for(int i=0;i<LEN;i++)
	{
		for(int j=0;j<LEN;j++)
		{
           m_rectArray[i][j].left =x;
		   m_rectArray[i][j].right =m_rectArray[i][j].left+sizeWidth;
		   m_rectArray[i][j].top =y;
		   m_rectArray[i][j].bottom =m_rectArray[i][j].top+sizeHeight ;
		   y=y+sizeHeight;
		}
		y=0.0;
		x=x+sizeWidth;
	}
	      m_bInitDraw=true;
	}

	pDC->Rectangle (&m_rectThis);
	pDC->SelectObject (&m_hPen);

	
	
	newsize=0;

	for(int i=0;i<=LEN;i++,newsize+=sizeHeight)
	{
	  pDC->MoveTo (0,newsize);
	  pDC->LineTo (m_rectThis.Width (),newsize);       //画背景网格
	 
	}

	newsize=0;
	for(int i=0;i<=LEN;newsize+=sizeWidth,i++)
	{
	  pDC->MoveTo (newsize,0);
	  pDC->LineTo (newsize,m_rectThis.Height ());       //画背景网格
	}

	pDC->SelectObject (&m_brSquare);
	for(int i=0;i<LEN;i++)
		for(int j=0;j<LEN;j++)
		{
			if(m_bArray[i][j]==true)
				pDC->Rectangle (&m_rectArray[i][j]);     //填充小方块
		}

	pDC->SelectObject (pOldBr);
	return false;
}


void CInputWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
	for(int i=0;i<LEN;i++)
	{
		for(int j=0;j<LEN;j++)
		{
			if(m_rectArray[i][j].PtInRect (point)&&m_bArray[i][j]==false)
			{
			 m_bArray[i][j]=true;
             this->InvalidateRect (&m_rectArray[i][j]);
			 break;
			}
		}
	}
	
	CWnd::OnLButtonDown(nFlags, point);
}

void CInputWnd::OnMouseMove(UINT nFlags, CPoint point)
{

    if(nFlags==MK_LBUTTON)
	{
		for(int i=0;i<LEN;i++)
	{
		for(int j=0;j<LEN;j++)
		{
			if(m_rectArray[i][j].PtInRect (point)&&m_bArray[i][j]==false)
			{
			 m_bArray[i][j]=true;
             this->InvalidateRect (&m_rectArray[i][j]);
			 break;
			}
		}
	}
	}
	CWnd::OnMouseMove(nFlags, point);
}



// 获取经过调整的输入层数值,或者样本数值
bool CInputWnd::GetInput(int index)
{

//////////////////////////////////////////////////////////////////////////////
/*                       调整坐标使输入居中                                 */

	int iLeft=LEN,iRight=0,iTop=LEN,iBottom=0;

	for(int i=0;i<LEN;i++)
	{
		for(int j=0;j<LEN;j++)
		{
			if(m_bArray[i][j])
			{
               if (iTop>j)
				   iTop=j;             //识别方阵的最左
			   
			   if(iBottom<j)            
				   iBottom=j;           //方阵的最右
			   
			   if(iLeft>i)
				    iLeft=i;            //方阵的最上
			   
			   if(iRight<i)
				    iRight=i;         //方阵的最下
			}
		}
	}

   

    int xMiddle=0,yMiddle=0;
	xMiddle=(iRight-iLeft)/2+1;          
	yMiddle=(iBottom-iTop)/2+1;           

	iLeft=iLeft+xMiddle;              //中间点的x
	iTop=iTop+yMiddle;                //中间点的y



	int dx=iLeft-LEN/2;                  //求出坐标差
	int dy=iTop-LEN/2;                  //求出坐标差


	
	for(int i=0;i<LEN;i++)            //平移坐标
		for(int j=0;j<LEN;j++)
		  if(m_bArray[i][j])
			  m_InputArray[i-dx][j-dy]=1;

	for(int i=0;i<LEN;i++)
		for(int j=0;j<LEN;j++)
			m_bArray[i][j]=false;

	for(int i=0;i<LEN;i++)
		for(int j=0;j<LEN;j++)
			if(m_InputArray[i][j]==1)
              m_bArray[i][j]=true;
    
	this->Invalidate ();

	

	for(int i=0,t=0;i<LEN;i++)  
		for(int j=0;j<LEN;j++)
		{
			e[index].input[t]=(int )m_InputArray[i][j];//获取输入层的值
			t++;
		}

///////////////////////////////////////////////////////////////////////////
//                          初始化输出端                                 //
	
    
	if(index<10)
	{
	  for(int i=0;i<10;i++)
	    e[index].output [i]=0;

	  for(int k=0;k<index;k++);
	    e[index].output [k]=1;
	    e[index].Figure =index;

	  
	}
		
/////////////////////////////////////////////////////////////////////////////

	e[index].simpling =true;

	{//判断是否完成采样,如果完成的话可以进入训练或者识别阶段
	int i=0;
    for(i=0;i<10;i++)
		if(e[i].simpling==true)
          continue;
		else break;
	if(i==10)
       m_bTrain=true;

	}

	for(int i=0;i<LEN;i++)  
		for(int j=0;j<LEN;j++)
		{
			m_InputArray[i][j]=0;//清洁旧值
		}
	



	return false;
}

// 给输入的矩阵清零,用来下次输入
bool CInputWnd::ClearInput(void)
{
	for(int i=0;i<LEN;i++)
		for(int j=0;j<LEN;j++)
			m_InputArray[i][j]=0;
	
	return false;
}

// 初始化样本,如果存在文件信息从文件里面调入信息
bool CInputWnd::Initialization(void)
{
	OVERLAPPED Overlapped={0};
	DATA d;
	//判断是否存在文件来调入信息
	m_hFile=::CreateFile ("info.dat",
		                  GENERIC_READ|GENERIC_WRITE,
				          0,
				          NULL,
						  OPEN_EXISTING,
						  0,
				          NULL);

	if(m_hFile!=INVALID_HANDLE_VALUE)
	{
		if( !ReadFile(m_hFile,&d,sizeof(DATA),NULL,&Overlapped))
		{//文件为空或者存在其他原因的话用默认方式来权值初始化
			InitWeight();
		}

		m_bTrain=true;
		memcpy(e ,d.e,sizeof(E)*10);
	    memcpy(&WE,&(d.WE ),sizeof(WEIGHT)); 		
	}
	else
	//说明文件不存在,所以用默认信息来初值化
	{
		m_hFile=::CreateFile ("info.dat",
	                           GENERIC_READ|GENERIC_WRITE,
				               0,
				               NULL,							   
				               CREATE_NEW,
							   FILE_ATTRIBUTE_NORMAL,
				               NULL);
		if(m_hFile==INVALID_HANDLE_VALUE)
		{
			AfxMessageBox("未能够创建文件");
			exit(1);
		}
		else
		{
			InitWeight();
		}
	}
		


	return false;
}

// 训练函数,界面线程应该跟工作线程分开,这里为了省去麻烦,没有分开
int CInputWnd::Training(int index)
{//
	float a[M],o[P];
	float Err[P];
	float errsum=0;
	float tempsum=0;//总误差
	float in_j[M];
	float in_i[P];
   
for(;;)
//迭代到达到需要的精度
{
	errsum=0;
	for(int u=0;u<LEN;u++)
	{
	for(int j=0;j<M;j++)
	{
		in_j[j]=0;
		for(int k=0;k<N;k++)
		{
			in_j[j]=in_j[j]+WE.v[k][j]*e[u].input [k]; 
		}
		a[j]=FX(in_j[j]);//求出矩阵a
	}

	for(int i=0;i<P;i++)
	{
		in_i[i]=0;
		for(int j=0;j<M;j++)
		{
		   in_i[i]=in_i[i]+WE.w[j][i]*a[j];
		}
		o[i]=FX(in_i[i]);//求出输出矩阵o
	}

 	for(int i=0;i<P;i++)
	{
		Err[i]=e[u].output[i]-o[i];
        tempsum+=Err[i]*Err[i];
	}
    errsum+=tempsum/2.0;//样本误差
	tempsum=0;

	for(int j=0;j<M;j++)//输出层误差调整
	{
		for(int i=0;i<P;i++)
		{
			WE.w[j][i]+=A*a[j]*Err[i]*DFX(in_i[i]);
		}
	}

	float NewErr[M];    //隐层的误差

	for(int j=0;j<M;j++)
	{
	   float sum=0;
	   for(int i=0;i<P;i++)
	   {
		   sum+=WE.w[j][i]*DFX(in_i[i])*Err[i];
	   }
	   NewErr[j]=sum;

	}

	for(int k=0;k<N;k++)//隐层权值调整
	{
		for(int j=0;j<M;j++)
		{
			WE.v[k][j]+=A*e[u].input [k]*NewErr[j]*DFX(in_j[j]);
	    }
	}
	}

	if(errsum<precision)
		break;
}
	return 0;
}

// 识别数字
RESULT CInputWnd::Identification(void)
{
   float Err[P];
   float a[M];
   float o[P];
   RESULT result;
   result.result =-1;

   for(int c=0;c<P;c++)
   {

   for(int j=0;j<M;j++)
       {
	     float sum=0;
	     for(int k=0;k<N;k++)
		   sum+=WE.v [k][j]*e[10].input [k];
	   a[j]=FX(sum);
   }

   for(int i=0;i<P;i++)
   {
       float sum=0;	
	   for(int j=0;j<M;j++)
	   {
		   sum+=WE.w [j][i]*a[j];
	   }
	   o[i]=FX(sum);
   }

   float errsum=0;
   for(int i=0;i<P;i++)
   {
      Err[i]=o[i]-e[c].output [i];
	  errsum+=Err[i]*Err[i];
   }
   errsum=errsum/2.0;//求出误差

   int r=0;
   for(;r<P;r++)
   {
	   //如果达到精度要求就输出
      if(errsum>precision)
		break;
   }
   if(r==P){
	   result.result =c;
	   result.error =errsum;
	   return result;
   }
   }
   return result;
}

// 初始化权值
void CInputWnd::InitWeight(void)
{
	//伪随机种子
	srand((unsigned)time( NULL ) );	  
    
	for(int i=0;i<M;i++)
	  for(int j=0;j<P;j++)
	  {
	    //给隐层权值赋伪随机值
       
		 float rnd;
         rnd=(rand()%100)/100.0;
         WE.w [i][j]= rnd;//权值初始化。
	   }

	for(int i=0;i<N;i++)
	   for(int j=0;j<M;j++)
	  {
	    //给输出层权值赋伪随机值
	    float rnd;
	    rnd=(rand()%100)/100.0;
        WE.v [i][j]= rnd;//权值初始化。
	  }
}

⌨️ 快捷键说明

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