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

📄 数字识别view.cpp

📁 利用bp网络进行数字识别的示例程序
💻 CPP
字号:
// 数字识别View.cpp : implementation of the CMyView class
//

#include "stdafx.h"
#include "数字识别.h"
#include <math.h>
#include "数字识别Doc.h"
#include "数字识别View.h"
#include <fstream.h>
#include <time.h>
#include <stdlib.h>
#include "backprop.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMyView

IMPLEMENT_DYNCREATE(CMyView, CView)

BEGIN_MESSAGE_MAP(CMyView, CView)
	//{{AFX_MSG_MAP(CMyView)
	ON_COMMAND(IDC_INPUT, OnInput)
	ON_COMMAND(IDC_RANDOM, OnRandom)
	ON_COMMAND(IDC_CLASSIFY, OnClassify)
	ON_COMMAND(IDC_NOISY, OnNoisy)
	ON_COMMAND(IDC_RECOG, OnRecog)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyView construction/destruction

CMyView::CMyView()
{
	// TODO: add construction code here
	draw=false;

}

CMyView::~CMyView()
{
}

BOOL CMyView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMyView drawing

void CMyView::OnDraw(CDC* pDC)
{
	CMyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	if(draw==TRUE)
	 DrawNumber(m_ipDrawNum);
}

/////////////////////////////////////////////////////////////////////////////
// CMyView printing

BOOL CMyView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CMyView diagnostics

#ifdef _DEBUG
void CMyView::AssertValid() const
{
	CView::AssertValid();
}

