patternDlg.cpp
上传用户:chinamans
上传日期:2016-04-11
资源大小:14485k
文件大小:25k
源码类别:

图形/文字识别

开发平台:

Visual C++

  1. // patternDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "pattern.h"
  5. #include "patternDlg.h"
  6. #include "Afxwin.h"
  7. #include "Afxdlgs.h"
  8. #include "winuser.h"
  9. #include "Store.h"
  10.  #include <stdio.h>
  11. //#define   _MBCS
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. #include<windows.h>
  18. #include<math.h>
  19. #define Startx 30
  20. #define Starty 190
  21. #define wid  192
  22. #define lon 192
  23. #define yu 3 //2 area
  24. #define yu1 5 //dou dong
  25. #define yu2  4 
  26. int num,Time;
  27. int xmax,ymax,xmin,ymin; //随时纪录书写过程中的书写范围
  28. //存储书写笔迹的坐标序列,按笔划存储,每个笔划最多300个点
  29. //每个字最多15个笔划
  30. struct 
  31. {
  32. int x;
  33. int y;
  34. }store[15][300];
  35. //备份的序列
  36. struct 
  37. {
  38. int x;
  39. int y;
  40. }storeback[15][300];
  41. struct
  42. {
  43. int total;//总的笔划数
  44. char zifu[2];//代表字符
  45. int dian[15];//每个笔划的点数
  46. struct{
  47. int relate;//相对前点特征
  48. int region;//全局位置特征
  49. int arc;//过渡带特征
  50. }detail[15][20];//15个笔划上的特征点,每个笔划20个特征点
  51. }tez[2002];
  52. struct
  53. {
  54. int total;
  55. int dian[15];
  56. struct
  57. {
  58. int relate;
  59. int region;
  60. int arc;
  61. }detail[15][20];
  62. }test;//意义同上,为测试点的结构
  63. int queue[50];
  64. int  queue1[40];
  65. int zong;
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CAboutDlg dialog used for App About
  68. class CAboutDlg : public CDialog
  69. {
  70. public:
  71. CAboutDlg();
  72. // Dialog Data
  73. //{{AFX_DATA(CAboutDlg)
  74. enum { IDD = IDD_ABOUTBOX };
  75. //}}AFX_DATA
  76. // ClassWizard generated virtual function overrides
  77. //{{AFX_VIRTUAL(CAboutDlg)
  78. protected:
  79. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  80. //}}AFX_VIRTUAL
  81. // Implementation
  82. protected:
  83. //{{AFX_MSG(CAboutDlg)
  84. //}}AFX_MSG
  85. DECLARE_MESSAGE_MAP()
  86. };
  87. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  88. {
  89. //{{AFX_DATA_INIT(CAboutDlg)
  90. //}}AFX_DATA_INIT
  91. }
  92. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  93. {
  94. CDialog::DoDataExchange(pDX);
  95. //{{AFX_DATA_MAP(CAboutDlg)
  96. //}}AFX_DATA_MAP
  97. }
  98. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  99. //{{AFX_MSG_MAP(CAboutDlg)
  100. // No message handlers
  101. //}}AFX_MSG_MAP
  102. END_MESSAGE_MAP()
  103. /////////////////////////////////////////////////////////////////////////////
  104. // CPatternDlg dialog
  105. CPatternDlg::CPatternDlg(CWnd* pParent /*=NULL*/)
  106. : CDialog(CPatternDlg::IDD, pParent)
  107. {
  108. //{{AFX_DATA_INIT(CPatternDlg)
  109. //}}AFX_DATA_INIT
  110. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  111. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  112. }
  113. void CPatternDlg::DoDataExchange(CDataExchange* pDX)
  114. {
  115. CDialog::DoDataExchange(pDX);
  116. //{{AFX_DATA_MAP(CPatternDlg)
  117. DDX_Control(pDX, IDC_EDIT2, m_edit2);
  118. DDX_Control(pDX, IDC_EDIT1, m_edit1);
  119. DDX_Control(pDX, IDC_BUTTON4, m_escape);
  120. DDX_Control(pDX, IDC_BUTTON3, m_clear);
  121. DDX_Control(pDX, IDC_BUTTON1, m_recog);
  122. DDX_Control(pDX, IDC_BUTTON2, m_study);
  123. //}}AFX_DATA_MAP
  124. }
  125. BEGIN_MESSAGE_MAP(CPatternDlg, CDialog)
  126. //{{AFX_MSG_MAP(CPatternDlg)
  127. ON_WM_SYSCOMMAND()
  128. ON_WM_PAINT()
  129. ON_WM_QUERYDRAGICON()
  130. ON_BN_CLICKED(IDC_BUTTON4, OnEsp)
  131. ON_BN_CLICKED(IDC_BUTTON1, OnRecog)
  132. ON_WM_MOUSEMOVE()
  133. ON_BN_CLICKED(IDC_BUTTON3, OnClear)
  134. ON_BN_CLICKED(IDC_BUTTON2, OnStudy)
  135.     ON_WM_LBUTTONUP()
  136.     ON_WM_LBUTTONDOWN()
  137. ON_COMMAND(ID_EXIT_MENU, OnExitMenu)
  138. ON_COMMAND(ID_ABOUT_MENU, OnAboutMenu)
  139. ON_COMMAND(ID_SAVE_MENU, OnSaveMenu1)
  140. ON_COMMAND(ID_OPEN_MENU, OnOpenMenu)
  141. //}}AFX_MSG_MAP
  142. END_MESSAGE_MAP()
  143. /////////////////////////////////////////////////////////////////////////////
  144. // CPatternDlg message handlers
  145. BOOL CPatternDlg::OnInitDialog()
  146. {
  147. CFile cf;
  148. CDialog::OnInitDialog();
  149. mouseDown=0;
  150. int i,j,k;
  151. //将每个笔划上坐标初始化为空
  152. for(i=0;i<15;i++)
  153. {
  154. for(j=0;j<300;j++)
  155. {
  156. store[i][j].x=-1;
  157. store[i][j].y=-1;
  158. }
  159. }
  160. for(i=0;i<15;i++)
  161. {
  162. for(j=0;j<300;j++)
  163. {
  164. storeback[i][j].x=-1;
  165. storeback[i][j].y=-1;
  166. }
  167. }
  168. for(i=0;i<10;i++)
  169. {
  170. tez[i].total=-1;
  171. for(j=0;j<15;j++) 
  172. tez[i].dian[j]=-1;
  173. for(j=0;j<15;j++)
  174. {
  175. for(k=0;k<20;k++)
  176. {
  177. tez[i].detail[j][k].relate=0;
  178. tez[i].detail[j][k].arc=0;
  179. tez[i].detail[j][k].region=0;
  180. }
  181. }
  182. }
  183. Time=0;
  184. num=0;
  185. zong=-1;//tez下标
  186. xmax=0;
  187. ymax=0;
  188. xmin=31;
  189. ymin=31;
  190. for(i=0;i<50;i++)
  191. queue[i]=-1;
  192. for(i=0;i<40;i++)
  193. queue1[i]=-1;
  194. test.total=-1;
  195. for(j=0;j<15;j++) 
  196. test.dian[j]=-1;
  197. for(j=0;j<15;j++)
  198. {
  199. for(k=0;k<20;k++)
  200. {
  201. test.detail[j][k].relate=0;
  202. test.detail[j][k].arc=0;
  203. test.detail[j][k].region=0;
  204. }
  205. }
  206. // Add "About..." menu item to system menu.
  207. // IDM_ABOUTBOX must be in the system command range.
  208. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  209. ASSERT(IDM_ABOUTBOX < 0xF000);
  210. CMenu* pSysMenu = GetSystemMenu(FALSE);
  211. if (pSysMenu != NULL)
  212. {
  213. CString strAboutMenu;
  214. strAboutMenu.LoadString(IDS_ABOUTBOX);
  215. if (!strAboutMenu.IsEmpty())
  216. {
  217. pSysMenu->AppendMenu(MF_SEPARATOR);
  218. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  219. }
  220. }
  221. // Set the icon for this dialog.  The framework does this automatically
  222. //  when the application's main window is not a dialog
  223. SetIcon(m_hIcon, TRUE); // Set big icon
  224. SetIcon(m_hIcon, FALSE); // Set small icon
  225. // TODO: Add extra initialization here
  226. if(cf.Open("mydata.dat",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==NULL){
  227. AfxMessageBox("打开文件失败,n您最好退出程序");}
  228. return TRUE;  // return TRUE  unless you set the focus to a control
  229. }
  230. void CPatternDlg::OnSysCommand(UINT nID, LPARAM lParam)
  231. {
  232. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  233. {
  234. CAboutDlg dlgAbout;
  235. dlgAbout.DoModal();
  236. }
  237. else
  238. {
  239. CDialog::OnSysCommand(nID, lParam);
  240. }
  241. }
  242. // If you add a minimize button to your dialog, you will need the code below
  243. //  to draw the icon.  For MFC applications using the document/view model,
  244. //  this is automatically done for you by the framework.
  245. void CPatternDlg::OnPaint() 
  246. {
  247. CPaintDC dc(this); 
  248. HBRUSH hB;
  249. hB=CreateSolidBrush(RGB(255,255,255));
  250. SelectObject(dc,hB);
  251. Rectangle(dc,Startx,Starty,Startx+wid-1,Starty+lon-1);
  252. DeleteObject(hB);
  253. if (IsIconic())
  254. {
  255. // device context for painting
  256. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  257. // Center icon in client rectangle
  258. int cxIcon = GetSystemMetrics(SM_CXICON);
  259. int cyIcon = GetSystemMetrics(SM_CYICON);
  260. CRect rect;
  261. GetClientRect(&rect);
  262. int x = (rect.Width() - cxIcon + 1) / 2;
  263. int y = (rect.Height() - cyIcon + 1) / 2;
  264. // Draw the icon
  265. dc.DrawIcon(x, y, m_hIcon);
  266. }
  267. else
  268. {
  269. CDialog::OnPaint();
  270. }
  271. }
  272. // The system calls this to obtain the cursor to display while the user drags
  273. //  the minimized window.
  274. HCURSOR CPatternDlg::OnQueryDragIcon()
  275. {
  276. return (HCURSOR) m_hIcon;
  277. }
  278. void CPatternDlg::OnEsp() 
  279. {
  280. OnOK();
  281. }
  282. //识别函数
  283. void CPatternDlg::OnRecog() 
  284. {  
  285. int j1,k1,m1,n1,x,y,xmod,ymod;//xmod,ymod;
  286. int  flagok2=0;
  287. char s[20];
  288. DealData();
  289. //安次序检验,有点下标数
  290. for(j1=0;j1<=zong&&test.total>=0&&flagok2==0;j1++)
  291. {       
  292. if(tez[j1].total==test.total)       //如果总条数相等
  293. {      
  294. for(k1=0;k1<=test.total;k1++)           
  295. {  
  296. if(test.dian[k1]!=tez[j1].dian[k1])  
  297. break;
  298. }
  299.                   
  300. if(k1>test.total)   
  301. //每条得点数相同
  302. {   
  303. for(m1=0;m1<=test.total;m1++)           //每条
  304. {     
  305. for(n1=0;n1<=test.dian[m1];n1++)        //每点
  306. {
  307. xmod=2*(tez[j1].detail[m1][n1].region % 8);  //8等分
  308. ymod=2*((int)tez[j1].detail[m1][n1].region/8);
  309. x=test.detail[m1][n1].region % 16;
  310. y=(int)test.detail[m1][n1].region/16;    //   5/16      
  311.   
  312. if(( test.detail[m1][n1].relate!=tez[j1].detail[m1][n1].relate
  313. &&(test.detail[m1][n1].relate-10*(int)(test.detail[m1][n1].relate/10))!=tez[j1].detail[m1][n1].relate
  314. &&(int)(test.detail[m1][n1].relate/10)!=tez[j1].detail[m1][n1].relate)
  315. ||((tez[j1].detail[m1][n1].arc!=test.detail[m1][n1].arc)&&(test.total<4)&&(test.dian[m1]<4))
  316. ||((x<xmod-3||x>xmod+3)||(y<ymod-3||y>ymod+3)))//shi为total+1
  317. break;
  318. }
  319. if(n1<=test.dian[m1])  
  320. break;
  321. }
  322. if(m1>test.total)
  323. {
  324. flagok2=1;
  325. sprintf(s,"输入正确,可识别,为:%s, 在字库%d个",tez[j1].zifu,j1);
  326. AfxMessageBox(s);
  327. m_edit1.ReplaceSel(tez[j1].zifu); 
  328. OnClear();
  329. }
  330. }
  331. }
  332. }    
  333.    
  334. if(flagok2==0)
  335. AfxMessageBox("字库不足或输入不规范,无法识别,请学习");
  336. OnRecogch();
  337. }
  338. }   
  339.  
  340. //学习函数  
  341. void CPatternDlg::OnStudy() 
  342. {     
  343. int j1,k1,m1,n1,k,m,xmod,ymod,x,y;//j1代表字典中的一个字,k 表示笔划,m 表示一个点
  344. CString z1;
  345. int i,j;
  346. int flagok1=0; //o无法识别,1可识别,已经识别出结果
  347. char s[30];
  348. Inputdialog inputdlg;
  349. //处理数据
  350.     DealData();
  351. if(test.total==-1)
  352. {
  353. AfxMessageBox("没有笔迹输入,n请重示");
  354. }
  355. for(j1=0;j1<=zong&&test.total!=-1;j1++)
  356. {    
  357. if(flagok1==1) 
  358. break;
  359. if(tez[j1].total==test.total&&flagok1==0)      //总笔划相等
  360. {      
  361. for(k1=0;k1<=test.total;k1++)
  362. {
  363. if(test.dian[k1]!=tez[j1].dian[k1])  
  364. break;
  365. }
  366. if(k1>test.total)      //每笔划点数相同下
  367. {  
  368. for(m1=0;m1<=test.total;m1++)
  369. {
  370. for(n1=0;n1<=test.dian[m1];n1++)
  371. {
  372. if(( test.detail[m1][n1].relate!=tez[j1].detail[m1][n1].relate
  373. &&(test.detail[m1][n1].relate % 10)!=tez[j1].detail[m1][n1].relate
  374. &&((int)(test.detail[m1][n1].relate/10))!=tez[j1].detail[m1][n1].relate)
  375. ||(tez[j1].detail[m1][n1].arc!=test.detail[m1][n1].arc))//shi为total+1
  376. break;
  377. xmod=2*(tez[j1].detail[m1][n1].region % 8);  //8等分
  378. ymod=2*((int)tez[j1].detail[m1][n1].region/8);
  379. x=test.detail[m1][n1].region % 16;
  380. y=(int)test.detail[m1][n1].region/16;
  381. if((x<xmod-1||x>xmod+1)||(y<ymod-1||y>ymod+1))
  382. break;      //3/16
  383. }         //对一个笔划的判断,tezheng不等,跳出n
  384. if(n1<=test.dian[m1])  
  385. break; //ci bihua不等,跳出m循环
  386. }
  387. if(m1>test.total&&k1>test.total)//当前库字与输入相符合
  388. {
  389. flagok1=1;
  390.     
  391. sprintf(s,"您输入的是:%s,数据已有",tez[j1].zifu); 
  392.     AfxMessageBox(s);
  393. m_edit1.ReplaceSel(tez[j1].zifu);
  394. OnClear();
  395. }
  396. }
  397. }
  398. }
  399.     
  400. if(flagok1==0&&test.total>=0&&inputdlg.DoModal()==IDOK) //shuruzifu
  401. {
  402. if(inputdlg.m_input1!=inputdlg.m_input2
  403. ||inputdlg.m_input1==""||inputdlg.m_input1==" ")
  404. {
  405. AfxMessageBox("您的输入有误(不等或空格),n请重新输入");
  406. for(i=0;i<50;i++)
  407. queue[i]=-1;
  408. for(i=0;i<40;i++)
  409. queue1[i]=-1;
  410. test.total=-1;
  411. for(j=0;j<15;j++) 
  412.      test.dian[j]=-1;
  413. for(j=0;j<15;j++)
  414. {
  415. for(k=0;k<20;k++)
  416. {
  417. test.detail[j][k].relate=0;
  418. test.detail[j][k].region=0;
  419. }
  420. }
  421. }
  422. else
  423. {
  424. zong++; 
  425. sprintf(tez[zong].zifu,"%s",inputdlg.m_input1);
  426. tez[zong].total=test.total;
  427. for(i=0;i<=test.total;i++)
  428. {
  429. tez[zong].dian[i]=test.dian[i];
  430. for(j=0;j<=test.dian[i];j++)
  431. {
  432. tez[zong].detail[i][j].relate=(test.detail[i][j].relate % 10);
  433. tez[zong].detail[i][j].arc=test.detail[i][j].arc;
  434.     x=(int)(test.detail[i][j].region % 16)/2;
  435. y=(int)(test.detail[i][j].region/16)/2;
  436. tez[zong].detail[i][j].region=8*y+x;
  437. }
  438. }
  439. OnSaveMenu();
  440. if(zong>=2000) 
  441. AfxMessageBox("版本太低,容量受限,Sorry!");
  442. m_edit1.ReplaceSel(inputdlg.m_input1);
  443. OnClear();
  444. }//zong dang前库下标
  445. }
  446. }
  447. void CPatternDlg::OnLButtonDown(UINT nFlags, CPoint point)
  448. {
  449. mouseDown=1;
  450. CWnd::OnLButtonDown(nFlags, point);
  451. }
  452. //鼠标左键抬起
  453. void CPatternDlg::OnLButtonUp(UINT nFlags, CPoint point)
  454. {
  455. mouseDown=0;
  456. if(store[num][Time-1].x>=0&&Time>0)
  457. {
  458. num++;
  459. Time=0;
  460. }
  461. if(num>=14) 
  462. {
  463. AfxMessageBox("写入有误(笔划太多)",NULL,NULL);
  464. OnClear();
  465. }
  466. CWnd::OnLButtonUp(nFlags, point);
  467. }
  468. //鼠标移动事件,模拟手写笔输入
  469. void CPatternDlg::OnMouseMove(UINT nFlags, CPoint point) 
  470. {
  471. // TODO: Add your message handler code here and/or call default
  472. int x,y;
  473. CBrush Brush (RGB (0, 0 , 255) );
  474. CBrush* pOldBrush;
  475. CDC *pDC=GetDC();
  476. CRgn Rgn;
  477. Rgn.CreateRectRgn(Startx,Starty,Startx+wid-1,Starty+lon-1);
  478. pDC->SelectClipRgn(&Rgn);
  479. if((point.x>=Startx)&&(point.x<Startx+wid)&&(point.y>=Starty)
  480. &&(point.y<Starty+lon))
  481. {
  482. HCURSOR m_HCross;
  483. m_HCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);
  484. SetCursor(m_HCross);
  485. }
  486. if((mouseDown==1)&&(point.x>=Startx)&&(point.x<Startx+wid)
  487. &&(point.y>=Starty)&&(point.y<Starty+lon))
  488. {
  489. // Select the brush into the device context .
  490. CBrush* pOldBrush = pDC->SelectObject (&Brush);
  491. pDC->Ellipse(point.x-4,point.y-4,point.x+4,point.y+4);
  492. pDC->SelectObject (pOldBrush );
  493. x=(int)(point.x-Startx)*32/wid;
  494. y= (int)(point.y-Starty)*32/lon;
  495. if(Time==0)
  496. store[num][Time].x=x;
  497. store[num][Time].y=y;
  498. Time++;
  499. if(y>ymax) 
  500. ymax=y;
  501. if(y<ymin) 
  502. ymin=y;
  503. if(x>xmax) 
  504. xmax=x;
  505. if(x<xmin) 
  506. xmin=x;
  507. }
  508.                
  509. else
  510. if(x!=store[num][Time-1].x||y!=store[num][Time-1].y)
  511. {
  512. store[num][Time].x=x;
  513. store[num][Time].y=y;
  514. Time++;
  515. if(y>ymax) 
  516. ymax=y;
  517. if(y<ymin) 
  518. ymin=y;
  519. if(x>xmax) 
  520. xmax=x;
  521. if(x<xmin) 
  522. xmin=x;
  523. }
  524. }
  525. if(Time>=300)
  526. {
  527. AfxMessageBox("当前笔划写入有误(太多)",NULL,NULL);
  528. OnClear();
  529. }
  530. }
  531. ReleaseDC(pDC );
  532. DeleteObject(pOldBrush);
  533. DeleteObject(Rgn);
  534. DeleteObject(Brush);
  535. CWnd::OnMouseMove(nFlags, point);
  536. }
  537. //清空画板
  538. void CPatternDlg::OnClear() 
  539. {
  540. int i,j,k;
  541. CDC *pDC=GetDC();
  542. pDC-> PatBlt (Startx,Starty,wid,lon, PATCOPY );
  543. ReleaseDC(pDC );
  544. mouseDown=0;
  545. for(i=0;i<15;i++){
  546. for(j=0;j<300;j++)
  547. {
  548. store[i][j].x=-1;
  549. store[i][j].y=-1;
  550. }
  551. }
  552. for(i=0;i<15;i++){
  553. for(j=0;j<300;j++)
  554. {
  555. storeback[i][j].x=-1;
  556. storeback[i][j].y=-1;
  557. }
  558. }
  559. Time=0;
  560. num=0;
  561. xmax=0;
  562. ymax=0;
  563. xmin=32;
  564. ymin=32;
  565. for(i=0;i<50;i++)
  566. queue[i]=-1;
  567. for(i=0;i<40;i++)
  568. queue1[i]=-1;
  569. test.total=-1;
  570. for(j=0;j<15;j++) 
  571. test.dian[j]=-1;
  572. for(j=0;j<15;j++)
  573. {
  574. for(k=0;k<20;k++)
  575. {
  576. test.detail[j][k].relate=0;
  577. test.detail[j][k].arc=0;
  578. test.detail[j][k].region=0;
  579. }
  580. }
  581.    
  582. return;
  583. }
  584. //去除噪声
  585. int CPatternDlg::Ridnoise(int j)         //返回k+1个特征点
  586. {
  587. int i,k,ff;
  588. k=0;
  589. ff=test.total+1;      //ff,当前的处理条数,total为已存条数的最大下标
  590. queue1[0]=queue[0];
  591. for(i=1;i<j-1;i++)
  592. if (abs(store[ff][queue[i]].x-store[ff][queue1[k]].x)<yu1+1+1
  593. &&(((store[ff][queue[i]].y-store[ff][queue1[k]].y)*(store[ff][queue[i]].y-store[ff][queue[i+1]].y))<0
  594. ||abs(store[ff][queue[i]].y-store[ff][queue[i+1]].y)<yu2))
  595. {;}
  596. else
  597. {
  598. if (abs(store[ff][queue[i]].y-store[ff][queue1[k]].y)<yu1+1+1
  599. &&(((store[ff][queue[i]].x-store[ff][queue1[k]].x)*(store[ff][queue[i]].x-store[ff][queue[i+1]].x))<0||abs(store[ff][queue[i]].x-store[ff][queue[i+1]].x)<yu2))
  600. {;}    
  601. else
  602. {
  603. k++; 
  604. queue1[k]=queue[i];
  605. }
  606. }
  607. if( abs(store[ff][queue[j-1]].y-store[ff][queue1[k]].y)<2
  608. &&abs(store[ff][queue[j-1]].x-store[ff][queue1[k]].x)<2)
  609. {      
  610. queue1[k]=queue[j-1];
  611. }
  612. else
  613. {
  614. k++;
  615. queue1[k]=queue[j-1];
  616. }
  617.   
  618. return k;
  619. }
  620. //得到arc特征
  621. int CPatternDlg::Getarc(int j)
  622. {
  623. int x1,x2,y1,y2,x3,y3,t1,smax,ci,vct,are;
  624. float s; 
  625. smax=0;ci=0;vct=0;
  626.  
  627. int kk;
  628. kk=test.total;
  629.   
  630. x1=store[kk][queue1[j-1]].x;
  631. y1=store[kk][queue1[j-1]].y;
  632. x3=store[kk][queue1[j]].x;
  633. y3=store[kk][queue1[j]].y;
  634. are=abs(x1-x3);
  635. if(abs(y1-y3)>are) 
  636. are=abs(y1-y3);
  637.  
  638. for(t1=queue1[j-1]+1;t1<queue1[j];t1++)
  639. {
  640. y2=store[kk][t1].y;
  641. x2=store[kk][t1].x;
  642. s=(x1*y2+x2*y3+x3*y1-x1*y3-x2*y1-x3*y2)/are;
  643. if(s>=yu||s<=-yu)
  644. {
  645. if(s*smax==0)
  646. {
  647. if(s>0)
  648. vct=1;
  649. else
  650. vct=-1;
  651. }
  652.  
  653. if(s*smax<=0)
  654. {
  655. ci++;
  656. smax=s;
  657. }
  658. if(abs(smax)<abs(s)) 
  659. smax=s;
  660. }
  661. }
  662.  
  663. ci=vct*ci;
  664. return ci;
  665. }
  666. //保存特征点
  667. void CPatternDlg::Save(int k)//此条共k+1个点
  668. {     
  669. int i,j,m,l,tat;
  670. float value;
  671. test.total++; //特征总条数加一
  672. tat=test.total;//没有排序
  673. test.dian[test.total]=k;//k+1 points,初值为-1,定义此条值
  674. for(j=0;j<=k;j++)
  675. {   
  676. m=(int)((store[tat][queue1[j]].x-xmin)*16/(xmax-xmin+1));
  677. l=(int)((store[tat][queue1[j]].y-ymin)*16/(ymax-ymin+1));
  678. test.detail[tat][j].region=16*l+m;
  679. if(j==0)
  680. {
  681. test.detail[tat][j].relate=10;
  682. test.detail[tat][j].arc=0;
  683. }
  684. if(j>0)
  685. {
  686. if((store[tat][queue1[j]].x-store[tat][queue1[j-1]].x)>5.67*abs(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y))
  687. {
  688. test.detail[test.total][j].relate=1;
  689. test.detail[test.total][j].arc=Getarc(j);
  690. }
  691. else 
  692. {
  693. if((store[tat][queue1[j]].x-store[tat][queue1[j-1]].x)<-5.67*abs(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y))
  694. {
  695. test.detail[test.total][j].relate=9;
  696. test.detail[test.total][j].arc=Getarc(j);
  697. }
  698. else
  699. {
  700. if(5.67*abs(store[tat][queue1[j]].x-store[tat][queue1[j-1]].x)<(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y))
  701. {
  702. test.detail[test.total][j].relate=7;
  703. test.detail[test.total][j].arc=Getarc(j);
  704. }
  705. else 
  706. {
  707. if(-5.67*abs(store[tat][queue1[j]].x-store[tat][queue1[j-1]].x)>(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y))
  708. {
  709. test.detail[test.total][j].relate=3;
  710. test.detail[test.total][j].arc=Getarc(j);
  711. }
  712. else
  713. {
  714. value=(float)(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)/(store[tat][queue1[j]].x-store[tat][queue1[j-1]].x);
  715. if(value<2.747&&value>0.364&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)>0)
  716. {
  717. test.detail[test.total][j].relate=6;
  718. test.detail[test.total][j].arc=Getarc(j);
  719. }
  720. if(value<2.747&&value>0.364&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)<0)
  721. {
  722. test.detail[test.total][j].relate=4;
  723. test.detail[test.total][j].arc=Getarc(j);
  724. }
  725.             
  726. if(value>-2.747&&value<-0.364&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)>0)
  727. {
  728. test.detail[test.total][j].relate=8;
  729. test.detail[test.total][j].arc=Getarc(j);
  730. }
  731. if(value>-2.747&&value<-0.364&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)<0)
  732. {
  733. test.detail[test.total][j].relate=2;
  734. test.detail[test.total][j].arc=Getarc(j);
  735. }
  736. if(value<=5.61&&value>=2.747&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)>0)
  737. {
  738. test.detail[test.total][j].relate=76;
  739. test.detail[test.total][j].arc=Getarc(j);
  740. }
  741. if(value<=5.61&&value>=2.747&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)<0)
  742. {
  743. test.detail[test.total][j].relate=34;
  744. test.detail[test.total][j].arc=Getarc(j);
  745. }
  746. if(value>=-5.61&&value<=-2.747&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)>0)
  747. {
  748. test.detail[test.total][j].relate=78;
  749. test.detail[test.total][j].arc=Getarc(j);
  750. }
  751. if(value>=-5.61&&value<=-2.747&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)<0)
  752. {
  753. test.detail[test.total][j].relate=32;
  754. test.detail[test.total][j].arc=Getarc(j);
  755. }
  756. if(value<=0.364&&value>=0.1782&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)>0)
  757. {
  758. test.detail[test.total][j].relate=16;
  759. test.detail[test.total][j].arc=Getarc(j);
  760. }
  761. if(value<=0.364&&value>=0.1782&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)<0)
  762. {
  763. test.detail[test.total][j].relate=94;
  764. test.detail[test.total][j].arc=Getarc(j);
  765. }
  766.            
  767. if(value>=-0.364&&value<=-0.1782&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)>0)
  768. {
  769. test.detail[test.total][j].relate=98;
  770. test.detail[test.total][j].arc=Getarc(j);
  771. }
  772.            
  773. if(value>=-0.364&&value<=-0.1782&&(store[tat][queue1[j]].y-store[tat][queue1[j-1]].y)<0)
  774. {
  775. test.detail[test.total][j].relate=12;
  776. test.detail[test.total][j].arc=Getarc(j);
  777. }
  778. }
  779. }
  780. }
  781. }
  782. }
  783. }
  784.   
  785. for(i=0;i<50;i++)
  786. queue[i]=-1;
  787. for(i=0;i<40;i++)
  788. queue1[i]=-1;       //must
  789. }
  790. //进一步处理数据,提取特征
  791. void  CPatternDlg::DealData()
  792. {  
  793. int i,j,k,num1,Time1;
  794. Inorder();
  795. for(num1=0;store[num1][0].x>-1;num1++)        //第几条线
  796. {
  797. for(Time1=0,j=0;store[num1][Time1].x>-1;Time1++) 
  798. {       
  799. if(Time1==0)
  800. {
  801. queue[j]=Time1;j++;
  802. }
  803. if(Time1>0&&store[num1][Time1+1].x==-1)
  804. {
  805. queue[j]=Time1;j++;
  806. }
  807.         
  808. if(Time1>0&&store[num1][Time1+1].x!=-1)
  809. {
  810. if((store[num1][Time1+1].x-store[num1][Time1].x)*(store[num1][Time1-1].x-store[num1][Time1].x)>0||(store[num1][Time1+1].y-store[num1][Time1].y)*(store[num1][Time1-1].y-store[num1][Time1].y)>0)
  811. {
  812. queue[j]=Time1;j++;
  813. }
  814. if (store[num1][Time1-1].x-store[num1][Time1].x==0)//&&(store[num1][Time1+1].x-store[num1][Time1].x!0))
  815. {
  816. for(i=1;store[num1][Time1-1-i].x==store[num1][Time1-1].x&&(Time1-1-i)>=0;i++){;}
  817. if((store[num1][Time1+1].x-store[num1][Time1].x)*(store[num1][Time1-1-i].x-store[num1][Time1].x)>0)
  818. {
  819. queue[j]=Time1;j++;
  820. }
  821. }
  822. if (store[num1][Time1-1].y-store[num1][Time1].y==0)//&&(store[num1][Time1+1].y-store[num1][Time1].y)<0)
  823. {
  824. for(i=1;store[num1][Time1-1-i].y==store[num1][Time1-1].y&&(Time1-1-i)>=0;i++){;}
  825. if((store[num1][Time1+1].y-store[num1][Time1].y)*(store[num1][Time1-1-i].y-store[num1][Time1].y)>0)
  826. {
  827. queue[j]=Time1;j++;
  828. }
  829. }
  830. }
  831. }
  832. k=Ridnoise(j);    //共j点,0到j-1
  833. Save(k);
  834. }
  835. }
  836. CPatternDlg::OnRecogch()                                 //清空获取的特征
  837. {
  838. int i,j,k;
  839. for(i=0;i<50;i++)
  840. queue[i]=-1;
  841. for(i=0;i<40;i++)
  842. queue1[i]=-1;
  843. test.total=-1;
  844. for(j=0;j<15;j++) 
  845.      test.dian[j]=-1;
  846. for(j=0;j<15;j++)
  847. {
  848. for(k=0;k<20;k++)
  849. {
  850. test.detail[j][k].relate=0;
  851. test.detail[j][k].arc=0;
  852. test.detail[j][k].region=0;
  853. }
  854. }
  855. return(1);
  856. }
  857. void CPatternDlg::OnExitMenu() 
  858. {
  859. // TODO: Add your command handler code here
  860. OnEsp();
  861. }
  862. void CPatternDlg::OnAboutMenu() 
  863. {  
  864. CAboutDlg cabout;
  865. // TODO: Add your command handler code here
  866. if(cabout.DoModal()==1)
  867. {;}
  868. }
  869. void CPatternDlg::OnSaveMenu() 
  870. {
  871. // TODO: Add your command handler code here
  872. CFile cf;
  873. int k,j;
  874. if(cf.Open("mydata.dat",CFile::modeReadWrite)==NULL)
  875. {
  876. AfxMessageBox("打开文件失败,n您最好退出程序");
  877. }
  878. else 
  879. {       
  880. cf.SeekToEnd();
  881. cf.Write(&tez[zong].zifu, sizeof(char)*2);
  882. cf.Write(&tez[zong].total, sizeof(int));
  883. for(j=0;j<=tez[zong].total;j++)
  884. {
  885. cf.Write(&tez[zong].dian[j], sizeof(int));
  886. }
  887.    
  888. for(j=0;j<=tez[zong].total;j++)
  889. {
  890. for(k=0;k<=tez[zong].dian[j];k++)
  891. {
  892. cf.Write(&tez[zong].detail[j][k].relate,sizeof(int));
  893. cf.Write(&tez[zong].detail[j][k].region, sizeof(int));
  894. cf.Write(&tez[zong].detail[j][k].arc, sizeof(int));
  895. }
  896. }
  897. cf.Close( );
  898. }
  899. }
  900. void CPatternDlg::OnOpenMenu() 
  901. {
  902. CFile cf;
  903. char s[20];
  904. int j,k;
  905. int nFileSize;
  906. int tt;
  907. if(cf.Open("mydata.dat",CFile::modeReadWrite)==NULL)
  908. {
  909. AfxMessageBox("打开文件失败,n您最好退出程序");
  910. }
  911. else 
  912. {     
  913. cf.SeekToBegin(); 
  914. nFileSize=cf.GetLength( ); 
  915.     for(zong=0,tt=0;tt<nFileSize-1;zong++)                //最后减一
  916. {  
  917. cf.Read(&tez[zong].zifu, sizeof(char)*2);
  918. tt=tt+sizeof(char)*2;
  919. cf.Read(&tez[zong].total, sizeof(int));
  920. tt=tt+sizeof(int);
  921. for(j=0;j<=tez[zong].total;j++)
  922. {
  923. cf.Read(&tez[zong].dian[j], sizeof(int));
  924. tt=tt+sizeof(int);}
  925.    
  926. for(j=0;j<=tez[zong].total;j++)
  927. {
  928. for(k=0;k<=tez[zong].dian[j];k++)
  929. {
  930. cf.Read(&tez[zong].detail[j][k].relate,sizeof(int));
  931. cf.Read(&tez[zong].detail[j][k].region, sizeof(int));
  932. cf.Read(&tez[zong].detail[j][k].arc, sizeof(int));
  933. tt=tt+sizeof(int)*3;
  934. }
  935. }
  936. }
  937. zong--;
  938. }
  939. cf.Close( );
  940. sprintf(s,"读入正确,共有字 %d",zong);
  941. AfxMessageBox(s);
  942. }
  943. void CPatternDlg::OnSaveMenu1()
  944. {
  945. AfxMessageBox("Save OK");
  946. }
  947. void CPatternDlg::Inorder()
  948. {
  949. int i,j,k,num1,Time1;
  950. int  xxbegin,xxend,yybegin,yyend,total;
  951.    
  952. for(num1=0;store[num1][0].x>-1;num1++)        //第几条线
  953. {
  954. xxbegin=store[num1][0].x;
  955. yybegin=store[num1][0].y;
  956. for(Time1=0,j=0;store[num1][Time1].x>-1;Time1++) 
  957. {;}
  958. total=Time1;
  959. xxend=store[num1][Time1-1].x;
  960. yyend=store[num1][Time1-1].y;
  961. for(Time1=0;store[num1][Time1].x>-1;Time1++) 
  962. {
  963. storeback[0][total-Time1-1].x=store[num1][Time1].x;
  964. storeback[0][total-Time1-1].y=store[num1][Time1].y;
  965. }
  966.    
  967. if(abs(xxbegin-xxend)>2*abs(yybegin-yyend)&&(xxbegin>xxend))
  968. {
  969. for(j=0;j<total;j++)
  970. {
  971. store[num1][j].x=storeback[0][j].x;
  972. store[num1][j].y=storeback[0][j].y;
  973. }
  974. }
  975. if(abs(xxbegin-xxend)<=2*abs(yybegin-yyend)&&(yybegin>yyend))
  976. {
  977. for(j=0;j<total;j++)
  978. {
  979. store[num1][j].x=storeback[0][j].x;
  980. store[num1][j].y=storeback[0][j].y;
  981. }
  982. }
  983. }
  984. }