📄 numrecogbpdlg.cpp
字号:
{
dc->FillSolidRect(dot.x, dot.y-10, 10, 10, RGB(0, 0, 0));
}
dot.x += 10;
if(dot.x==ix+10*NN_RESX)
{
dot.x = ix;
dot.y += 10;
}
cell ++;
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CNumRecogBPDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
/////////////////////////////////////////////////////////////////////////
// 由于某些原因,若采用“Maxinum Speed”优化将引起程序运行失败,所以先
// 关闭此优化,在该段代码运行结束后再打开此优化功能
/////////////////////////////////////////////////////////////////////////
#pragma optimize("", off)
// 训练按钮处理函数
void CNumRecogBPDlg::OnButtonTrain()
{
// TODO: Add your control notification handler code here
srand((unsigned)time(NULL)); // 设置随机数
m_RunInfor.ResetContent(); // 程序运行信息
// 所有权值0初始化
memset(&m_fWeights, 0, sizeof(m_fWeights));
// 产生带有随机噪声的训练数据
m_RunInfor.InsertString(-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_iTrainNoisy[i][j] = !m_iTrainData[num][j];
}
else
m_iTrainNoisy[i][j] = m_iTrainData[num][j];
}
if(((float)(i+1)/NN_NOISY == (i+1)/NN_NOISY)&&(i != 0))
{
num++;
}
}
m_RunInfor.InsertString(-1, "训练中......");
RunBPNet(true); // 运行网络
m_RunInfor.InsertString(-1, "训练结束......");
GetDlgItem(IDC_BUTTON_RECOG)->EnableWindow(true); // 运行训练后再开始识别
}
// 识别按钮处理函数
void CNumRecogBPDlg::OnButtonRecog()
{
// TODO: Add your control notification handler code here
m_RunInfor.ResetContent(); // 程序运行信息
m_RunInfor.InsertString(-1, "开始识别......");
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_iRecogData[0][k];
}
}
int bestind = 0;
for(j=1; j<NN_NUMBERS; j++)
{
if(d[j]>d[bestind])
{
bestind = j;
}
}
/////////////////////////////////////////////////////////////////////////////
// 零、壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、元、角、分
/////////////////////////////////////////////////////////////////////////////
switch(bestind)
{
case 0:
m_RunInfor.InsertString(-1, "识别结果为元");
break;
case 1:
m_RunInfor.InsertString(-1, "识别结果为角");
break;
case 2:
m_RunInfor.InsertString(-1, "识别结果为分");
break;
case 3:
m_RunInfor.InsertString(-1, "识别结果为零");
break;
case 4:
m_RunInfor.InsertString(-1, "识别结果为壹");
break;
case 5:
m_RunInfor.InsertString(-1, "识别结果为贰");
break;
case 6:
m_RunInfor.InsertString(-1, "识别结果为叁");
break;
case 7:
m_RunInfor.InsertString(-1, "识别结果为肆");
break;
case 8:
m_RunInfor.InsertString(-1, "识别结果为伍");
break;
case 9:
m_RunInfor.InsertString(-1, "识别结果为陆");
break;
case 10:
m_RunInfor.InsertString(-1, "识别结果为柒");
break;
case 11:
m_RunInfor.InsertString(-1, "识别结果为捌");
break;
case 12:
m_RunInfor.InsertString(-1, "识别结果为玖");
break;
case 13:
m_RunInfor.InsertString(-1, "识别结果为拾");
break;
default:
m_RunInfor.InsertString(-1, "无法识别");
}
}
// 运行BP网络处理函数
void CNumRecogBPDlg::RunBPNet(bool training)
{
// 检测带有噪声的数据
float d[NN_NUMBERS];
int cycles = 0; // 初始化循环次数为0
bool correct;
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_iTrainNoisy[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_iTrainNoisy[i][j];
m_fWeights[realval][j] += m_iTrainNoisy[i][j];
}
}
}
++cycles; //???
}while(!correct && cycles<=NN_MAXITER);
// 如果循环次数太大还没得到结果则退出
if(cycles >= NN_MAXITER)
{
MessageBox("训练超时!", "训练错误", MB_OK|MB_ICONINFORMATION);
return;
}
}
// 恢复系统优化
#pragma optimize("", on)
// 训练数据滚动条的处理函数
void CNumRecogBPDlg::OnDeltaposSpinTrainnum(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
// TODO: Add your control notification handler code here
int iPos = pNMUpDown->iPos;
int iDelta = pNMUpDown->iDelta;
if((iPos==0 && iDelta==-1) || (iPos==NN_NUMBERS-1 && iDelta== 1))
{
if(iDelta==-1)
{
m_ipDrawTrainNum = &m_iTrainData[0][0];
InvalidateTrainPic();
}
else
{
m_ipDrawTrainNum = &m_iTrainData[NN_NUMBERS-1][0];
InvalidateTrainPic();
}
}
else
{
m_ipDrawTrainNum = &m_iTrainData[iPos+iDelta][0];
InvalidateTrainPic();
}
*pResult = 0;
}
//////////////////////////////////////////////////////////////////////
// 强制重绘函数
// 训练区重绘函数
void CNumRecogBPDlg::InvalidateTrainPic()
{
// 获取绘画区域
CRect rect_Train; // 训练窗口
// 生成训练窗口绘图区
m_TrainPic.GetClientRect(&rect_Train);
m_TrainPic.ClientToScreen(&rect_Train);
ScreenToClient(&rect_Train);
InvalidateRect(rect_Train, false);
}
// 识别区重绘函数
void CNumRecogBPDlg::InvalidateRecogPic()
{
// 获取绘画区域
CRect rect_Recog; // 识别窗口
// 生成识别窗口绘图区
m_RecogPic.GetClientRect(&rect_Recog);
m_RecogPic.ClientToScreen(&rect_Recog);
ScreenToClient(&rect_Recog);
InvalidateRect(rect_Recog, false);
}
////////////////////////////////////////////////////////////////////
// 打开识别文件
void CNumRecogBPDlg::OnOpenrecogfile()
{
// TODO: Add your control notification handler code here
CFileDialog OpenFileDlg(TRUE, NULL, NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"识别文件(*.dat)|*.dat|所有文件(*.*)|*.*||");
if(OpenFileDlg.DoModal()==IDOK)
{
CString fileName = OpenFileDlg.GetFileName();
// 打开文件
ifstream recogdata(fileName, ios::nocreate);
// 检查文件的有效性
if(!recogdata)
{
MessageBox("没有找到保存识别数据的文件!", "载入文件错误!",
MB_OK|MB_ICONERROR);
}
// 读文件(打开待识别的文件)
for(int i=0; i<NN_NUMBERS; i++)
{
for(int j=0; j<NN_RESX*NN_RESY; j++)
{
int onoff;
recogdata >> onoff;
m_iRecogData[i][j] = onoff;
}
}
m_bDrawNum = 1; // 设置画数字标志
m_ipDrawRecogNum = &m_iRecogData[0][0]; // 画数字指针赋值
InvalidateRecogPic(); // 绘图区刷新
m_RunInfor.ResetContent(); // 载入新文件,程序运行信息初始化
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -