📄 数字识别view.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 + -