【作业】手写数字识别系统

1.项目名称:手写数字识别系统

2.项目内容

         设计一个简单的手写数字识别系统,能够识别手写输入的数字1-9。目前像汉王公司推出了一系列的手写笔等产品,通过实现这样的一个简单功能可以有效地学习VC++基于MFC的编程,同时对于手写笔这样的产品的工作原理能够产生一定的了解!

3.功能设计思路

         手写数字识别的难度在于其形状很多,对于规范的手写数字,可以采用模板匹配的方法,但是由于个人的字体不尽相同,导致数字可大可小,或胖或瘦,采用模板匹配就行不通了,一中解决方案是以数字的笔画特征区别手写的数字。以数字2为例,其笔画为向右,向左下,向右的顺序。

4.编码实施

         首先建立一个利用向导生成一个MFC程序名为RegFigure;修改应用程序图标过程如下:

1.在资源视图中“Icon”下选择“IDR_MAINFRAME”图标,然后用“Delete”键删除。(在Windows的资源管理器里面,打开当前项目下的“res”子目录,删除相应的图标文件。)

2.在资源视图中“~.rc”下,用右键菜单的“import...”,然后在对话框中选择“Icon”导入一个图标。

3.在属性工具中,将新建的图标的ID改为“IDR_MAINFRAME”(默认为“IDI_ICON1”)。

 

         在资源视图中右击“插入对话框”生成一个对话框IDD_DIG_Reg,利用MFC ClassWizard生成对话框类RegDlg,在类视图中右击RegDlg添加成员函数和成员变量,如图

增加手写数字输入菜单和手写数字输入工具按钮将ID号都改为:ID_Menu_Reg。为CRegFigureView类添加commond事件,并添加如下代码:

void CRegFigureView::OnMenuRegClick()

{

         // TODO:点击手写数字输入功能,弹出识别对话框

         RegDlg m_RegDlg;

         m_RegDlg.DoModal();

}

将CAboutDlg类独立出来,生成两个文件CAboutDlg.h和CAboutDlg.cpp,这样就可以多次调用。

5.功能实现

手写数字识别显示

6.总结

         本设计实现了简单的数字1-9的识别,最明显的一个问题就是6和0的识别会产生混淆,因此可以想象对于大型的文字识别系统,采用简单的方向判别还是不够的!对于大型的手写文字识别,目前向百度主页上已经采用的汉王手写识别采用了数据库技术和这样的一中方向判别的机制,这种机制对于文字的书写笔画要求很高。

附录代码