void CMyView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMyDoc* CMyView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
	return (CMyDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMyView message handlers

void CMyView::OnInput() 
{
	// TODO: Add your command handler code here	// 打开文件
	ifstream data("learn.dat", ios::nocreate);
	ifstream test("test.dat", ios::nocreate);

	// 检查文件的有效性
	if (!test || !data) 
	{
		MessageBox("No learning or test data present.", "Cannot run...",
			MB_OK | MB_ICONERROR);
	}

	// 读文件
	for(int i=0;i<NN_NUMBERS;i++) 
	{
		for(int j=0;j<NN_RESX * NN_RESY;j++) 
		{
			int onoff;
			test >> onoff;
			m_bTestData[i][j] = onoff;

			data >> onoff;
			m_bNumbers[i][j] = onoff;
		}
	}

	// 设置初始要画的数字指针
	m_ipDrawNum = &m_bNumbers[0][0];
    DrawNumber(	m_ipDrawNum);
	draw=true;
  
	
}

void CMyView::DrawNumber(int *cell)
{
	CPoint tl(100,100);
	int ix=100;
	
	CDC *dc;
	dc=this->GetDC();
	CPen pen;
	pen.CreatePen(PS_DOT, 1, RGB(127,0,0));
	CPen *pOldPen = dc->SelectObject(&pen);
	for(int i=0;i<9;i++)
	{
		pOldPen=dc->SelectObject(&pen);
  
		dc->MoveTo(tl.x, tl.y);
		dc->LineTo(tl.x+50, tl.y);
		
		dc->LineTo(tl.x+50, tl.y+70);
		
		dc->LineTo(tl.x, tl.y+70);
		
		dc->LineTo(tl.x, tl.y);
        
          
		dc->SelectObject(pOldPen);
		// 画数字
		CPoint p;
		p.x=tl.x;
		p.y=tl.y;
	for(int j=0;j<NN_RESX*NN_RESY;j++) 
	{
		
		if ((*cell) == 1) 
		{
			dc->FillSolidRect(tl.x,tl.y,10,10,RGB(0,0,0));
		}
		tl.x += 10;
		if (tl.x == ix + 10*NN_RESX) 
		{
			tl.x = ix;
			tl.y += 10;
		}
		cell++;
		
		
	}
      tl.x=p.x;
	  tl.y=p.y;
	  tl.x=tl.x+100;
	ix=ix+100;
 
	}
	
  
}

void CMyView::OnRandom() 
{
	// TODO: Add your command handler code here
	srand((unsigned)time(NULL));
		memset(&m_fWeights,0,sizeof(m_fWeights));
		int num = 0;
	for (int i=0;i<NN_NUMBERS * NN_NOISY;i++) 
	{
		for(int j=0;j<NN_RESX * NN_RESY;j++) 
		{
			if (rand() % 100 < 7) 
			{
				m_iNoisy[i][j] = !m_bNumbers[num][j];
			} 
			else 
				m_iNoisy[i][j] = m_bNumbers[num][j];
		}
		
		if ((float)(i+1)/NN_NOISY == (i+1)/NN_NOISY && i != 0) 
			num++;
	}
        RunNet(TRUE);
	

	
}

void CMyView::RunNet(BOOL training)
{
	// 检测带有噪声的数据
	float d[NN_NUMBERS];
	int cycles = 0;//初始化循环次数为0
	bool correct;
int out,t[20],delta;

	do 
	{
		correct = true;
		for(int i=0;i<NN_NUMBERS * NN_NOISY;i++) 
		{
			for(int j=0;j<NN_NUMBERS;j++) 
			{
				d[j] = 0;
				for(int k=0;k<NN_RESX * NN_RESY;k++) 
				{
					d[j] += m_fWeights[j][k]*m_iNoisy[i][k];
				}
			}
			
			int bestind = 0;
			for(j=1;j<NN_NUMBERS;j++) 
				if (d[j] > d[bestind]) 
					bestind = j;
			
			int realval = (int)(i/NN_NOISY);
			if (bestind == realval) continue;
			
			if (training) 
			{
				
				correct = false;
				
				for(j=0;j<NN_RESX * NN_RESY;j++) 
				{
					m_fWeights[bestind][j] -= m_iNoisy[i][j];
					m_fWeights[realval][j] += m_iNoisy[i][j];
				}
			}
		}
		   
			for(int k=0;k<NN_RESX * NN_RESY;k++) 
				{
			
				t[cycles] +=m_fWeights[0][k]*m_iNoisy[0][k];
				//delta=out-t;
				}
       
		
		cycles++;
	} while (!correct && cycles <= NN_MAXITER);
	for(int k=0;k<NN_RESX * NN_RESY;k++) 
	out+=m_fWeights[0][k]*m_bNumbers[0][k];
	CClientDC dc(this);
	dc.MoveTo(100,300);
	dc.LineTo(300,300);
	dc.MoveTo(100,300);
	dc.LineTo(100,200);
	dc.TextOut(300,275,"训练次数");
	dc.TextOut(110,200," 误差曲线");
		CPen newpen(PS_SOLID,1,RGB(0,0, 255));
    CPen* old=dc.SelectObject(&newpen);
	dc.MoveTo(100,300);
	for(int i=0;i<cycles;i++)
    {
		
		delta=int(fabs(out-t[i]));
		dc.LineTo(100+i*10,300-delta*4);
		

	}
	

	CString str;
	str.Format("训练次数为%d",cycles);
	MessageBox(str);
	
	//如果循环次数太大还每得到结果则退出
	if (cycles >= NN_MAXITER) 
	{
		MessageBox("Training has timed-out.",
			"Error in Training", MB_OK | MB_ICONINFORMATION);
		return;
	}
}

void CMyView::OnClassify() 
{
	// TODO: Add your command handler code herer
	CClientDC dc(this);
	CRect rect;
	GetClientRect(&rect);
	CBrush brush(RGB(255,255,255));
	CBrush *pOldBrush=dc.SelectObject(&brush);
	
  dc.PatBlt(rect.left,rect.top,rect.Width(),rect.Height(),PATCOPY);



	m_ipDrawNum = &m_bTestData[0][0];
    DrawNumber(	m_ipDrawNum);
	draw=true;
	for(int i=0;i<NN_NUMBERS;i++)
	{
		float d[NN_NUMBERS];
	 for(int j=0;j<NN_NUMBERS;j++) 
	 {
		d[j] = 0;
		for(int k=0;k<NN_RESX * NN_RESY;k++) 
		{
			d[j] += m_fWeights[j][k]*m_bTestData[i][k];
		}
	 }
	
	int bestind = 0;
	for(j=1;j<NN_NUMBERS;j++) 
		if (d[j] > d[bestind]) 
			bestind = j;
			CString str;
	str.Format("识别结果为%d",++bestind);
	dc.TextOut(100+i*100,200,str);
	}

	
}





void CMyView::OnNoisy() 
{
	// TODO: Add your command handler code here
	double *a=new double[10000];
		srand((unsigned)time(NULL));


    net=bpnn_create(35,6,4);
	//bpnn_randomize_weights(net->input_weights,35,5);
	//bpnn_randomize_weights(net->hidden_weights,5,1);
	int m,n;
	for( m=0;m<=35;m++)
		for( n=0;n<=6;n++)
		{
			net->input_weights[m][n]=(double)((float)(rand())/(32767/2) - 1);
		}
		for(m=0;m<=6;m++)
			for(n=0;n<=4;n++)
			{
				net->hidden_weights[m][n]=(double)((float)(rand())/(32767/2) - 1);
			}

	
				int num = 0;
	for (int i=0;i<NN_NUMBERS * NN_NOISY;i++) 

	{
		for(int j=0;j<NN_RESX * NN_RESY;j++) 
		{
			if (rand() % 100 < 7) 
			{
				m_iNoisy[i][j] = !m_bNumbers[num][j];
			} 
			else 
				m_iNoisy[i][j] = m_bNumbers[num][j];
		}
		
		if ((float)(i+1)/NN_NOISY == (i+1)/NN_NOISY && i != 0) 
			num++;
	}


	//net->input_units=(double *)m_iNoisy[0][0];
//	net->target=m_bNumbers[0][0];
	double eta,momentum;
	eta=0.3;
	momentum=0;
	double eo1,eh1;
	 num=1;
	 
	for(int j=0;j<=10000;j++)
	{
		//对标准的0到9数字进行网络训练
		for (int i=0;i<NN_NUMBERS;i++) 
		{
            for(int k=1;k<=NN_RESX * NN_RESY;k++)
			{
				net->input_units[k]=(double )m_bNumbers[i][k-1];

			}
             double num1=(double)num;
			 SetTarget(net->target,i+1);
		
		//	if ((float)(i+1)/NN_NOISY == (i+1)/NN_NOISY && i != 0)
		//	{
		//		num++;
		//	    
		//	}
          	   bpnn_train(net,eta,momentum,&eo1,&eh1);
             
		}
//对随机产生的25个躁声加入到网络中进行训练,用来提高对躁声的识别精度
		
	for(int m1=0;m1<25;m1++)
		for(int i1=0;i1<NN_NUMBERS;i1++) 
		{
			for(int k1=1;k1<=NN_RESX * NN_RESY;k1++)
			{
				net->input_units[k1]=(double )m_iNoisy[i1*25+m1][k1-1];
			}
			double num1=(double)num;
			 SetTarget(net->target,i1+1);
			 bpnn_train(net,eta,momentum,&eo1,&eh1);

		} 
		a[j]=eo1;
	}
		CClientDC dc(this);
	dc.MoveTo(100,300);
	dc.LineTo(300,300);
	dc.MoveTo(100,300);
	dc.LineTo(100,200);
	dc.TextOut(300,275,"训练次数");
	dc.TextOut(110,200," 误差曲线");
		CPen newpen(PS_SOLID,1,RGB(0,0, 255));
    CPen* old=dc.SelectObject(&newpen);
	dc.MoveTo(100,300);
	for( i=0;i<1000;i++)
    {
		
	
		dc.LineTo(100+i,300-a[i]*10000);
		

	}
  
	


}

void CMyView::OnRecog() 
{
	// TODO: Add your command handler code here
	CClientDC dc(this);
	CRect rect;
	GetClientRect(&rect);
	CBrush brush(RGB(255,255,255));
	CBrush *pOldBrush=dc.SelectObject(&brush);
	
    dc.PatBlt(rect.left,rect.top,rect.Width(),rect.Height(),PATCOPY);



	m_ipDrawNum = &m_bTestData[0][0];
    DrawNumber(	m_ipDrawNum);
	draw=true;
	int num=1;
	double t;
     double d[4]={0,0,0,0};
    for(int i=0;i<NN_NUMBERS;i++)
	{
	 for(int k=1;k<=NN_RESX * NN_RESY;k++)
	 {
				net->input_units[k]=(double)m_bTestData[i][k-1];
	 }
                //bpnn_layerforward(net->input_units,net->hidden_units,net->input_weights,net->input_n,net->hidden_n);
                     
	                 bpnn_feedforward(net);
					 
					 
					 for(int m=1;m<=9;m++)
					 {
						  d[0]=net->output_units[1];
						  d[1]=net->output_units[2];
						  d[2]=net->output_units[3];
						  d[3]=net->output_units[4];
                          t=d[0]+d[1]*2+d[2]*4+d[3]*8;
						// d[m]=double(fabs(net->output_units[1]-m));
					 }
					 double min;
						 min=fabs(t-1);
					 for(int n=1;n<9;n++)
					 {    
						 
						 if(min>fabs((t-(n+1))))
						 {
							 min=fabs((t-(n+1)));
							 num=n+1;
						 }

						
						 
						
					 }
	
         		CString str;
	str.Format("识别结果为%d",num);
	dc.TextOut(100+i*100,200,str);
	}
					 
}
//8421来表示
void CMyView::SetTarget(double *t, double num)
{
	switch(int(num))
	{
	case 1:
		t[1]=1;t[2]=0;t[3]=0;t[4]=0;
		break;
		case 2:
		t[1]=0;t[2]=1;t[3]=0;t[4]=0;
		break;
		case 3:
		t[1]=1;t[2]=1;t[3]=0;t[4]=0;
		break;
		case 4:
		t[1]=0;t[2]=0;t[3]=1;t[4]=0;
		break;
		case 5:
		t[1]=1;t[2]=0;t[3]=1;t[4]=0;
		break;
		case 6:
		t[1]=0;t[2]=1;t[3]=1;t[4]=0;
		break;
		case 7:
		t[1]=1;t[2]=1;t[3]=1;t[4]=0;
		break;
		case 8:
		t[1]=0;t[2]=0;t[3]=0;t[4]=1;
		break;
		case 9:
		t[1]=1;t[2]=0;t[3]=0;t[4]=1;
		break;

	}

}

⌨️ 快捷键说明

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