RegDlg.h添加代码如下:

  1 enum Dir{left,right,up,down,none};
  2 struct Figure
  3 {
  4     Dir  Direction[16]; //方向 0-left 1-right 2-up 3 -down 
  5     int  DotCount ;    //断笔数
  6 };
  7 /////////////////////////////////////////////////////////////////////////////
  8 // RegDlg dialog
  9 class RegDlg : public CDialog
 10 {
 11 // Construction
 12 public:
 13     RegDlg(CWnd* pParent = NULL);   // standard constructor
 14     void DrawGrid(int row,int col);
 15     
 16     CRect m_rect;
 17     BOOL m_Buttondowned; 
 18     CPen pen;
 19     CPoint m_Startpt;
 20     CPoint m_Endpt;
 21     
 22     CPoint m_Prept;
 23     Figure m_Figure;
 24     int m_curpen;  //当前笔数
 25     BOOL m_Isreg;  //是否开始识别
 26 // Dialog Data
 27     //{{AFX_DATA(RegDlg)
 28     enum { IDD = IDD_DIG_Reg };
 29     CStatic    m_Panel;
 30     //}}AFX_DATA
 31 // Overrides
 32     // ClassWizard generated virtual function overrides
 33     //{{AFX_VIRTUAL(RegDlg)
 34     protected:
 35     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 36     //}}AFX_VIRTUAL
 37 // Implementation
 38 protected:
 39     HICON m_hIcon;
 40     // Generated message map functions
 41     //{{AFX_MSG(RegDlg)
 42         // NOTE: the ClassWizard will add member functions here
 43     virtual BOOL OnInitDialog();
 44     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 45     afx_msg void OnPaint();
 46     afx_msg HCURSOR OnQueryDragIcon();
 47     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
 48     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
 49     afx_msg void OnMouseMove(UINT nFlags, CPoint point);
 50     afx_msg void OnReg();
 51     afx_msg void OnButton1();
 52     //}}AFX_MSG
 53     DECLARE_MESSAGE_MAP()
 54 };
 55 RegDlg.cpp代码:
 56 #include "stdafx.h"
 57 #include "RegFigure.h"
 58 #include "RegDlg.h"
 59 #include "AboutDlg.h"
 60 #ifdef _DEBUG
 61 #define new DEBUG_NEW
 62 #undef THIS_FILE
 63 static char THIS_FILE[] = __FILE__;
 64 #endif
 65 /////////////////////////////////////////////////////////////////////////////
 66 // RegDlg dialog
 67 RegDlg::RegDlg(CWnd* pParent /*=NULL*/)    : CDialog(RegDlg::IDD)
 68 {
 69     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 70     m_Buttondowned = FALSE;
 71     m_curpen= 0;
 72     m_Isreg = FALSE;
 73     m_Figure.DotCount = 0;
 74 }
 75 /////////////////////////////////////////////////////////////////////////////
 76 // RegDlg message handlers
 77 BOOL RegDlg::OnInitDialog()
 78 {
 79     CDialog::OnInitDialog();
 80     // Add "About..." menu item to system menu.
 81     // IDM_ABOUTBOX must be in the system command range.
 82     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 83     ASSERT(IDM_ABOUTBOX < 0xF000);
 84     CMenu* pSysMenu = GetSystemMenu(FALSE);
 85     if (pSysMenu != NULL)
 86     {
 87         CString strAboutMenu;
 88         strAboutMenu.LoadString(IDS_ABOUTBOX);
 89         if (!strAboutMenu.IsEmpty())
 90         {
 91             pSysMenu->AppendMenu(MF_SEPARATOR);
 92             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
 93         }
 94     }
 95     // Set the icon for this dialog.  The framework does this automatically
 96     //  when the application's main window is not a dialog
 97     SetIcon(m_hIcon, TRUE);            // Set big icon
 98     SetIcon(m_hIcon, FALSE);        // Set small icon
 99     // TODO: Add extra initialization here
100     pen.CreatePen(PS_SOLID,5,RGB(0,100,0));//绿色画笔
101     m_Panel.GetClientRect(m_rect);
102     //MapWindowPoints(&m_Panel,m_rect);
103     m_Figure.DotCount = 0;
104     for (int i =0; i<16; i++)
105     {
106         m_Figure.Direction[i]= none;
107     }
108     return TRUE;  // return TRUE  unless you set the focus to a control
109 }
110 void RegDlg::OnSysCommand(UINT nID, LPARAM lParam)
111 {
112     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
113     {
114         CAboutDlg dlgAbout;
115         dlgAbout.DoModal();
116     }
117     else
118     {
119         CDialog::OnSysCommand(nID, lParam);
120     }
121 }
122 void RegDlg::OnPaint() 
123 {
124     if (IsIconic())
125     {
126         CPaintDC dc(this); // device context for painting
127 
128         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
129 
130         // Center icon in client rectangle
131         int cxIcon = GetSystemMetrics(SM_CXICON);
132         int cyIcon = GetSystemMetrics(SM_CYICON);
133         CRect rect;
134         GetClientRect(&rect);
135         int x = (rect.Width() - cxIcon + 1) / 2;
136         int y = (rect.Height() - cyIcon + 1) / 2;
137         // Draw the icon
138         dc.DrawIcon(x, y, m_hIcon);
139     }
140     else
141     {
142         CDialog::OnPaint();
143     }
144     //m_rect.CopyRect(CRect (50,80,200,300));
145 }
146 // The system calls this to obtain the cursor to display while the user drags
147 //  the minimized window.
148 HCURSOR RegDlg::OnQueryDragIcon()
149 {
150     return (HCURSOR) m_hIcon;
151 }
152 void RegDlg::OnLButtonDown(UINT nFlags, CPoint point) 
153 {
154     m_Buttondowned = TRUE;
155     m_Startpt = point;
156     m_Prept = point;
157     
158     if(m_rect.PtInRect(point))
159             m_Figure.DotCount += 1;
160 
161     CDialog::OnLButtonDown(nFlags, point);
162 }
163 void RegDlg::OnLButtonUp(UINT nFlags, CPoint point) 
164 {
165 //    m_curpen = 0;
166     m_Endpt = point;
167     m_Buttondowned = FALSE;    
168     CDialog::OnLButtonUp(nFlags, point);
169 }
170 void RegDlg::OnMouseMove(UINT nFlags, CPoint point) 
171 {
172     if (m_Buttondowned)
173         if (m_rect.PtInRect(point))
174         {
175             CDC* pDC = m_Panel.GetDC();
176             pDC->SelectObject(&pen);
177             pDC->MoveTo(point);
178             pDC->LineTo(CPoint(point.x+1,point.y+1));
179             
180             if (m_curpen>15)
181                 return;
182             if (point.x>m_Prept.x+30) //向右
183             {
184                 if (m_Figure.Direction[m_curpen]==none)
185                     m_Figure.Direction[m_curpen] = right;
186                 else if (m_Figure.Direction[m_curpen] != right)
187                 {
188                     m_curpen+=1;
189                     m_Figure.Direction[m_curpen] = right;        
190                 }
191                 m_Prept = point;
192             }
193             else if (point.y>m_Prept.y+30)
194             {
195                 if (m_Figure.Direction[m_curpen]==none)
196                     m_Figure.Direction[m_curpen] = down;
197                 else if (m_Figure.Direction[m_curpen] != down)
198                 {
199                     m_curpen+=1;
200                     m_Figure.Direction[m_curpen] = down;        
201                 }
202                 m_Prept = point;
203             }
204             else if (point.x<m_Prept.x-30)
205             {
206                 if (m_Figure.Direction[m_curpen]==none)
207                     m_Figure.Direction[m_curpen] = left;
208                 else if (m_Figure.Direction[m_curpen] != left)
209                 {
210                     m_curpen+=1;
211                     m_Figure.Direction[m_curpen] = left;                        
212                 }
213                 m_Prept = point;
214             }
215             else if (point.y< m_Prept.y-30)
216             {
217                 if (m_Figure.Direction[m_curpen]==none)
218                     m_Figure.Direction[m_curpen]= up;
219                 else if (m_Figure.Direction[m_curpen] != up)
220                 {
221                     m_curpen+=1;
222                     m_Figure.Direction[m_curpen] = up;                        
223                 }
224                 m_Prept = point;
225             }        
226         }    
227     CDialog::OnMouseMove(nFlags, point);
228 }
229 void RegDlg::DrawGrid(int row, int col)
230 {
231     CDC* pDC = m_Panel.GetDC();
232     CRect rect;
233     m_Panel.GetClientRect(rect);
234     for (int i = 0; i<row+1; i++)
235     {    
236         pDC->MoveTo(0,i*30);
237         pDC->LineTo(rect.Width(),i*30);
238     }
239     for (int j = 0; j<col+1;j++)
240     {
241         pDC->MoveTo(j*30,0);
242         pDC->LineTo(j*30,rect.Height());    
243     }
244 }
245 void RegDlg::OnReg() 
246 {
247     m_curpen=0;
248     if (m_Figure.Direction[0]==down) //判断1
249         if (m_Figure.Direction[1]==none)
250         {
251             if ( m_Figure.DotCount == 1)
252             {
253                 MessageBox("1");
254 
255                 for (int i =0; i<16; i++)
256                 {
257                     m_Figure.Direction[i]= none;
258                 }
259                 m_Figure.DotCount = 0;
260                 m_Panel.Invalidate();
261                 return;
262             }
263         }
264     if (m_Figure.Direction[0]==right) //判断7
265         if (m_Figure.Direction[1]==down)
266             if (m_Figure.Direction[2]==none)
267         {
268             if ( m_Figure.DotCount == 1)
269             {
270                 MessageBox("7");
271                 for (int i =0; i<16; i++)
272                 {
273                     m_Figure.Direction[i]= none;
274                 }
275                 m_Figure.DotCount = 0;
276                 m_Panel.Invalidate();
277                 return;
278             }
279         }
280     if (m_Figure.Direction[0]==right) //判断2 
281         if (m_Figure.Direction[1]==down)
282         {
283             if (m_Figure.DotCount == 1)
284             {
285                 if (m_Figure.Direction[2]==left)
286                 {
287                     if (m_Figure.Direction[3]==right)
288                         if ( m_Figure.Direction[4]==none)
289                         {
290                             MessageBox("2");
291                             for (int i =0; i<16; i++)
292                             {
293                                 m_Figure.Direction[i]= none;
294                             }
295                             m_Figure.DotCount = 0;
296                             m_Panel.Invalidate();
297                             return;
298                         }
299                 }
300                 else if (m_Figure.Direction[2]==right)
301                 {
302                     if (m_Figure.Direction[3]==none)
303                     {
304                         MessageBox("2");
305                     
306                         for (int i =0; i<16; i++)
307                         {
308                             m_Figure.Direction[i]= none;
309                         }
310                         m_Figure.DotCount = 0;
311                         m_Panel.Invalidate();
312                         return;
313                     }
314                 }
315             }
316         }
317     if (m_Figure.Direction[0]==right) //判断3
318         if (m_Figure.Direction[1]==down)
319             if (m_Figure.DotCount==1)
320             {
321                 if (m_Figure.Direction[2]==left)
322                     if (m_Figure.Direction[3]==right)
323                     {
324                         MessageBox("3");                    
325                     }
326             
327                 for (int i =0; i<16; i++)
328                 {
329                     m_Figure.Direction[i]= none;
330                 }
331                 m_Figure.DotCount = 0;
332                 m_Panel.Invalidate();
333                 return;            
334             }
335     if (m_Figure.Direction[0]==down)//判断4
336         if (m_Figure.Direction[1]==right)
337             if (m_Figure.DotCount ==2)
338             {
339                 if (m_Figure.Direction[2]==down)
340                     if(m_Figure.Direction[3]==none)
341                     {
342                         for (int i=0;i<16;i++)
343                         {
344                             m_Figure.Direction[i]=none;
345                         }
346                         m_Figure.DotCount =0;
347                         m_Panel.Invalidate();
348                         MessageBox("4");
349                         return;    
350                     }
351             }
352     if (m_Figure.Direction[0]==down)//判断5
353         if (m_Figure.Direction[1]==right)
354             if (m_Figure.DotCount ==2)
355                 if (m_Figure.Direction [2]==down)
356                     if(m_Figure.Direction[3]==left)
357                         if (m_Figure.Direction[4]==right)
358                             if(m_Figure.Direction [5]==none)
359                             {
360                                 MessageBox("5");
361                                 for (int i=0;i<16;i++)
362                                 {
363                                     m_Figure.Direction [i]=none;
364                                 }
365                                 m_Figure.DotCount =0;
366                                 m_Panel.Invalidate();
367                                 return;    
368                             }
369     if (m_Figure.DotCount ==1)
370     {
371         if (m_Figure.Direction[0]==left)
372             if (m_Figure.Direction[1]==down)//判断6,第一笔向左
373                 if (m_Figure.Direction[2]==right)
374                     if (m_Figure.Direction[3]==up)
375                         if (m_Figure.Direction[4]==left)
376                         {
377                             MessageBox("6");
378                             for (int i=0;i<16;i++)
379                             {
380                                 m_Figure.Direction [i]=none;
381                             }
382                             m_Figure.DotCount =0;
383                             m_Panel.Invalidate();
384                             return;    
385                         }
386         if (m_Figure.Direction[0]==down)//判断6,第一笔向下,此处和0有冲突,需要计算画笔移动的距离
387             if (m_Figure.Direction[1]==right)
388                 if (m_Figure.Direction[2]==up)
389                     if (m_Figure.Direction[3]==left)
390                     {
391                         MessageBox("6");
392                         for (int i=0;i<16;i++)
393                         {
394                             m_Figure.Direction [i]=none;
395                         }
396                         m_Figure.DotCount =0;
397                         m_Panel.Invalidate();
398                         return;    
399                     }
400     }
401     if (m_Figure.DotCount ==1)
402     {
403         if (m_Figure.Direction[0]==left)//判断8方式1
404         {
405             if (m_Figure.Direction[1]==down)
406                 if (m_Figure.Direction[2]==left)
407                     if (m_Figure.Direction[3]==up)
408                         if (m_Figure.Direction[4]==right)
409                             if (m_Figure.Direction[5]==up)
410                             {
411                                 MessageBox("8");
412                                 for (int i=0;i<16;i++)
413                                 {
414                                     m_Figure.Direction [i]=none;
415                                 }
416                                 m_Figure.DotCount =0;
417                                 m_Panel.Invalidate();
418                                 return;    
419                             }
420         }
421         if (m_Figure.Direction[0]==down)//判断8方式2
422         {
423             if (m_Figure.Direction[1]==right)
424                 if (m_Figure.Direction[2]==down)
425                     if (m_Figure.Direction[3]==left)
426                         if (m_Figure.Direction[4]==up)
427                             if (m_Figure.Direction[5]==right)
428                             {
429                                 MessageBox("8");
430                                 for (int i=0;i<16;i++)
431                                 {
432                                     m_Figure.Direction [i]=none;
433                                 }
434                                 m_Figure.DotCount =0;
435                                 m_Panel.Invalidate();
436                                 return;    
437                             }
438         }
439         if (m_Figure.Direction[0]==left)//判断8方式3
440         {
441             if (m_Figure.Direction[1]==down)
442                 if (m_Figure.Direction[2]==right)
443                     if (m_Figure.Direction[3]==down)
444                         if (m_Figure.Direction[4]==left)
445                             if (m_Figure.Direction[5]==up)
446                             {
447                                 MessageBox("8");
448                                 for (int i=0;i<16;i++)
449                                 {
450                                     m_Figure.Direction [i]=none;
451                                 }
452                                 m_Figure.DotCount =0;
453                                 m_Panel.Invalidate();
454                                 return;    
455                             }
456         }
457     }
458     if (m_Figure.DotCount ==1)
459     {
460         if (m_Figure.Direction[0]==left)//判断9方式1
461         {
462             if (m_Figure.Direction[1]==down)
463                 if (m_Figure.Direction[2]==right)
464                     if (m_Figure.Direction[3]==up)
465                         if (m_Figure.Direction[4]==down)
466                         {
467                             MessageBox("9");
468                             for (int i=0;i<16;i++)
469                             {
470                                 m_Figure.Direction [i]=none;
471                             }
472                             m_Figure.DotCount =0;
473                             m_Panel.Invalidate();
474                             return;    
475                         }
476         }
477         if (m_Figure.Direction[0]==left)//判断9方式2
478         {
479             if (m_Figure.Direction[1]==up)
480             //    if (m_Figure.Direction[2]==right)
481                     if (m_Figure.Direction[2]==right)
482                         if (m_Figure.Direction[3]==down)
483                         {
484                             MessageBox("9");
485                             for (int i=0;i<16;i++)
486                             {
487                                 m_Figure.Direction [i]=none;
488                             }
489                             m_Figure.DotCount =0;
490                             m_Panel.Invalidate();
491                             return;    
492                         }
493         }
494     
495         if (m_Figure.Direction[0]==right)//判断9方式3
496         {
497             if (m_Figure.Direction[1]==up)
498                 if (m_Figure.Direction[2]==left)
499                     if (m_Figure.Direction[3]==down)
500                     {
501                         MessageBox("9");
502                         for (int i=0;i<16;i++)
503                         {
504                             m_Figure.Direction [i]=none;
505                         }
506                         m_Figure.DotCount =0;
507                         m_Panel.Invalidate();
508                         return;    
509                     }
510         }
511     }
512     for (int i =0; i<16; i++)
513     {
514         m_Figure.Direction[i]= none;
515     }
516     
517     m_Figure.DotCount = 0;
518     m_Panel.Invalidate();
519 }
520 void RegDlg::OnButton1() 
521 {
522     // TODO: Add your control notification handler code here
523     DrawGrid(9,5);//画网格
524 }
posted @ 2012-10-11 10:15  太一吾鱼水  阅读(1604)  评论(0编辑  收藏  举报