dipView.cpp
上传用户:cdscwht
上传日期:2022-07-27
资源大小:264k
文件大小:79k
源码类别:

图形/文字识别

开发平台:

Visual Basic

  1. // dipView.cpp : implementation of the CDipView class
  2. //
  3. #include "stdafx.h"
  4. #include "dip.h"
  5. #include "dipDoc.h"
  6. #include "dipView.h"
  7. #include "afxdlgs.h"
  8. #include "afxwin.h"
  9. #include "math.h"
  10. #include ".dipview.h"
  11. #include "stdlib.h"
  12. #include "malloc.h"
  13. #include "mainfrm.h"
  14. #include "charview.h"
  15. #include "recvchar.h"
  16. #include "training.h"
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CDipView
  24. IMPLEMENT_DYNCREATE(CDipView, CView)
  25. BEGIN_MESSAGE_MAP(CDipView, CView)
  26. //{{AFX_MSG_MAP(CDipView)
  27. ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
  28. ON_WM_PAINT()
  29. ON_COMMAND(ID_FILE_SAVE, OnFileSave)
  30. ON_COMMAND(ID_reopen, Onreopen)
  31. ON_WM_MOUSEMOVE()
  32. ON_WM_CREATE()
  33. ON_COMMAND(ID_LINE, OnLine)
  34. ON_COMMAND(ID_F3, Onfse)
  35. ON_COMMAND(ID_F4, Onfz)
  36. ON_COMMAND(ID_MoHu, OnMoHu)
  37. ON_COMMAND(ID_ForHandle, OnForHandle)
  38. ON_COMMAND(ID_HSearch, OnHSearch)
  39. ON_COMMAND(ID_Banlance, OnBanlance)
  40. ON_COMMAND(ID_SubVertical, OnSubVertical)
  41. ON_COMMAND(ID_SubHorizontal, OnSubHorizontal)
  42. ON_COMMAND(ID_MidValue, OnMidValue)
  43. ON_COMMAND(ID_Average, OnAverage)
  44. ON_COMMAND(ID_Bool, OnBool)
  45. ON_COMMAND(ID_Choose, OnChoose)
  46. ON_COMMAND(ID_TRAINFROMVEHICLE, OnTrainfromvehicle)
  47. ON_COMMAND(ID_SAVESA, OnSave)
  48. ON_COMMAND(ID_READSA, OnLoad)
  49. ON_COMMAND(ID_CHANGE, OnChange)
  50. ON_COMMAND(ID_TRAIN, OnTrain)
  51. ON_COMMAND(ID_SAVEBP, OnSavebp)
  52. ON_COMMAND(ID_VSearch, OnVSearch)
  53. ON_COMMAND(ID_Locate, OnLocate)
  54. ON_COMMAND(ID_Sobel, OnSobel)
  55. ON_COMMAND(ID_VSplit, OnVSplit)
  56. ON_COMMAND(ID_CharacterRec, OnCharacterRecg)
  57. ON_COMMAND(ID_READBP, OnReadbp)
  58. //}}AFX_MSG_MAP
  59. // Standard printing commands
  60. ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
  61. ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
  62. ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
  63. END_MESSAGE_MAP()
  64. /////////////////////////////////////////////////////////////////////////////
  65. // CDipView construction/destruction
  66. CDipView::CDipView()
  67. //: Height(NULL)
  68. //, TopRow(NULL)
  69. //: Widths(NULL)
  70. //, Left(NULL)
  71. //: Rect_X(NULL)
  72. //, Rect_Y(NULL)
  73. //, Rect_W(NULL)
  74. //, Rect_H(NULL)
  75. //, Rect_Areas(0)
  76. {
  77. // TODO: add construction code here
  78. //初始化
  79. m_pMemDC=new CDC; //分配内存DC
  80. m_pBitmap=new CBitmap; //分配背景图像的空间
  81. IsNewFile=true;
  82. IsNewBitmap=true;
  83. m_pBmp=NULL;
  84. Height=new int[20];
  85. TopRow=new int[20];
  86. Widths=new int[30];                     //Top' width
  87. Left=new int[30];                   //Top' top col
  88. Rect_X=new int[50];
  89.     Rect_Y=new int[50]; 
  90. Rect_W=new int[50];
  91.     Rect_H=new int[50];
  92. Rect_Areas=0;
  93. cRects=new crect[10];
  94. CharacterNum=0;
  95. cDatas=new cData[10];        //实际大小由CharacterNum确定
  96. char_ConnectPos=NULL;
  97. num_ConnectPos=NULL;
  98. han_ConnectPos=NULL;
  99. }
  100. CDipView::~CDipView()
  101. {
  102. //释放内存
  103. delete m_pBitmap;
  104. delete m_pMemDC;
  105. }
  106. BOOL CDipView::PreCreateWindow(CREATESTRUCT& cs)
  107. {
  108. // TODO: Modify the Window class or styles here by modifying
  109. //  the CREATESTRUCT cs
  110. return CView::PreCreateWindow(cs);
  111. }
  112. /////////////////////////////////////////////////////////////////////////////
  113. // CDipView drawing
  114. void CDipView::OnDraw(CDC* pDC)
  115. {
  116. CDipDoc* pDoc = GetDocument();
  117. ASSERT_VALID(pDoc);
  118. // TODO: add draw code for native data here
  119. //如果已经读入一幅新的图像,则向CDC中写入新的图像信息
  120. if ((pDoc->ImgData!=NULL)&&IsNewFile)
  121. {
  122. //
  123.    ChageStatuBar(&"正在打开文件 ");
  124. //
  125. int i,j,k;
  126. k=0;
  127. BYTE r,g,b;
  128. for(i=0;i<pDoc->ImgHeight;i++)
  129. for(j=0;j<pDoc->ImgWidth;j++)
  130. {
  131. //从调色板中得到r,g,b分量
  132. r=pDoc->palette[pDoc->ImgData[k]].rgbBlue;
  133. g=pDoc->palette[pDoc->ImgData[k]].rgbGreen;
  134. b=pDoc->palette[pDoc->ImgData[k]].rgbRed;
  135. pDC->SetPixel(j,i,(r<<16)|(g<<8)|b);
  136. k++;
  137. }
  138. IsNewFile=false; //写完后,将文件标志位置为假
  139.     //恢复鼠标
  140.  
  141.     char * path =pDoc->FileName.GetBuffer(256) ;
  142. ChageStatuBar(path);
  143. }
  144.        
  145. }
  146. /////////////////////////////////////////////////////////////////////////////
  147. // CDipView printing
  148. BOOL CDipView::OnPreparePrinting(CPrintInfo* pInfo)
  149. {
  150. // default preparation
  151. return DoPreparePrinting(pInfo);
  152. }
  153. void CDipView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  154. {
  155. // TODO: add extra initialization before printing
  156. }
  157. void CDipView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  158. {
  159. // TODO: add cleanup after printing
  160. }
  161. /////////////////////////////////////////////////////////////////////////////
  162. // CDipView diagnostics
  163. #ifdef _DEBUG
  164. void CDipView::AssertValid() const
  165. {
  166. CView::AssertValid();
  167. }
  168. //setpentext
  169. void CDipView::Dump(CDumpContext& dc) const
  170. {
  171. CView::Dump(dc);
  172. }
  173. CDipDoc* CDipView::GetDocument() // non-debug version is inline
  174. {
  175. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDipDoc)));
  176. return (CDipDoc*)m_pDocument;
  177. }
  178. #endif //_DEBUG
  179. /////////////////////////////////////////////////////////////////////////////
  180. // CDipView message handlers
  181. //打开一个BMP文件
  182. void CDipView::OnFileOpen() 
  183. {
  184. // TODO: Add your command handler code here
  185. CFileDialog mydlg(true);
  186. CString filename;
  187. mydlg.m_ofn.lpstrFilter="BMP files(*.bmp)*.bmpJPG files(*.jpg)*.jpg";
  188. //显示文件对话框
  189. if (mydlg.DoModal()==IDOK)
  190. {
  191. filename=mydlg.GetPathName();
  192. //读入文件
  193. CDipDoc * myDoc;
  194. myDoc=GetDocument();            //enable you to call the number
  195.                                 //function of CDocment 
  196. myDoc->FileOpen(filename);
  197. //将文件标志位和图像标志位置为真
  198. IsNewFile=true;
  199. IsNewBitmap=true;
  200. //刷新屏幕
  201. myDoc->UpdateAllViews(NULL);
  202. }
  203. }
  204. void CDipView::OnPaint() 
  205. {
  206. CPaintDC dc(this); // device context for painting
  207. // TODO: Add your message handler code here
  208. this->GetActiveWindow()->SetWindowText("数字图像处理程序");
  209. //设定从内存DC到屏幕DC的拷贝区域
  210. CRect rc(0,0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN));
  211. CBitmap * pOldBitmap=(CBitmap *)(m_pMemDC->SelectObject(m_pBitmap));
  212. if (IsNewBitmap)
  213. m_pMemDC->Rectangle(-1,-1,2000,2000); //新图,清除背景
  214. else
  215. m_pMemDC->SelectObject(mymap); //旧图,直接调用内存中的图像
  216. m_pMemDC->SelectClipRgn(NULL);
  217. OnDraw(m_pMemDC); //向内存DC中画图像
  218. //拷贝到屏幕DC中
  219. dc.BitBlt(rc.left,rc.top,rc.Width(),rc.Height(),m_pMemDC,rc.left,rc.top,SRCCOPY);
  220. if (IsNewBitmap)
  221. {
  222. //保存历史图像,已备下次显示
  223. mymap=m_pMemDC->GetCurrentBitmap();
  224. IsNewBitmap=false;
  225. }
  226. m_pMemDC->SelectObject(pOldBitmap);
  227. // m_wait=theapp->LoadCursor(IDC_ARROW);
  228. // SetCursor(m_wait);
  229. // Do not call CView::OnPaint() for painting messages
  230. }
  231. void CDipView::OnInitialUpdate() 
  232. {
  233. CView::OnInitialUpdate();
  234. // ChageStatuBar(&"请打开一个BMP格式的位图文件");
  235. // TODO: Add your specialized code here and/or call the base class
  236. //初始化m_pMemDC和m_pBitmap
  237. if (m_pMemDC->GetSafeHdc()==NULL)
  238. {
  239. CClientDC dc(this);
  240. OnPrepareDC(&dc);
  241. //设定背景图像的大小
  242. CRect rc(0,0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN));
  243. m_pMemDC->CreateCompatibleDC(&dc);
  244. m_pBitmap->CreateCompatibleBitmap(&dc,rc.right,rc.bottom);
  245. }
  246. CDipDoc* pDoc=GetDocument();
  247. int i;
  248.    for( i=0;i<pDoc->ImgWidth*pDoc->ImgHeight;i++)
  249.    img[i]=pDoc->ImgData[i];
  250.    
  251. }
  252. void CDipView::OnFileSave() 
  253. {
  254. // TODO: Add your command handler code here
  255. CFileDialog mydlg(false);
  256. CString filename,promt;
  257. mydlg.m_ofn.lpstrFilter="BMP files(*.bmp)*.bmp";
  258. //打开存储对话框
  259. if (mydlg.DoModal()==IDOK)
  260. {
  261. filename=mydlg.GetPathName();
  262. if(filename.Find(".bmp")<=0)
  263. filename=filename+".bmp";
  264. //存储图像
  265. CDipDoc* pDoc = GetDocument();
  266. pDoc->FileSave(filename);
  267. }
  268. }
  269. //重新显示原始图像
  270. void CDipView::Onreopen() 
  271. {
  272. // TODO: Add your command handler code here
  273. CDipDoc* pDoc = GetDocument();
  274. pDoc->FileOpen();
  275. IsNewBitmap=true;
  276. IsNewFile=true;
  277. pDoc->UpdateAllViews(NULL);
  278. }
  279. void CDipView::OnMouseMove(UINT nFlags, CPoint point) 
  280. {
  281. if (AfxGetApp() != NULL && AfxGetApp()->m_pMainWnd != NULL) {
  282. char buffer[256];
  283. CStatusBar* pStatus = (CStatusBar*) 
  284. AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
  285. va_list argptr;
  286. pStatus->SetPaneInfo(2,2,SBPS_STRETCH  ,7);       
  287. CString x;
  288. x.Format(_T("%d"),point.x); 
  289. CString y;
  290. y.Format(_T("%d"),point.y); 
  291.  CString zuobiao=" x= "+x + " , " + "y= " +y;
  292. char * fmt=zuobiao.GetBuffer(12);
  293. va_start(argptr, fmt);
  294. vsprintf(buffer, fmt, argptr);
  295. va_end(argptr);
  296.         if (pStatus != NULL)
  297. {
  298. pStatus->SetPaneText(2, buffer);
  299. pStatus->UpdateWindow();
  300. }
  301. }
  302. // TODO: Add your message handler code here and/or call default
  303. CView::OnMouseMove(nFlags, point);
  304. }
  305. void CDipView::ChageStatuBar(char * fmt)
  306. {
  307. if (AfxGetApp() != NULL && AfxGetApp()->m_pMainWnd != NULL) {
  308. char buffer[256];
  309. CStatusBar* pStatus = (CStatusBar*) 
  310. AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
  311. va_list argptr;
  312. va_start(argptr, fmt);
  313. vsprintf(buffer, fmt, argptr);
  314. va_end(argptr);
  315. if (pStatus != NULL) {
  316. pStatus->SetPaneText(0, buffer);
  317. pStatus->UpdateWindow();
  318. }
  319. }
  320. }
  321. //DEL BOOL CDipView::OnEraseBkgnd(CDC* pDC) 
  322. //DEL {
  323. //DEL  // TODO: Add your message handler code here and/or call default
  324. //DEL  if (AfxGetApp() != NULL && AfxGetApp()->m_pMainWnd != NULL) {
  325. //DEL  char buffer[256];
  326. //DEL  CStatusBar* pStatus = (CStatusBar*) 
  327. //DEL  AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
  328. //DEL 
  329. //DEL  va_list argptr;
  330. //DEL  // char * fmt =&" BMPBMPBMPBMP";
  331. //DEL //gai kuandu
  332. //DEL  pStatus->SetPaneInfo(2,2,SBPS_STRETCH  ,7);
  333. //DEL        //itoa(point.x,,10)
  334. //DEL 
  335. //DEL  char * fmt="请打开文件";
  336. //DEL  va_start(argptr, fmt);
  337. //DEL  vsprintf(buffer, fmt, argptr);
  338. //DEL  va_end(argptr);
  339. //DEL         if (pStatus != NULL)
  340. //DEL  {
  341. //DEL  // pStatus
  342. //DEL  pStatus->SetPaneText(2, buffer);
  343. //DEL  pStatus->UpdateWindow();
  344. //DEL  }
  345. //DEL  }
  346. //DEL  return CView::OnEraseBkgnd(pDC);
  347. //DEL }
  348. int CDipView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  349. {
  350. if (CView::OnCreate(lpCreateStruct) == -1)
  351. return -1;
  352. OnLoad();
  353. char_bp.Initialize(3434);
  354. char_bp.CreateBP(13,60,26);
  355. num_bp.Initialize(3434);
  356. num_bp.CreateBP(13,60,10);
  357. char_num_bp.Initialize(3434);
  358. char_num_bp.CreateBP(13,60,36);
  359. // TODO: Add your specialized creation code here
  360. // ChageStatuBar(&"请打开一个BMP格式的位图文件");
  361. return 0;
  362. }
  363. void CDipView::OnLine() 
  364. {
  365. // TODO: Add your command handler code here
  366. CDipDoc* pDoc = GetDocument();
  367. ASSERT_VALID(pDoc);
  368. Mdlg dlg;
  369. dlg.DoModal();
  370. a=dlg.m_edit1;
  371. b=dlg.m_edit2;
  372. for(int i=0;i<pDoc->ImgWidth*pDoc->ImgHeight;i++)
  373. {
  374. pDoc->ImgData[i]=a*pDoc->ImgData[i]+b;
  375. if(pDoc->ImgData[i]>255) pDoc->ImgData[i]=255;
  376. if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0;
  377. }
  378.      IsNewFile=true;
  379.      IsNewBitmap=true;
  380.  
  381. Invalidate();
  382. }
  383. void CDipView::Onfse() 
  384. {
  385. // TODO: Add your command handler code here
  386. CDipDoc* pDoc = GetDocument();
  387. ASSERT_VALID(pDoc);
  388. for(int i=0;i<pDoc->ImgWidth*pDoc->ImgHeight;i++)
  389. {
  390. //pDoc->ImgData[i]=a*pDoc->ImgData[i]+b;
  391.   pDoc->ImgData[i]=255-pDoc->ImgData[i];
  392. //if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0;
  393. }
  394.  IsNewFile=true;
  395.      IsNewBitmap=true;
  396.  
  397. Invalidate();
  398. }
  399. void CDipView::Onfz() 
  400. {
  401. // TODO: Add your command handler code here
  402. CDipDoc* pDoc = GetDocument();
  403. ASSERT_VALID(pDoc);
  404. BYTE * ImgData1=new BYTE[pDoc->ImgWidth*pDoc->ImgHeight];
  405. for(int i=0;i<pDoc->ImgWidth*pDoc->ImgHeight;i++)
  406. {
  407. //pDoc->ImgData[i]=a*pDoc->ImgData[i]+b;
  408.   ImgData1[pDoc->ImgWidth*pDoc->ImgHeight-i]=pDoc->ImgData[i];
  409. //if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0;
  410. }
  411. for( i=0;i<pDoc->ImgWidth*pDoc->ImgHeight;i++)
  412. {
  413. //pDoc->ImgData[i]=a*pDoc->ImgData[i]+b;
  414. pDoc->ImgData[i]=ImgData1[i];
  415. //if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0;
  416. }
  417.  IsNewFile=true;
  418.      IsNewBitmap=true;
  419.  
  420. Invalidate();
  421. }
  422. void CDipView::OnMoHu() 
  423. {
  424. // TODO: Add your command handler code here
  425. CDipDoc* pDoc = GetDocument();
  426. int h=pDoc->ImgHeight;
  427. int w=pDoc->ImgWidth;
  428. BYTE * g=new BYTE[h*w];
  429. float temp;
  430. //标示图象的坐标
  431. int x,y;
  432. //标示算子的坐标
  433. int i,j;
  434. BYTE mb[3][3]={{-1,0,0},{0,0,0},{0,0,1}};
  435.   
  436. for(x=1;x<h-1;x++)
  437. {
  438. for(y=1;y<w-1;y++)
  439. {
  440. temp=0;
  441.     for(i=0;i<3;i++)
  442.      {
  443.      for(j=0;j<3;j++)
  444. {
  445.      temp=temp+(float( mb[i][j])*( float (pDoc->ImgData[(x-1+i)*w+(y-1+j)])));
  446. }
  447. }
  448. g[x*w+y]=int(temp);
  449. }
  450. }
  451. for(x=1;x<h-1;x++)
  452. for(y=1;y<w-1;y++)
  453. pDoc->ImgData[x*w+y]=g[x*w+y];
  454. IsNewFile=true;
  455.     IsNewBitmap=true;  
  456. Invalidate();
  457. }
  458. void CDipView::OnForHandle() 
  459. {
  460. // TODO: Add your command handler code here
  461.  CDipDoc *p=GetDocument();
  462.  BYTE *temp=new BYTE[p->ImgHeight*p->ImgWidth];
  463.  int x,y;
  464. for(x=0;x<p->ImgHeight;x++)
  465. {
  466. for(y=0;y<p->ImgWidth;y++)
  467.  {
  468. temp[(x*p->ImgWidth)+y]=p->ImgData[(x*p->ImgWidth)+y];
  469. }
  470. }
  471.  long double total=0;
  472.  float aver=0;
  473.  for(x=0;x<p->ImgHeight;x++)
  474.  {
  475.  for(y=0;y<p->ImgWidth;y++)
  476.  {
  477.  total+=p->ImgData[x*p->ImgWidth+y];
  478.  }
  479.  }
  480.  aver=(BYTE)(total/(float)(p->ImgHeight*p->ImgWidth));
  481.  float delt; 
  482.  float sub=0; 
  483.  for(x=0;x<p->ImgHeight;x++)
  484.  {
  485.  for(y=0;y<p->ImgWidth;y++)
  486.  {
  487.  sub+=(p->ImgData[x*p->ImgWidth+y]-aver)*(p->ImgData[x*p->ImgWidth+y]-aver);  
  488.  }
  489.  }
  490.  delt=(float)(sqrt(sub/(float)(p->ImgHeight*p->ImgWidth)));
  491.  BYTE judge;
  492.  judge=(BYTE)(delt+aver);
  493.  for(x=0;x<p->ImgHeight;x++)
  494.  {
  495. for(y=0;y<p->ImgWidth;y++)
  496.  {
  497. if(p->ImgData[(x*p->ImgWidth)+y]>=judge)
  498. {
  499. p->ImgData[(x*p->ImgWidth)+y]=255;
  500. }
  501. else
  502. {
  503. p->ImgData[(x*p->ImgWidth)+y]=0;
  504. }
  505. }
  506. }
  507.  
  508.  free(temp);
  509.  IsNewBitmap=true;
  510.  IsNewFile=true;
  511.  p->UpdateAllViews(NULL);
  512. }
  513. void CDipView::OnHSearch() 
  514. {
  515. // TODO: Add your command handler code here
  516. CDipDoc *pDoc=GetDocument();
  517. int width,height;
  518. width=pDoc->ImgWidth;
  519. height=pDoc->ImgHeight;
  520. BYTE *g=new BYTE[width*height];
  521.     int *Count= new int[height];
  522. int *TempCount=new int[height];
  523. int *maxChanges=new int[10];
  524. int *Rows=new int[10];                                  
  525. int H[20];
  526. int Top[20];
  527.  
  528. for(int row=0;row<pDoc->ImgHeight;row++)
  529.  {
  530. for(int col=0;col<pDoc->ImgWidth;col++)
  531. {
  532.    g[row*width+col]=pDoc->ImgData[row*width+col];
  533. }
  534.  }
  535.  
  536. for(int c=0;c<height;c++)
  537. {
  538. Count[c]=0;
  539. TempCount[c]=0;
  540. }
  541. for(c=0;c<10;c++)
  542. {
  543.         maxChanges[c]=0;
  544.     Rows[c]=0; 
  545. H[c]=0;
  546. Top[c]=1;
  547. }
  548.     for(row=0;row<height;row++)
  549. {
  550. for(int col=0;col<width-1;col++)
  551. {
  552. if(pDoc->ImgData[row*width+col]!=pDoc->ImgData[row*width+col+1])
  553. Count[row]++;
  554. }
  555. TempCount[row]=Count[row];
  556. }
  557. /////////////////////////////////////Top 10 chage row
  558. for(int top=0;top<10;top++)
  559. {
  560. int Max=0;
  561. for(row=0;row<height;)
  562. {
  563. if(Max<TempCount[row])
  564. {
  565. Max=TempCount[row];
  566. }
  567. row=row+10 ;
  568. }
  569. maxChanges[top]=Max;
  570. int R=0;
  571.      for(row=0;row<height;)
  572. {
  573.      if(Max!=TempCount[row])
  574. {
  575.      row=row+10;
  576. }
  577. else
  578. {
  579. R=row;
  580. break;
  581. }
  582. }
  583. Rows[top]=R;
  584. TempCount[R]=0;
  585. }
  586. for(top=0;top<10;top++)
  587. {
  588. for(int range=-10;range<10;range++)
  589. {
  590. if((0.7*Count[Rows[top]]<=Count[Rows[top]+range])&&(Count[Rows[top]+range]<=1.3*Count[Rows[top]]))
  591. {
  592.  for(int col=0;col<width;col++)
  593.  {
  594.          g[(Rows[top]+range)*width+col]=255;
  595.  }
  596. }
  597. }
  598. }
  599.  for(row=0;row<height;row++)
  600.  {
  601. for(int col=0;col<pDoc->ImgWidth;col++)
  602. {
  603.     if(g[row*width+col]<255)
  604. {
  605.                g[row*width+col]=0;
  606. }
  607. }
  608.  }
  609. int Area=0;                   //标识区域的地点
  610. if(g[0*width+10]==255)
  611. {
  612. Area++;
  613. H[Area]++;
  614.     Top[Area]=0;
  615. }
  616. for(row=1;row<height;row++)
  617. {
  618. if((g[row*width+10]==255) && (g[(row-1)*width+10]==0))
  619. {
  620. Area++;
  621.         H[Area]++;
  622.      Top[Area]=row;
  623. }
  624. else 
  625. {
  626. if(g[row*width+10]==255&&g[(row-1)*width+10]==255)
  627.     {
  628.      H[Area]++;
  629.     }     
  630. }
  631.  }  
  632. for(int x=0;x<20;x++)
  633. {
  634. int h=H[x];
  635. if(h>20)                                //特定应用条件,拍摄所得车牌的区域高度、宽度均有一定的范围
  636. {                                       //分析图象可得
  637.     int r=0;
  638. int r0=0;
  639. r=Top[x];
  640. r0=Top[x]+h;
  641. if(r!=0&&r0!=height)
  642. {
  643. for(int col=0;col<width;col++)
  644.     {
  645. pDoc->ImgData[r*width+col]=255;
  646. pDoc->ImgData[r0*width+col]=255;
  647. }
  648. }
  649. else
  650. {
  651. if(r==0)
  652. {
  653. r=5;
  654. for(int col=0;col<width;col++)
  655.         {
  656. pDoc->ImgData[r*width+col]=255;
  657. pDoc->ImgData[r0*width+col]=255;
  658. }
  659. }
  660. else
  661. {
  662. if(r0==height)
  663. {
  664. r0=height-10;
  665. for(int col=0;col<width;col++)
  666. {
  667. pDoc->ImgData[r*width+col]=255;
  668. pDoc->ImgData[r0*width+col]=255;
  669. }
  670. }
  671. }
  672. }
  673. }
  674. }
  675. free(g);
  676. IsNewBitmap=true;
  677. IsNewFile=true;
  678. pDoc->UpdateAllViews(NULL);
  679. }
  680. void CDipView::OnBanlance() 
  681. {
  682. // TODO: Add your command handler code here
  683. CDipDoc *pDoc=GetDocument();
  684.  int width,height;
  685.  width=pDoc->ImgWidth;
  686.  height=pDoc->ImgHeight;
  687.  float num=0;
  688.  int row,col;
  689.  int count[256];
  690.  float s0[256];
  691.  int s[256];                        //256个灰度等级
  692.  int x=0;
  693.  int temp=0;
  694.  for( x=0;x<256;x++)
  695.  {
  696.  count[x]=0;
  697.  s0[x]=0.0;
  698.  s[x]=0;
  699.  }
  700.  for(row=0;row<pDoc->ImgHeight;row++)                          //每个灰度等级象素个数
  701.  {
  702. for(col=0;col<pDoc->ImgWidth;col++)
  703. {
  704. temp=pDoc->ImgData[row*width+col];
  705. count[temp]++;
  706. }
  707.  }
  708.  for(x=0;x<256;x++)                                       //对应灰度等级概率
  709.  {
  710.  num=(float)width*height;
  711.  s0[x]=(float)(count[x]/num);
  712.  }
  713.  for( x=1;x<256;x++)                                      //概率累计,合并灰度等级    
  714.  {
  715.  s0[x]+=s0[x-1];  
  716.  }
  717.      for( x=0;x<256;x++)                                      //映射
  718.  {
  719.   s[x]=(int)(s0[x]*255+0.5);
  720.  }
  721.   for(row=0;row<pDoc->ImgHeight;row++)                          //每个灰度等级象素个数
  722.  {
  723. for(col=0;col<pDoc->ImgWidth;col++)
  724. {
  725. int reflect=0;
  726. temp=pDoc->ImgData[row*width+col];
  727. reflect=s[temp];
  728. pDoc->ImgData[row*width+col]=reflect;
  729. }
  730.  }
  731.  IsNewBitmap=true;
  732.  IsNewFile=true;
  733.  pDoc->UpdateAllViews(NULL); 
  734. }
  735. void CDipView::OnSubVertical() 
  736. {
  737. // TODO: Add your command handler code here
  738. CDipDoc *pDoc=GetDocument();
  739. int width,height;
  740. width=pDoc->ImgWidth;
  741. height=pDoc->ImgHeight;
  742.     BYTE *g=new BYTE[width*height];
  743. int row,col,sub;
  744. for(row=0;row<height-1;row++)
  745. {
  746. for(col=0;col<width;col++)
  747. {
  748. sub=abs((pDoc->ImgData[row*width+col])-(pDoc->ImgData[(row+1)*width+col]));
  749. g[row*width+col]=sub;
  750. }
  751. }
  752. for(row=0;row<height;row++)
  753. {
  754. for(col=0;col<width-1;col++)
  755. {
  756. pDoc->ImgData[row*width+col]=g[row*width+col];
  757. }
  758. }
  759.  
  760. free(g);
  761. IsNewBitmap=true;
  762. IsNewFile=true;
  763. pDoc->UpdateAllViews(NULL);
  764. }
  765. void CDipView::OnSubHorizontal() 
  766. {
  767. // TODO: Add your command handler code here
  768. CDipDoc *pDoc=GetDocument();
  769. int width,height;
  770. width=pDoc->ImgWidth;
  771. height=pDoc->ImgHeight;
  772.     BYTE *g=new BYTE[width*height];
  773. int row,col,sub;
  774. for(row=0;row<height;row++)
  775. {
  776. for(col=0;col<width-1;col++)
  777. {
  778. sub=abs((pDoc->ImgData[row*width+col])-(pDoc->ImgData[row*width+col+1]));
  779. if(sub<15)
  780. {
  781. g[row*width+col]=0;
  782. }
  783. else
  784. {
  785. if(sub>15)
  786. {
  787. g[row*width+col]=sub+50;
  788. }
  789. // else
  790. // g[row*width+col]=sub;
  791. }
  792. }
  793. }
  794. for(row=0;row<height;row++)
  795. {
  796. for(col=0;col<width-1;col++)
  797. {
  798. pDoc->ImgData[row*width+col]=g[row*width+col];
  799. if(col==0)
  800. {
  801. pDoc->ImgData[row*width+col]=0;
  802. }
  803. }
  804. }
  805.  
  806. free(g);
  807. IsNewBitmap=true;
  808. IsNewFile=true;
  809. pDoc->UpdateAllViews(NULL);
  810. }
  811. void CDipView::OnMidValue() 
  812. {
  813. // TODO: Add your command handler code here
  814. CDipDoc *pDoc=GetDocument();
  815. int width,height;
  816. width=pDoc->ImgWidth;
  817. height=pDoc->ImgHeight;
  818.     BYTE *g=new BYTE[width*height];
  819. BYTE temp[25];
  820. int row,col;
  821. int u,v,a;
  822. for(row=2;row<height-2;row++)
  823. {
  824. for(col=2;col<width-2;col++)
  825. {
  826. for(u=0;u<5;u++)
  827. {
  828. for(v=0;v<5;v++)
  829. {
  830. temp[u*5+v]=pDoc->ImgData[(row-2+u)*width+(col-2)+v];
  831. }
  832. }
  833. for(u=0;u<25;u++)
  834. {
  835. for(v=u+1;v<25;v++)
  836. {
  837. if(temp[u]>temp[v])
  838. {
  839. a=temp[u];
  840. temp[u]=temp[v];
  841. temp[v]=a;
  842. }
  843. }
  844. }
  845. g[row*width+col]=temp[12];
  846. }
  847. }
  848. for(row=0;row<height;row++)
  849. {
  850. for(col=0;col<width-1;col++)
  851. {
  852. pDoc->ImgData[row*width+col]=g[row*width+col];
  853. }
  854. }
  855. IsNewBitmap=true;
  856. IsNewFile=true;
  857. pDoc->UpdateAllViews(NULL);
  858. }
  859. void CDipView::OnAverage() 
  860. {
  861. // TODO: Add your command handler code here
  862. CDipDoc *pDoc=GetDocument();
  863.  int width,height;
  864.  width=pDoc->ImgWidth;
  865.  height=pDoc->ImgHeight;
  866.  BYTE *g=new BYTE[width*height];
  867.  int row,col;
  868.  BYTE s[3][3]={{1,1,1},{1,1,1},{1,1,1}};
  869.  for(row=1;row<pDoc->ImgHeight-1;row++)
  870.  {
  871. for(col=1;col<pDoc->ImgWidth-1;col++)
  872. {
  873. long sum=0;
  874. for(int i=0;i<3;i++)
  875. {
  876. for(int j=0;j<3;j++)
  877. {
  878. sum+=s[i][j]*pDoc->ImgData[((row-1+i)*pDoc->ImgWidth)+(col-1+j)];
  879. }
  880. }
  881. g[(row*pDoc->ImgWidth)+col]=(BYTE)(sum/9);
  882. }
  883.  }
  884.  for(row=0;row<height;row++)
  885.  {
  886. for(col=0;col<width;col++)
  887. {
  888. pDoc->ImgData[row*width+col]=g[row*width+col];
  889. }
  890.      }
  891.  IsNewBitmap=true;
  892.  IsNewFile=true;
  893.  pDoc->UpdateAllViews(NULL); 
  894. }
  895. void CDipView::OnBool() 
  896. {
  897. // TODO: Add your command handler code here
  898.  CDipDoc *pDoc=GetDocument();
  899.  int width,height;
  900.  width=pDoc->ImgWidth;
  901.  height=pDoc->ImgHeight;
  902.  int row,col;
  903.  for(row=0;row<pDoc->ImgHeight;row++)
  904.  {
  905. for(col=0;col<pDoc->ImgWidth;col++)
  906. {
  907.     if(pDoc->ImgData[row*width+col]<255)
  908. {
  909.                pDoc->ImgData[row*width+col]=0;
  910. }
  911. }
  912.  }
  913.  
  914.  IsNewBitmap=true;
  915.  IsNewFile=true;
  916.  pDoc->UpdateAllViews(NULL); 
  917. }
  918. void CDipView::OnVSearch()
  919. {
  920. // TODO: 在此添加命令处理程序代码
  921. CDipDoc *pDoc=GetDocument();
  922. int width,height;
  923. width=pDoc->ImgWidth;
  924. height=pDoc->ImgHeight;
  925. BYTE *g=new BYTE[width*height];
  926.     int *Count= new int[width];
  927. int *TempCount=new int[width];
  928. int *maxChanges=new int[30];
  929. int *Cols=new int[30];                  //maxChanges' col                       
  930. int *W=new int[30];                     //Top' width
  931. int *left=new int[30];                   //Top' top col
  932.  
  933. for(int row=0;row<pDoc->ImgHeight;row++)
  934.  {
  935. for(int col=0;col<pDoc->ImgWidth;col++)
  936. {
  937.    g[row*width+col]=pDoc->ImgData[row*width+col];
  938. }
  939.  }
  940.  
  941. for(int c=0;c<width;c++)
  942. {
  943. Count[c]=0;
  944. TempCount[c]=0;
  945. }
  946. for(c=0;c<30;c++)
  947. {
  948.         maxChanges[c]=0;
  949.     Cols[c]=0; 
  950. W[c]=0;
  951. left[c]=-1;
  952. }
  953.     for(int col=0;col<width;col++)
  954. {
  955. for(int row=0;row<height-1;row++)
  956. {
  957. if(pDoc->ImgData[row*width+col]!=pDoc->ImgData[(row+1)*width+col])
  958. Count[col]++;
  959. }
  960. TempCount[col]=Count[col];
  961. }
  962. /////////////////////////////////////Top 30 change col
  963. for(int top=0;top<30;top++)
  964. {
  965. int Max=0;
  966. for(int col=0;col<width;)
  967. {
  968. if(Max<TempCount[col])
  969. {
  970. Max=TempCount[col];
  971. }
  972. col=col+10 ;
  973. }
  974. maxChanges[top]=Max;
  975. int C=0;
  976.      for(col=0;col<width;)
  977. {
  978.      if(Max!=TempCount[col])
  979. {
  980.      col=col+10;
  981. }
  982. else
  983. {
  984. C=col;
  985. break;
  986. }
  987. }
  988. Cols[top]=C;
  989. TempCount[C]=0;
  990. }
  991. for(top=0;top<30;top++)
  992. {
  993. for(int range=-20;range<20;range++)
  994. {
  995. if((Cols[top]+range)>=0&&(Cols[top]+range)<width)
  996. {
  997. if((0.8*Count[Cols[top]]<=Count[Cols[top]+range])&&(Count[Cols[top]+range]<=1.2*Count[Cols[top]]))
  998. {
  999. for(int row=0;row<height;row++)
  1000. {
  1001.          g[row*width+(Cols[top]+range)]=255;
  1002. }
  1003. }
  1004. }
  1005. else
  1006. {
  1007. continue;
  1008. }
  1009. }
  1010. }
  1011.  for(row=0;row<height;row++)
  1012.  {
  1013. for(int col=0;col<width;col++)
  1014. {
  1015.     if(g[row*width+col]<255)
  1016. {
  1017.                g[row*width+col]=0;
  1018. }
  1019. }
  1020.  }
  1021. int Area=-1;                   //标识区域的地点
  1022. if(g[10*width+0]==255)
  1023. {
  1024. Area++;
  1025. W[Area]++;
  1026.     left[Area]=0;
  1027. }
  1028. for(col=1;col<width;col++)
  1029. {
  1030. if(g[10*width+col]==255 && g[10*width+(col-1)]==0)
  1031. {
  1032. Area++;
  1033. W[Area]++;
  1034.      left[Area]=col;
  1035. }
  1036. else 
  1037. {
  1038. if((g[10*width+col]==255)&&(g[10*width+col-1]==255))
  1039. {
  1040.      W[Area]++;
  1041. }     
  1042. }
  1043.  }
  1044. for(int x=0;x<30;x++)
  1045. {
  1046. int w=W[x];
  1047. if(w>10)
  1048. {
  1049.     int c=0;
  1050. int c0=0;
  1051. c=left[x];
  1052. c0=left[x]+w;
  1053. if(c!=0&&c0!=width)
  1054. {
  1055. for(int row=0;row<height;row++)
  1056. {
  1057. pDoc->ImgData[row*width+c]=255;
  1058. pDoc->ImgData[row*width+c0]=255;
  1059. }
  1060. }
  1061. else
  1062. {
  1063. if(c==0)
  1064. {
  1065. c=10;
  1066. for(int row=0;row<height;row++)
  1067. {
  1068. pDoc->ImgData[row*width+c]=255;
  1069. pDoc->ImgData[row*width+c0]=255;
  1070. }
  1071. }
  1072. else
  1073. {
  1074. if(c0==width)
  1075. {
  1076. c0=width-10;
  1077. for(int row=0;row<height;row++)
  1078.     {
  1079. pDoc->ImgData[row*width+c]=255;
  1080. pDoc->ImgData[row*width+c0]=255;
  1081. }
  1082. }
  1083. }
  1084. }
  1085. }
  1086. }
  1087. free(g);
  1088. IsNewBitmap=true;
  1089. IsNewFile=true;
  1090. pDoc->UpdateAllViews(NULL);
  1091. }
  1092. /// <summary>
  1093. /// CDipView::OnLocate()的摘要说明。
  1094. /// 创建人  :刘陈炜
  1095. /// 创建时间:2004.5.1
  1096. /// 函数功能:完成车牌定位的整个过程
  1097. /// 程序流程:1.产生副本
  1098. ///           2.水平差分提取边缘,寻找横向的车牌带状区域
  1099. ///           3.垂直差分提取边缘,寻找纵向的车牌带状区域
  1100. ///           4.利用先验知识标识车牌区域,进行车牌带状区域的选择,(横纵向)
  1101. ///           5.构造出车牌矩形域;
  1102. ///           6.再次利用利用跳变数选择车牌矩形区域,进行车牌区域的最终选择;
  1103. ///           7.精确定位车牌,即削弱车牌横向宽度;
  1104. ///           8.更新图象;
  1105. /// </summary> 
  1106. void CDipView::OnLocate()
  1107. {
  1108. // TODO: 在此添加命令处理程序代码
  1109. CDipDoc *pDoc=GetDocument();
  1110. int width,height;
  1111. width=pDoc->ImgWidth;
  1112. height=pDoc->ImgHeight;
  1113. BYTE *g=new BYTE[width*height];
  1114. CopyImg(pDoc,g,width,height);
  1115. //Banlance(g,width,height);
  1116. HSub(g,width,height);
  1117.     Search(g,width,height);
  1118. CopyImg(pDoc,g,width,height);
  1119. VSub(g,width,height);
  1120. VSearch(g,width,height);
  1121. Mark(pDoc,width,height);
  1122.     VMark(pDoc,width,height);
  1123. DrawRect(pDoc,width,height);
  1124. Choose(pDoc,width,height);
  1125. FurtherLocate(pDoc,width,height);
  1126. free(g);
  1127. IsNewBitmap=true;
  1128. IsNewFile=true;
  1129. pDoc->UpdateAllViews(NULL);    
  1130. }
  1131. // 均衡化图象
  1132. void CDipView::Banlance(BYTE* DisposeImg,int Width,int Height)
  1133. {
  1134.     float num=0;
  1135. int row,col;
  1136. int count[256];
  1137. float s0[256];
  1138. int s[256];                        //256个灰度等级
  1139. int x=0;
  1140. int temp=0;
  1141. for( x=0;x<256;x++)
  1142. {
  1143. count[x]=0;
  1144. s0[x]=0.0;
  1145. s[x]=0;
  1146. }
  1147. for(row=0;row<Height;row++)                          //每个灰度等级象素个数
  1148. {
  1149. for(col=0;col<Width;col++)
  1150. {
  1151. temp=DisposeImg[row*Width+col];
  1152. count[temp]++;
  1153. }
  1154. }
  1155. for(x=0;x<256;x++)                                       //对应灰度等级概率
  1156. {
  1157. num=(float)Width*Height;
  1158. s0[x]=(float)(count[x]/num);
  1159. }
  1160. for( x=1;x<256;x++)                                      //概率累计,合并灰度等级    
  1161. {
  1162. s0[x]+=s0[x-1];  
  1163. }
  1164.     for( x=0;x<256;x++)                                      //映射
  1165. {
  1166.  s[x]=(int)(s0[x]*255+0.5);
  1167. }
  1168. for(row=0;row<Height;row++)                          //每个灰度等级象素个数
  1169. {
  1170. for(col=0;col<Width;col++)
  1171. {
  1172. int reflect=0;
  1173. temp=DisposeImg[row*Width+col];
  1174. reflect=s[temp];
  1175. DisposeImg[row*Width+col]=reflect;
  1176. }
  1177. }
  1178. }
  1179. // 图象复制
  1180. void CDipView::CopyImg(CDipDoc * SourceImg, BYTE* DestImg, int Width, int Height)
  1181. {
  1182. for(int row=0;row<Height;row++)
  1183. {
  1184. for(int col=0;col<Width;col++)
  1185. {
  1186. DestImg[row*Width+col]=SourceImg->ImgData[row*Width+col];
  1187. }
  1188. }
  1189. }
  1190. // 图象复制
  1191. void CDipView::CopyImg(BYTE* SourceImg, BYTE* DestImg, int Width , int Height)
  1192. {
  1193.     for(int row=0;row<Height;row++)
  1194. {
  1195. for(int col=0;col<Width;col++)
  1196. {
  1197. DestImg[row*Width+col]=SourceImg[row*Width+col];
  1198. }
  1199. }
  1200. }
  1201. /// <summary>
  1202. /// CDipView::HSub(BYTE* DisposeImg, int Width , int Height)的摘要说明。
  1203. /// 创建人  :刘陈炜
  1204. /// 创建时间:2004.5.1
  1205. /// 函数功能:水平差分提取图象边缘。
  1206. /// 程序流程:1.逐行扫描,sub=|f(x,y)-f(x,y+1)|;
  1207. ///           2.若差值小于20,则g(x,y)=0;
  1208. ///             若差值大于30,则增强原图象,令g(x,y)=g(x,y)+30;
  1209. ///           3.另最后一列全部为0,即黑色;
  1210. /// </summary> 
  1211. // 水平差分
  1212. void CDipView::HSub(BYTE* DisposeImg, int Width , int Height)
  1213. {
  1214. int row,col,sub;
  1215. for(row=0;row<Height;row++)
  1216. {
  1217. for(col=0;col<Width-1;col++)
  1218. {
  1219. sub=abs((DisposeImg[row*Width+col])-(DisposeImg[row*Width+col+1]));
  1220. if(sub<20)
  1221. {
  1222. DisposeImg[row*Width+col]=0;
  1223. }
  1224. else
  1225. {
  1226. if(sub>30)
  1227. {
  1228.                  DisposeImg[row*Width+col]=sub+30;
  1229. }
  1230. else
  1231. DisposeImg[row*Width+col]=sub;
  1232. }
  1233. }
  1234. }
  1235. for(row=0;row<Height;row++)
  1236. {
  1237. DisposeImg[row*Width+Width-1]=0;
  1238. }  
  1239. }
  1240. // 纵向差分
  1241. void CDipView::VSub(BYTE* DisposeImg, int Width , int Height)
  1242. {
  1243. int row,col,sub;
  1244. for(row=0;row<Height-1;row++)
  1245. {
  1246. for(col=0;col<Width;col++)
  1247. {
  1248. sub=abs((DisposeImg[row*Width+col])-(DisposeImg[(row+1)*Width+col]));
  1249. /* if(sub<5)
  1250. {
  1251. DisposeImg[row*Width+col]=0;
  1252. }
  1253. else
  1254. {
  1255. if(sub>10)
  1256. {
  1257.                  DisposeImg[row*Width+col]=sub+30;
  1258. }
  1259. else
  1260. DisposeImg[row*Width+col]=sub;
  1261. }*/
  1262. DisposeImg[row*Width+col]=sub;
  1263. }
  1264. }
  1265. for(col=0;col<Width-1;col++)
  1266. {
  1267. DisposeImg[(Height-1)*Width+col]=0;
  1268. }
  1269. }
  1270. /// <summary>
  1271. /// CDipView::Search(BYTE* DisposeImg, int width , int height)的摘要说明。
  1272. /// 创建人  :刘陈炜
  1273. /// 创建时间:2004.5.1
  1274. /// 函数功能:完成图象车牌区域的初步定位。即寻找出差分扫描后水平跳变数最大的前10个区域。
  1275. /// 程序流程:1.利用间行扫描的方式找出跳变数最大的前10行;
  1276. ///           2.对 Top 10 行进行区域细粒度增长选择;
  1277. ///             其相似度的选取为:0.7~1.3 倍的该行跳变总数;
  1278. ///           3.二值化,threshold=255;
  1279. ///           4.任意选择一列,最好不要边缘列,可能有干扰(本程序选择为第十列),搜索出各个带状候选域,存入标志;
  1280. /// </summary> 
  1281. void CDipView::Search(BYTE* DisposeImg, int width , int height)
  1282. {
  1283. BYTE*TempImg=new BYTE[width*height];
  1284.     int *Count= new int[height];
  1285. int *TempCount=new int[height];
  1286. int *maxChanges=new int[10];
  1287. int *Rows=new int[10]; 
  1288. CopyImg(DisposeImg,TempImg,width,height);
  1289. for(int c=0;c<height;c++)
  1290. {
  1291. Count[c]=0;
  1292. TempCount[c]=0;
  1293. }
  1294. for(c=0;c<10;c++)
  1295. {
  1296.         maxChanges[c]=0;
  1297.     Rows[c]=0; 
  1298. Height[c]=0;
  1299. TopRow[c]=-1;
  1300. }
  1301.     for(int row=0;row<height;row++)
  1302. {
  1303. for(int col=0;col<width-1;col++)
  1304. {
  1305. if(DisposeImg[row*width+col]!=DisposeImg[row*width+col+1])
  1306. Count[row]++;
  1307. }
  1308. TempCount[row]=Count[row];
  1309. }
  1310. /////////////////////////////////////Top 10 chage row
  1311. for(int top=0;top<10;top++)
  1312. {
  1313. int Max=0;
  1314. for(row=0;row<height;)
  1315. {
  1316. if(Max<TempCount[row])
  1317. {
  1318. Max=TempCount[row];
  1319. }
  1320. row=row+10 ;
  1321. }
  1322. maxChanges[top]=Max;
  1323. int R=0;
  1324.      for(row=0;row<height;)
  1325. {
  1326.      if(Max!=TempCount[row])
  1327. {
  1328.      row=row+10;
  1329. }
  1330. else
  1331. {
  1332. R=row;
  1333. break;
  1334. }
  1335. }
  1336. Rows[top]=R;
  1337. TempCount[R]=0;
  1338. }
  1339. for(top=0;top<10;top++)
  1340. {
  1341. for(int range=-10;range<10;range++)
  1342. {
  1343. if((0.7*Count[Rows[top]]<=Count[Rows[top]+range])&&(Count[Rows[top]+range]<=1.3*Count[Rows[top]]))
  1344. {
  1345.  for(int col=0;col<width;col++)
  1346.  {
  1347.          DisposeImg[(Rows[top]+range)*width+col]=255;
  1348.  }
  1349. }
  1350. }
  1351. }
  1352.  for(row=0;row<height;row++)
  1353.  {
  1354. for(int col=0;col<width;col++)
  1355. {
  1356.     if(DisposeImg[row*width+col]<255)
  1357. {
  1358.                DisposeImg[row*width+col]=0;
  1359. }
  1360. }
  1361.  }
  1362. int Area=0;                   //标识区域的地点
  1363. if(DisposeImg[0*width+10]==255)
  1364. {
  1365. Area++;
  1366. Height[Area]++;
  1367.     TopRow[Area]=0;
  1368. }
  1369. for(row=1;row<height;row++)
  1370. {
  1371. if((DisposeImg[row*width+10]==255) && (DisposeImg[(row-1)*width+10]==0))
  1372. {
  1373. Area++;
  1374.         Height[Area]++;
  1375.      TopRow[Area]=row;
  1376. }
  1377. else 
  1378. {
  1379. if(DisposeImg[row*width+10]==255&&DisposeImg[(row-1)*width+10]==255)
  1380.     {
  1381.      Height[Area]++;
  1382.     }     
  1383. }
  1384. }
  1385. // Mark(TempImg,width,height);
  1386. // CopyImg(TempImg,DisposeImg,width,height);
  1387. free(TempImg);
  1388.     free(Count);
  1389. free(TempCount);
  1390. free(maxChanges);
  1391. free(Rows); 
  1392. }
  1393. /// <summary>
  1394. /// CDipView::Mark(CDipDoc * DisposeImg, int width , int height)的摘要说明。
  1395. /// 创建人  :刘陈炜
  1396. /// 创建时间:2004.5.1
  1397. /// 函数功能:利用先验知识标识车牌区域,进行车牌区域的选择,(横向)
  1398. /// 函数说明:特定应用条件,拍摄所得车牌的区域高度、宽度均有一定的范围,其大小可以分析图象后可得
  1399. ///           根据统计得到:车牌的顶部极少出现在高度小于100个像素的区域;
  1400. ///                         车牌高度也一般大于20个像素。
  1401. ///           程序的最终结果为满足条件的经过扩展了的带状区域
  1402. /// 程序流程:1.舍弃区域顶部小于100的待选域
  1403. ///           2.选择区域高度大于20的待选域
  1404. ///           3.区域扩展,上下各增大5个像素。若顶部小于5,则顶部坐标不变,高度加5;
  1405. ///                                          若底部大于图象的底部,则底部坐标不变,高度加5;
  1406. /// </summary> 
  1407. void CDipView::Mark(CDipDoc * DisposeImg, int width , int height)
  1408. {
  1409. for(int x=0;x<20;x++)
  1410. {
  1411. int h=Height[x];
  1412. if(TopRow[x]<=5)
  1413. {
  1414. Height[x]=0;
  1415. TopRow[x]=-1;
  1416. }
  1417. }
  1418.  for(x=0;x<20;x++)
  1419. {
  1420. int h=Height[x];
  1421. if(h>20)                                
  1422. {                                       
  1423.     int r=0;
  1424. int r0=0;
  1425. r=TopRow[x]-5;
  1426. r0=TopRow[x]+h+5;
  1427. if((r>0)&&(r0<height))
  1428. {
  1429. // for(int col=0;col<width;col++)
  1430. //     {
  1431. // DisposeImg->ImgData[r*width+col]=255;
  1432. // DisposeImg->ImgData[r0*width+col]=255;
  1433. // }
  1434. TopRow[x]=r+5;
  1435. Height[x]=h;
  1436. }
  1437. else
  1438. {
  1439. if(r<=0)
  1440. {
  1441. r=r+5;
  1442. //for(int col=0;col<width;col++)
  1443.   //      {
  1444. // DisposeImg->ImgData[r*width+col]=255;
  1445. // DisposeImg->ImgData[r0*width+col]=255;
  1446. //}
  1447. TopRow[x]=r;
  1448. Height[x]=h;
  1449. }
  1450. else
  1451. {
  1452. if(r0>=height)
  1453. {
  1454. r0=r0-5;
  1455. //for(int col=0;col<width;col++)
  1456. //{
  1457. // DisposeImg->ImgData[r*width+col]=255;
  1458. // DisposeImg->ImgData[r0*width+col]=255;
  1459. //}
  1460. Height[x]=Height[x]-5;
  1461. }
  1462. }
  1463. }
  1464. }
  1465. }
  1466. for(x=0;x<20;x++)
  1467. {
  1468. int h=Height[x];
  1469. if(h<20||TopRow[x]<=100)
  1470. {
  1471. Height[x]=0;
  1472. TopRow[x]=-1;
  1473. }
  1474. }
  1475. }
  1476. /// <summary>
  1477. /// CDipView::VSearch(BYTE* DisposeImg, int width , int height)的摘要说明。
  1478. /// 创建人  :刘陈炜
  1479. /// 创建时间:2004.5.1
  1480. /// 函数功能:水平查找后,纵向查找。完成图象车牌区域的初步定位。即寻找出差分扫描后垂直跳变数最大的前30个区域。
  1481. /// 程序流程:1.利用间行扫描的方式找出跳变数最大的前30行;
  1482. ///           2.对 Top 30 行进行区域增长;
  1483. ///             其相似度的选取为:0.8~1.2 倍的该行跳变总数;
  1484. ///           3.二值化,threshold=255;
  1485. ///           4.任意选择一列,(本程序选择为第十行),搜索出各个带状候选域,存入标志;
  1486. /// </summary> 
  1487. //
  1488. void CDipView::VSearch(BYTE* DisposeImg, int width, int height)
  1489. {
  1490. BYTE *g=new BYTE[width*height];
  1491.     int *Count= new int[width];
  1492. int *TempCount=new int[width];
  1493. int *maxChanges=new int[30];
  1494. int *Cols=new int[30];                  //maxChanges' col  
  1495. CopyImg(DisposeImg,g,width,height);
  1496.  
  1497. for(int c=0;c<width;c++)
  1498. {
  1499. Count[c]=0;
  1500. TempCount[c]=0;
  1501. }
  1502. for(c=0;c<30;c++)
  1503. {
  1504.         maxChanges[c]=0;
  1505.     Cols[c]=0; 
  1506. Widths[c]=0;
  1507. Left[c]=-1;
  1508. }
  1509.     for(int col=0;col<width;col++)
  1510. {
  1511. for(int row=0;row<height-1;row++)
  1512. {
  1513. if(DisposeImg[row*width+col]!=DisposeImg[(row+1)*width+col])
  1514. Count[col]++;
  1515. }
  1516. TempCount[col]=Count[col];
  1517. }
  1518. /////////////////////////////////////Top 30 change col
  1519. for(int top=0;top<30;top++)
  1520. {
  1521. int Max=0;
  1522. for(int col=0;col<width;)
  1523. {
  1524. if(Max<TempCount[col])
  1525. {
  1526. Max=TempCount[col];
  1527. }
  1528. col=col+10 ;
  1529. }
  1530. maxChanges[top]=Max;
  1531. int C=0;
  1532.      for(col=0;col<width;)
  1533. {
  1534.      if(Max!=TempCount[col])
  1535. {
  1536.      col=col+10;
  1537. }
  1538. else
  1539. {
  1540. C=col;
  1541. break;
  1542. }
  1543. }
  1544. Cols[top]=C;
  1545. TempCount[C]=0;
  1546. }
  1547. for(top=0;top<30;top++)
  1548. {
  1549. for(int range=-20;range<20;range++)
  1550. {
  1551. if((Cols[top]+range)>=0&&(Cols[top]+range)<width)
  1552. {
  1553. if((0.8*Count[Cols[top]]<=Count[Cols[top]+range])&&(Count[Cols[top]+range]<=1.2*Count[Cols[top]]))
  1554. {
  1555. for(int row=0;row<height;row++)
  1556. {
  1557.          DisposeImg[row*width+(Cols[top]+range)]=255;
  1558. }
  1559. }
  1560. }
  1561. else
  1562. {
  1563. continue;
  1564. }
  1565. }
  1566. }
  1567.  for(int row=0;row<height;row++)
  1568.  {
  1569. for(int col=0;col<width;col++)
  1570. {
  1571.     if(DisposeImg[row*width+col]<255)
  1572. {
  1573.                DisposeImg[row*width+col]=0;
  1574. }
  1575. }
  1576.  }
  1577. int Area=-1;                   //标识区域的地点
  1578. if(DisposeImg[10*width+0]==255)
  1579. {
  1580. Area++;
  1581. Widths[Area]++;
  1582.     Left[Area]=0;
  1583. }
  1584. for(col=1;col<width;col++)
  1585. {
  1586. if(DisposeImg[10*width+col]==255 && DisposeImg[10*width+(col-1)]==0)
  1587. {
  1588. Area++;
  1589. Widths[Area]++;
  1590.      Left[Area]=col;
  1591. }
  1592. else 
  1593. {
  1594. if((DisposeImg[10*width+col]==255)&&(DisposeImg[10*width+col-1]==255))
  1595. {
  1596.      Widths[Area]++;
  1597. }     
  1598. }
  1599.  }
  1600. }
  1601. // 纵向定位
  1602. void CDipView::VMark(CDipDoc* DisposeImg, int width, int height)
  1603. {
  1604. for(int x=0;x<30;x++)
  1605. {
  1606. int w=Widths[x];
  1607. if(w>100)
  1608. {
  1609.     int c=0;
  1610. int c0=0;
  1611. c=Left[x];
  1612. c0=Left[x]+w-10;
  1613. if(c!=0&&c0>0)
  1614. {
  1615. //for(int row=0;row<height;row++)
  1616. //{
  1617. // DisposeImg->ImgData[row*width+c]=255;
  1618. // DisposeImg->ImgData[row*width+c0]=255;
  1619. //}
  1620. Widths[x]=Widths[x]-10;
  1621. }
  1622. else
  1623. {
  1624. if(c<=0)
  1625. {
  1626. c=5;
  1627. //for(int row=0;row<height;row++)
  1628. //{
  1629. // DisposeImg->ImgData[row*width+c]=255;
  1630. // DisposeImg->ImgData[row*width+c0]=255;
  1631. //}
  1632. Left[x]=c;
  1633. }
  1634. else
  1635. {
  1636. if(c0<=0)
  1637. {
  1638. c0=c0+10;
  1639. //for(int row=0;row<height;row++)
  1640.  //   {
  1641. // DisposeImg->ImgData[row*width+c]=255;
  1642. // DisposeImg->ImgData[row*width+c0]=255;
  1643. //}
  1644. //Widths[x]=Widths[x]-5;
  1645. }
  1646. }
  1647. }
  1648. }
  1649. }
  1650. for(x=0;x<30;x++)
  1651. {
  1652. int w=Widths[x];
  1653. if(w<100)
  1654. {
  1655. Widths[x]=0;
  1656. Left[x]=-1;
  1657. }
  1658. }
  1659. }
  1660. /// <summary>
  1661. /// CDipView::DrawRect(CDipDoc* DisposeImg, int width, int height)的摘要说明。
  1662. /// 创建人  :刘陈炜
  1663. /// 创建时间:2004.5.1
  1664. /// 函数功能:利用先验知识标识车牌区域,进行车牌区域的选择,(横纵向)
  1665. /// 函数说明:国家标准:车牌的宽高比近似为3:1;
  1666. /// 程序流程:1.初始化存储数组
  1667. ///           2.选择区域高宽比大于3的待选域
  1668. /// </summary> 
  1669. void CDipView::DrawRect(CDipDoc* DisposeImg, int width, int height)
  1670. {
  1671. for(int x=0;x<50;x++)
  1672. {
  1673. Rect_X[x]=-1;
  1674. Rect_Y[x]=-1;
  1675. Rect_W[x]=0;
  1676. Rect_H[x]=0;
  1677. }
  1678. Rect_Areas=0;
  1679. for(int m=0;m<20;m++)
  1680. {
  1681. for(int n=0;n<30;n++)
  1682. {
  1683. if((Widths[n]>3*Height[m])&&(Widths[n]*Height[m]!=0))
  1684. {
  1685. Rect_Areas++;
  1686. Rect_X[Rect_Areas-1]=Left[n];
  1687. Rect_Y[Rect_Areas-1]=TopRow[m];
  1688. Rect_W[Rect_Areas-1]=Widths[n];
  1689. Rect_H[Rect_Areas-1]=Height[m];
  1690. }
  1691. }
  1692. }
  1693. //for( x=0;x<Rect_Areas;x++)
  1694. //{
  1695. // for(int row=Rect_Y[x];row<(Rect_Y[x]+Rect_H[x]);row++)
  1696. // {
  1697. // DisposeImg->ImgData[row*width+Rect_X[x]]=255;
  1698. // DisposeImg->ImgData[row*width+Rect_X[x]+Rect_W[x]]=255;
  1699. // }
  1700. //}
  1701. //for( x=0;x<Rect_Areas;x++)
  1702. //{
  1703. // for(int col=Rect_X[x];col<(Rect_X[x]+Rect_W[x]);col++)
  1704. // {
  1705. // DisposeImg->ImgData[Rect_Y[x]*width+col]=255;
  1706. // DisposeImg->ImgData[(Rect_Y[x]+Rect_H[x])*width+col]=255;
  1707. // }
  1708. //}
  1709. }
  1710. void CDipView::OnChoose() 
  1711. {
  1712. // TODO: Add your command handler code here
  1713. }
  1714. /// <summary>
  1715. /// CDipView::Choose(CDipDoc *DisposeImg, int width, int height)的摘要说明。
  1716. /// 创建人  :刘陈炜
  1717. /// 创建时间:2004.5.1
  1718. /// 函数功能:再次利用利用跳变数选择车牌区域,进行车牌区域的最终选择,(横纵向)
  1719. /// 程序流程:1.初始化存储数组
  1720. ///           2.计算每个伪车牌区域的跳变数
  1721. ///           3.选择具有最大跳变数的区域为车牌区
  1722. /// </summary> 
  1723. void CDipView::Choose(CDipDoc *DisposeImg, int width, int height)
  1724. {
  1725. int row=0;
  1726. int col=0;
  1727. int temp=0;
  1728. int *JumpNums=new int[Rect_Areas];
  1729. for(int area=0;area<Rect_Areas;area++)
  1730. {
  1731. JumpNums[area]=0;
  1732. }
  1733. for(area=0;area<Rect_Areas;area++)    //计算每个伪车牌区域的行跳变数
  1734. {
  1735. BYTE* TempImg=new BYTE[Rect_W[area]*Rect_H[area]];
  1736. for(row=0;row<Rect_H[area];row++)
  1737. {
  1738. for(col=0;col<Rect_W[area];col++)
  1739. {
  1740. TempImg[row*Rect_W[area]+col]=DisposeImg->ImgData[(Rect_Y[area]+row)*width+(Rect_X[area]+col)];
  1741. }
  1742. }
  1743. JumpNums[area]=JumpNum(TempImg,Rect_W[area],Rect_H[area]);
  1744. free(TempImg);
  1745. }
  1746. temp=MaxJump(JumpNums,Rect_Areas);
  1747. // 区域刻画
  1748. /* for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++)
  1749. {
  1750. DisposeImg->ImgData[row*width+Rect_X[temp]]=255;
  1751. DisposeImg->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;
  1752. }
  1753.     for(col=Rect_X[temp];col<(Rect_X[temp]+Rect_W[temp]);col++)
  1754. {
  1755. DisposeImg->ImgData[Rect_Y[temp]*width+col]=255;
  1756.      DisposeImg->ImgData[(Rect_Y[temp]+Rect_H[temp])*width+col]=255;
  1757. } */
  1758. //剔除伪车牌区
  1759. for(area=0;area<Rect_Areas;area++)    
  1760. {
  1761. if(area!=temp)
  1762. {
  1763. Rect_X[area]=-1;
  1764. Rect_Y[area]=-1;
  1765. Rect_W[area]=0;
  1766. Rect_H[area]=0;
  1767. }
  1768. }
  1769. //移至第一位
  1770. Rect_X[0]=Rect_X[temp];
  1771. Rect_Y[0]=Rect_Y[temp];
  1772. Rect_W[0]=Rect_W[temp];
  1773. Rect_H[0]=Rect_H[temp];
  1774. //清空
  1775. if(temp!=0)
  1776. {
  1777. Rect_X[temp]=-1;
  1778. Rect_Y[temp]=-1;
  1779. Rect_W[temp]=0;
  1780. Rect_H[temp]=0;
  1781. }
  1782. Rect_Areas=1;
  1783. }
  1784. /// <summary>
  1785. /// CDipView::JumpNum(BYTE *DisposeImg,int width,int height)的摘要说明。
  1786. /// 创建人  :刘陈炜
  1787. /// 创建时间:2004.5.1
  1788. /// 函数功能:计算伪车牌区的跳变平均数
  1789. /// 程序流程:1.初始化;
  1790. ///           2.水平差分,边缘提取;
  1791. ///           3.选择车牌的中间1/3行来计算每个伪车牌区域的跳变平均数;
  1792. /// </summary>
  1793. /// <return>各个区域的平均跳变数</return>
  1794. int CDipView::JumpNum(BYTE *DisposeImg,int width,int height)
  1795. {
  1796. int startRow=0;
  1797. int endRow=0;
  1798. long JumpNum=0;
  1799. int averJump=0;
  1800. int r=0;
  1801. BYTE* g=new BYTE[width*height];
  1802.     CopyImg(DisposeImg,g,width,height);
  1803. HSub(g,width,height);
  1804. startRow=(int)(0+height/3);
  1805. endRow=(int)(0+2*height/3);
  1806. for(int row=startRow;row<endRow;row++)
  1807. {
  1808. for(int col=0;col<width-1;col++)
  1809. {
  1810. if(g[row*width+col]!=g[row*width+col+1])
  1811. JumpNum++;
  1812. }
  1813. }
  1814. r=endRow-startRow;
  1815. averJump=(int)(JumpNum/r);
  1816. free(g);
  1817. return averJump;
  1818. }
  1819. /// <summary>
  1820. /// CDipView::MaxJump(int *JumpNums,int num)的摘要说明。
  1821. /// 创建人  :刘陈炜
  1822. /// 创建时间:2004.5.1
  1823. /// 函数功能:找出所有伪车牌区域中具有最大跳变平均数的区域号
  1824. /// 程序说明:选择排序
  1825. /// </summary>
  1826. /// <return>最大跳变平均数的区域号</return>
  1827. int CDipView::MaxJump(int *JumpNums,int num)
  1828. {
  1829. int area=0;
  1830. int temp=0;
  1831. int val=0;
  1832. val=JumpNums[0];
  1833. for(area=0;area<num;area++)
  1834. {
  1835. if(JumpNums[area]>val)
  1836. {
  1837. temp=area;
  1838. val=JumpNums[area];
  1839. }
  1840. }
  1841. return temp;
  1842. }
  1843. /// <summary>
  1844. /// CDipView::FurtherLocate(CDipDoc *DisposeImg,int width,int height)的摘要说明。
  1845. /// 创建人  :刘陈炜
  1846. /// 创建时间:2004.5.1
  1847. /// 函数功能:精确定位车牌
  1848. /// 程序流程:
  1849. /// 程序说明:由于水平分割出的伪车牌区域已经比较准确,故仅作垂直方向的进一步定位(缩小宽度)
  1850. /// </summary>
  1851. void CDipView::FurtherLocate(CDipDoc *DisposeImg,int width,int height)
  1852. {
  1853. int row=0;
  1854. int col=0;
  1855. //copy 到一个暂存数组,以便处理操作且不破坏原图象
  1856. BYTE* TempImg=new BYTE[Rect_W[0]*Rect_H[0]];
  1857. for(row=0;row<Rect_H[0];row++)
  1858. {
  1859. for(col=0;col<Rect_W[0];col++)
  1860. {
  1861. TempImg[row*Rect_W[0]+col]=DisposeImg->ImgData[(Rect_Y[0]+row)*width+(Rect_X[0]+col)];
  1862. }
  1863. }
  1864. VFurthLocate(TempImg,Rect_W[0],Rect_H[0]);
  1865. /* int temp=0;
  1866. // 区域刻画
  1867. for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++)
  1868. {
  1869. DisposeImg->ImgData[row*width+Rect_X[temp]]=255;
  1870. DisposeImg->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;
  1871. }
  1872.     for(col=Rect_X[temp];col<(Rect_X[temp]+Rect_W[temp]);col++)
  1873. {
  1874. DisposeImg->ImgData[Rect_Y[temp]*width+col]=255;
  1875.      DisposeImg->ImgData[(Rect_Y[temp]+Rect_H[temp])*width+col]=255;
  1876. } */
  1877. free(TempImg);
  1878. }
  1879. /// <summary>
  1880. /// CDipView::VFurthLocate(BYTE *DisposeImg, int width, int height)的摘要说明。
  1881. /// 创建人  :刘陈炜
  1882. /// 创建时间:2004.5.1
  1883. /// 函数功能:找出车牌的左右边缘
  1884. /// 程序流程:1.水平差分,二值化;
  1885. ///           2.垂直方向投影,统计各列的投影值;
  1886. ///           3.去除噪声点;
  1887. ///           4.找出左右边缘
  1888. ///           5.计算车牌宽度
  1889. ///           6.车牌精确定位赋值
  1890. /// </summary>
  1891. void CDipView::VFurthLocate(BYTE *DisposeImg, int width, int height)
  1892. {
  1893. int row=0;
  1894. int col=0;
  1895. int num=0;
  1896. int leftCol=0;
  1897. int rightCol=width-1;
  1898. HSub(DisposeImg,width,height); 
  1899. ForHandle(DisposeImg,width,height);                           //二值化
  1900.     //note the value of hProjection
  1901. int*HProj=new int[width];                        
  1902. for(col=0;col<width;col++)
  1903. {
  1904. HProj[col]=0;
  1905. }    
  1906. for(col=0;col<width;col++)
  1907. {
  1908. for(row=0;row<height;row++)
  1909. {
  1910. if(DisposeImg[row*width+col]==255)
  1911. HProj[col]++;
  1912. }
  1913. }
  1914. HProj[0]=0;
  1915. for(col=0;col<width;col++)                    //去除噪声点
  1916. {
  1917. if(HProj[col]<3)
  1918. {
  1919. HProj[col]=0;
  1920. }
  1921. }    
  1922. ///////////////////////////////////////////找出左边缘
  1923. int nextCol=0;
  1924. int w=0;
  1925. for(col=0;col<width;col++)
  1926. {
  1927. num=0;
  1928. if(HProj[col]==0&&HProj[col+1]!=0)
  1929. {
  1930. num++;
  1931. nextCol=FindNextCol_LR(HProj,width,col);
  1932. w=nextCol-col;
  1933. leftCol=col;
  1934. }
  1935. if(w<3)
  1936. {
  1937. num=num-1;
  1938. }
  1939. if(num==1)
  1940. {
  1941. break;
  1942. }
  1943. }
  1944. //////////////////////////////////////////找出右边缘
  1945. nextCol=0;
  1946. w=0;
  1947. for(col=width;col>=0;col--)
  1948. {
  1949. num=0;
  1950. if(HProj[col]==0&&HProj[col-1]!=0)
  1951. {
  1952. num++;
  1953. nextCol=FindNextCol_RL(HProj,width,col);
  1954. w=col-nextCol;
  1955. rightCol=col;
  1956. }
  1957. if(w<3)
  1958. {
  1959. num=num-1;
  1960. }
  1961. if(num==1)
  1962. {
  1963. break;
  1964. }
  1965. }
  1966. int blantCols=0;
  1967. blantCols=leftCol+(width-rightCol);
  1968. Rect_X[0]+=leftCol;
  1969. Rect_W[0]=width-blantCols;
  1970. free(HProj);
  1971. }
  1972. /// <summary>
  1973. /// CDipView::ForHandle(BYTE *DisposeImg, int width, int height)的摘要说明。
  1974. /// 创建人  :刘陈炜
  1975. /// 创建时间:2004.5.1
  1976. /// 函数功能:二值化图象
  1977. /// 程序说明:threshold=average+delt;
  1978. /// 程序流程:1.计算图象均值;
  1979. ///           2.计算图象方差;
  1980. ///           3.二值化
  1981. /// </summary>
  1982. void CDipView::ForHandle(BYTE *DisposeImg, int width, int height)
  1983. {
  1984.  BYTE *temp=new BYTE[height*width];
  1985.  int x,y;
  1986.  CopyImg(DisposeImg,temp,width,height);
  1987.  long double total=0;
  1988.  float aver=0;
  1989.  for(x=0;x<height;x++)
  1990.  {
  1991.  for(y=0;y<width;y++)
  1992.  {
  1993.  total+=DisposeImg[x*width+y];
  1994.  }
  1995.  }
  1996.  aver=(BYTE)(total/(float)(height*width));
  1997.  float delt; 
  1998.  float sub=0; 
  1999.  for(x=0;x<height;x++)
  2000.  {
  2001.  for(y=0;y<width;y++)
  2002.  {
  2003.  sub+=(DisposeImg[x*width+y]-aver)*(DisposeImg[x*width+y]-aver);  
  2004.  }
  2005.  }
  2006.  delt=(float)(sqrt(sub/(float)(height*width)));
  2007.  BYTE judge;
  2008.  judge=(BYTE)(delt+aver);
  2009.  for(x=0;x<height;x++)
  2010.  {
  2011. for(y=0;y<width;y++)
  2012.  {
  2013. if(DisposeImg[(x*width)+y]>=judge)
  2014. {
  2015. DisposeImg[(x*width)+y]=255;
  2016. }
  2017. else
  2018. {
  2019. DisposeImg[(x*width)+y]=0;
  2020. }
  2021. }
  2022. }
  2023.  
  2024.  free(temp);
  2025. }
  2026. // 寻找left==255,right==0的列
  2027. int CDipView::FindNextCol_LR(int* HProj, int size, int objectCol)
  2028. {
  2029. int num=0;
  2030. int x=0;
  2031. for(x=objectCol;x<size;x++)
  2032. {
  2033. if(HProj[x]>=0&&HProj[x+1]==0)
  2034. {
  2035. num++;
  2036. }
  2037. if(num==1)
  2038. {
  2039. break;
  2040. }
  2041. }
  2042. if(num==0)
  2043. {
  2044. return objectCol; 
  2045. }
  2046. else
  2047. {
  2048. return x;
  2049. }
  2050. }
  2051. // 寻找right==255,left==0的列
  2052. int CDipView::FindNextCol_RL(int* HProj, int size, int objectCol)
  2053. {
  2054. int num=0;
  2055. int x=0;
  2056. for(x=objectCol;x>=0;x--)
  2057. {
  2058. if(HProj[x]>=0&&HProj[x-1]==0)
  2059. {
  2060. num++;
  2061. }
  2062. if(num==1)
  2063. {
  2064. break;
  2065. }
  2066. }
  2067. if(num==0)
  2068. {
  2069. return objectCol; 
  2070. }
  2071. else
  2072. {
  2073. return x;
  2074. }
  2075. }
  2076. void CDipView::OnSobel()
  2077. {
  2078. // TODO: 在此添加命令处理程序代码
  2079. }
  2080. /// <summary>
  2081. /// CDipView::OnVSplit()的摘要说明。
  2082. /// 创建人  :刘陈炜
  2083. /// 创建时间:2004.5.1
  2084. /// 函数功能:车牌字符分割
  2085. /// 程序流程:1.区域扩展;
  2086. ///           2.投影分割;
  2087. ///           3.字符区域的获取;
  2088. /// </summary>
  2089. void CDipView::OnVSplit()
  2090. {
  2091. // TODO: 在此添加命令处理程序代码
  2092. CDipDoc *pDoc=GetDocument();
  2093. int width,height;
  2094. width=pDoc->ImgWidth;
  2095. height=pDoc->ImgHeight;
  2096. int row=0;
  2097. int col=0;
  2098. //extend area
  2099. int threshold=2;
  2100. Rect_X[0]=Rect_X[0];
  2101. Rect_Y[0]=Rect_Y[0];//-threshold;
  2102. Rect_W[0]=Rect_W[0]+7;
  2103. Rect_H[0]=Rect_H[0];//+2*threshold;
  2104. //车牌区域的高度、宽度
  2105. int w=Rect_W[0];
  2106. int h=Rect_H[0];
  2107. BYTE* TempImg=new BYTE[w*h];
  2108. for(row=0;row<h;row++)
  2109. {
  2110. for(col=0;col<w;col++)
  2111. {
  2112. TempImg[row*w+col]=pDoc->ImgData[(Rect_Y[0]+row)*width+(Rect_X[0]+col)];
  2113. }
  2114. }
  2115. //二值化车牌区域图象
  2116. ForHandle(TempImg,w,h);
  2117. //搜索各字符域
  2118. int *projArray=new int[w];
  2119. for(col=0;col<w;col++)
  2120. {
  2121. projArray[col]=0;
  2122. }
  2123. HProj(TempImg,projArray,w,h);
  2124. CharacterSplit(projArray,w);
  2125. // GetCharacter();
  2126. ///////////////////////////////标记出各个字符区域
  2127. int area;
  2128. area=CharacterNum;
  2129. for(;area>=0;area--)
  2130. {
  2131. if(cRects[area].w!=0&&cRects[area].x!=-1)
  2132. {
  2133. for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line
  2134. {
  2135. pDoc->ImgData[row*width+cRects[area].x]=255;
  2136. pDoc->ImgData[row*width+(cRects[area].x+cRects[area].w)]=255;
  2137. }
  2138.      for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line
  2139. {
  2140. pDoc->ImgData[cRects[area].y*width+col]=255;
  2141. pDoc->ImgData[(cRects[area].y+cRects[area].h)*width+col]=255;
  2142. }
  2143. }
  2144. }
  2145. // 区域刻画
  2146. //int temp=0;
  2147. //for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++)
  2148. //{
  2149. // pDoc->ImgData[row*width+Rect_X[temp]]=255;
  2150. // pDoc->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;
  2151. //}
  2152. //
  2153.  //   for(col=Rect_X[temp];col<(Rect_X[temp]+Rect_W[temp]);col++)
  2154. //{
  2155. // pDoc->ImgData[Rect_Y[temp]*width+col]=255;
  2156.  //    pDoc->ImgData[(Rect_Y[temp]+Rect_H[temp])*width+col]=255;
  2157. //}
  2158. //for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++)
  2159. //{
  2160. // for(col=0;col<w;col++)
  2161. // {
  2162. // if(projArray[col]==1)
  2163. // {
  2164. // pDoc->ImgData[row*width+Rect_X[temp]+col]=255;
  2165. // // pDoc->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;
  2166. // }
  2167. // }
  2168. //}
  2169. free(TempImg);
  2170. free(projArray);
  2171. IsNewBitmap=true;
  2172. IsNewFile=true;
  2173. pDoc->UpdateAllViews(NULL); 
  2174. }
  2175. // 图像规定化0~100
  2176. void CDipView::GuiYiHua(BYTE* DisposeImg, int width , int height)
  2177. {
  2178. }
  2179. // 增强车牌区,削弱背景
  2180. void CDipView::Hance(BYTE* DisposeImg, int width , int height)
  2181. {
  2182. }
  2183. void CDipView::OnGuiYiHua()
  2184. {
  2185. // TODO: 在此添加命令处理程序代码
  2186. }
  2187. void CDipView::OnHance()
  2188. {
  2189. // TODO: 在此添加命令处理程序代码
  2190. }
  2191. /// <summary>
  2192. /// CDipView::HProj(BYTE* DisposeImg, int* projArray, int width , int height)的摘要说明。
  2193. /// 创建人  :刘陈炜
  2194. /// 创建时间:2004.5.1
  2195. /// 函数功能:水平方向投影,分割出字符
  2196. /// 程序流程:1.统计各列白象素个数;
  2197. ///           2.平滑投影曲线;
  2198. ///           3.寻找波谷(trough)进行分割;
  2199. /// </summary>
  2200. void CDipView::HProj(BYTE* DisposeImg, int* projArray, int width , int height)
  2201. {
  2202. int row=0;
  2203. int col=0;
  2204. float alph=0.0;
  2205. int*E=new int[width];
  2206. long double*MSE=new long double[9];                         //针对每一个alph的deltl;
  2207. //统计各列白象素个数
  2208. for(col=0;col<width;col++)
  2209. {
  2210. for(row=0;row<height;row++)
  2211. {
  2212. if(DisposeImg[row*width+col]==255)
  2213. projArray[col]++;
  2214. }
  2215. }
  2216. //一次平滑
  2217. for(int x=1;x<10;x++)
  2218. {
  2219. alph=(float)(0.1*x);
  2220. E[0]=projArray[0];
  2221. for(col=1;col<width;col++)
  2222. {
  2223. E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
  2224. }
  2225. for(col=0;col<width;col++)
  2226. {
  2227. MSE[x-1]+=(projArray[col]-E[col])*(projArray[col]-E[col]);
  2228. }
  2229. MSE[x-1]=MSE[x-1]/width;
  2230. }
  2231. long double min=0.0;
  2232. for(x=1;x<10;x++)
  2233. {
  2234. if(MSE[x-1]>min)
  2235. {
  2236. min=MSE[x-1];
  2237. }
  2238. }
  2239. for(x=1;x<10;x++)
  2240. {
  2241. if(MSE[x-1]==min)
  2242. {
  2243. alph=(float)(0.1*x);
  2244. }
  2245. }
  2246. E[0]=projArray[0];
  2247. for(col=1;col<width;col++)
  2248. {
  2249. E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
  2250. }
  2251. for(col=1;col<width;col++)
  2252. {
  2253. projArray[col]=E[col];
  2254. E[col]=0;
  2255. }
  2256. //二次平滑
  2257. for(x=1;x<10;x++)
  2258. {
  2259. alph=(float)(0.1*x);
  2260. E[0]=projArray[0];
  2261. for(col=1;col<width;col++)
  2262. {
  2263. E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
  2264. }
  2265. for(col=0;col<width;col++)
  2266. {
  2267. MSE[x-1]+=(projArray[col]-E[col])*(projArray[col]-E[col]);
  2268. }
  2269. MSE[x-1]=MSE[x-1]/width;
  2270. }
  2271. min=0.0;
  2272. for(x=1;x<10;x++)
  2273. {
  2274. if(MSE[x-1]<min)
  2275. {
  2276. min=MSE[x-1];
  2277. }
  2278. }
  2279. for(x=1;x<10;x++)
  2280. {
  2281. if(MSE[x-1]==min)
  2282. {
  2283. alph=(float)(0.1*x);
  2284. }
  2285. }
  2286. E[0]=projArray[0];
  2287. for(col=1;col<width;col++)
  2288. {
  2289. E[col]=(int)(alph*projArray[col]+(1-alph)*E[col-1]);
  2290. }
  2291. for(col=1;col<width;col++)
  2292. {
  2293. projArray[col]=E[col];
  2294. E[col]=0;
  2295. }
  2296.     //寻找波谷进行分割trough
  2297. FindTrough(projArray,width); //获得波谷位置
  2298. free(E);
  2299. free(MSE);
  2300. }
  2301. // 寻找波谷,划分字符区间
  2302. void CDipView::FindTrough(int* Array, int size)
  2303. {
  2304. int col=0;
  2305. bool*flage=new bool[size];
  2306. bool LFlage=false;                                //a wave start leftside
  2307. bool RFlage=false;                                //a wave end   rightside
  2308. int  LSide=0;                                     //left side
  2309. int  RSide=0;   //right side
  2310. int  length=0;                                    //area width
  2311. for(col=0;col<size;col++)
  2312. {
  2313. flage[col]=false;
  2314. }
  2315. for(col=1;col<size-1;col++)
  2316. {
  2317. if(Array[col]==0&&Array[col+1]!=0&&LFlage==false)
  2318. {
  2319. flage[col]=true;
  2320. LFlage=true;
  2321. }
  2322. if((Array[col-1]!=0)&&(Array[col]==0)&&(LFlage==true)&&(RFlage==false))
  2323. {
  2324. flage[col]=true;
  2325. RFlage=true;
  2326. }
  2327. if((LFlage==true)&&(RFlage==true))
  2328. {
  2329. LFlage=false;
  2330. RFlage=false;
  2331. }
  2332. }
  2333. for(col=0;col<size;col++)
  2334. {
  2335. Array[col]=0;
  2336. if(flage[col]==true)
  2337. {
  2338. Array[col]=1;
  2339. }
  2340. }
  2341. }
  2342. // 分割字符
  2343. void CDipView::CharacterSplit(int* Array, int size)
  2344. {
  2345. CDipDoc *pDoc=GetDocument();
  2346. int width,height;
  2347. width=pDoc->ImgWidth;
  2348. height=pDoc->ImgHeight;
  2349.     int x=Rect_X[0];
  2350. int y=Rect_Y[0];
  2351. int w=Rect_W[0];
  2352. int h=Rect_H[0];
  2353.     int num=0;
  2354. for(num=0;num<10;num++)
  2355. {
  2356. cRects[num].x=-1;
  2357. cRects[num].y=-1;
  2358. cRects[num].w=0;
  2359. cRects[num].h=0;
  2360. }
  2361. bool flage=false;
  2362. int row=0;
  2363. int col=0;
  2364. int area=0;
  2365. num=0;
  2366. for(col=0;col<size;col++)
  2367. {
  2368. if(Array[col]==1)
  2369. {
  2370. num++;
  2371. if(num%2!=0&&flage==false)
  2372. {
  2373. flage=true;
  2374. cRects[area].x=x+col;
  2375. }
  2376. else if(num%2==0&&flage==true)
  2377. {
  2378. flage=false;
  2379. cRects[area].w=col-(cRects[area].x-x);
  2380. cRects[area].y=y;
  2381. cRects[area].h=h;
  2382. area++;
  2383. }
  2384. }
  2385. }
  2386. CharacterNum=area;
  2387. // CharacterNum=area+1;
  2388. for(;area>=0;area--)
  2389. {
  2390. if(cRects[area].w!=0)
  2391. {
  2392. for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line
  2393. {
  2394. pDoc->ImgData[row*width+cRects[area].x-1]=255;
  2395. pDoc->ImgData[row*width+(cRects[area].x+cRects[area].w)]=255;
  2396. }
  2397. for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line
  2398. {
  2399. pDoc->ImgData[(cRects[area].y-1)*width+col]=255;
  2400. pDoc->ImgData[(cRects[area].y+cRects[area].h)*width+col]=255;
  2401. }
  2402. }
  2403. }
  2404. //save character
  2405.     for(area=CharacterNum;area>=0;area--)
  2406. {
  2407. cDatas[area].w=cRects[area].w;
  2408. cDatas[area].h=cRects[area].h;
  2409. cDatas[area].Img=new BYTE[cRects[area].w*cRects[area].h];
  2410. for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line
  2411. {
  2412. for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line
  2413. {
  2414. cDatas[area].Img[(row-cRects[area].y)*cRects[area].w+(col-cRects[area].x)]=pDoc->ImgData[row*width+col];
  2415. }
  2416. }
  2417. }
  2418. }
  2419. /*
  2420. // 读取样本库,传入一个sample类型的数组(从文件里读出的样本数据将放入其中),返回值为样本个数
  2421. int CDipView::LoadCharLib(sample* sa)
  2422. {
  2423. CFile cf;
  2424. if(cf.Open(".\mydata.dat",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  2425. {
  2426. AfxMessageBox("打开文件失败,n您最好退出程序");
  2427. }
  2428. int num=0;
  2429. try
  2430. {
  2431. sample sampleTemp;
  2432. cf.SeekToBegin();
  2433. DWORD dwBytesRemaining=(DWORD)(cf.GetLength());
  2434. while(dwBytesRemaining)
  2435. {
  2436. UINT nBytesRead=cf.Read(&sampleTemp,sizeof(sample));
  2437. sa[num]=sampleTemp;
  2438. dwBytesRemaining-=nBytesRead;
  2439. num++;
  2440. }
  2441. CString s;
  2442. // s.Format("共读取数据%d个,最后一个的序列号为%d",
  2443. // num,sampleTemp.serialnum);
  2444. // AfxMessageBox(s);
  2445. }
  2446. catch(CFileException *e)
  2447. {
  2448. e->ReportError();
  2449. e->Delete();
  2450. }
  2451. cf.Close();
  2452. return num;
  2453. }
  2454. // 缩放算法,一律缩放为20*36
  2455. void CDipView::Zoom(BYTE* DisposeImg, int width, int height)
  2456. {
  2457. if ((width==20)&&(height==36))
  2458. return;
  2459. // 源图像的宽度和高度
  2460. LONG lWidth=width;
  2461. LONG lHeight=height;
  2462. BYTE *temp_img=new BYTE[width*height];
  2463. // 循环变量
  2464. int i;
  2465. int j;
  2466. for(i = 0; i < height; i++)
  2467. {
  2468. for(j = 0; j < width; j++)
  2469. {
  2470. temp_img[j+i*width]=DisposeImg[j+i*width];
  2471. }
  2472. }
  2473. // 缩放后图像的宽度和高度
  2474. LONG lNewWidth;
  2475. LONG lNewHeight;
  2476. float XZRatio=(float)( 20.0/(float)(width));
  2477. float YZRatio=(float)(36.0/(float)(height));
  2478. // 象素在源坐标
  2479. LONG i0;
  2480. LONG j0;
  2481. //归一后的大小
  2482. lNewWidth = 20;
  2483. lNewHeight = 36;
  2484. height=lNewHeight;
  2485. width=lNewWidth;
  2486. for(i = 0;i< lNewHeight;i++)
  2487. {
  2488. for(j = 0;j< lNewWidth;j++)
  2489. {
  2490. i0 = (LONG) (i / YZRatio + 0.5);
  2491. j0 = (LONG) (j / XZRatio + 0.5);
  2492. // 判断是否在源图范围内
  2493. if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
  2494. {
  2495. // 复制象素
  2496. DisposeImg[j+i*lWidth] = temp_img[j0 + i0*lWidth];
  2497. }
  2498. else
  2499. {
  2500. // 对于源图中没有的象素,直接赋值为255
  2501. // DisposeImg[j+i*lWidth] = 0;
  2502. }
  2503. }
  2504. }
  2505. delete [] temp_img;
  2506. }
  2507. // 二值化算法,二值化为0和1两种值
  2508. void CDipView::BinaryImg(BYTE* DisposeImg, int width , int height)
  2509. {
  2510.  BYTE *temp=new BYTE[height*width];
  2511.  int x,y;
  2512.  CopyImg(DisposeImg,temp,width,height);
  2513.  long double total=0;
  2514.  float aver=0;
  2515.  for(x=0;x<height;x++)
  2516.  {
  2517.  for(y=0;y<width;y++)
  2518.  {
  2519.  total+=DisposeImg[x*width+y];
  2520.  }
  2521.  }
  2522.  aver=(BYTE)(total/(float)(height*width));
  2523.  float delt; 
  2524.  float sub=0; 
  2525.  for(x=0;x<height;x++)
  2526.  {
  2527.  for(y=0;y<width;y++)
  2528.  {
  2529.  sub+=(DisposeImg[x*width+y]-aver)*(DisposeImg[x*width+y]-aver);  
  2530.  }
  2531.  }
  2532.  delt=(float)(sqrt(sub/(float)(height*width)));
  2533.  BYTE judge;
  2534.  judge=(BYTE)(delt+aver);
  2535.  for(x=0;x<height;x++)
  2536.  {
  2537. for(y=0;y<width;y++)
  2538.  {
  2539. if(DisposeImg[(x*width)+y]>=judge)
  2540. {
  2541. DisposeImg[(x*width)+y]=(BYTE)1;
  2542. }
  2543. else
  2544. {
  2545. DisposeImg[(x*width)+y]=(BYTE)0;
  2546. }
  2547. }
  2548.  }
  2549.  
  2550.  free(temp);
  2551. }
  2552. // Hilditch细化算法
  2553. void CDipView::ThinnerHilditch(void* image, unsigned long lx, unsigned long ly)
  2554. {
  2555. char *f, *g;
  2556. char n[10];
  2557. unsigned int counter;
  2558. short k, shori, xx, nrn;
  2559. unsigned long i, j;
  2560. long kk, kk11, kk12, kk13, kk21, kk22, kk23, kk31, kk32, kk33, size;
  2561. size = (long)lx * (long)ly;
  2562. g = (char *)malloc(size);
  2563. if(g == NULL)
  2564. {
  2565. printf("error in allocating memory!n");
  2566. return;
  2567. }
  2568. f = (char *)image;
  2569. for(i=0; i<lx; i++)
  2570. {
  2571. for(j=0; j<ly; j++)
  2572. {
  2573. kk=i*ly+j;
  2574. if(f[kk]!=0)
  2575. {
  2576. f[kk]=1;
  2577. g[kk]=f[kk];
  2578. }
  2579. }
  2580. }
  2581. counter = 1;
  2582. do
  2583. {
  2584. printf("%4d*",counter);
  2585. counter++;
  2586. shori = 0;
  2587. for(i=0; i<lx; i++)
  2588. {
  2589. for(j=0; j<ly; j++)
  2590. {
  2591. kk = i*ly+j;
  2592. if(f[kk]<0)
  2593. f[kk] = 0;
  2594. g[kk]= f[kk];
  2595. }
  2596. }
  2597. for(i=1; i<lx-1; i++)
  2598. {
  2599. for(j=1; j<ly-1; j++)
  2600. {
  2601. kk=i*ly+j;
  2602. if(f[kk]!=1)
  2603. continue;
  2604. kk11 = (i-1)*ly+j-1;
  2605. kk12 = kk11 + 1;
  2606. kk13 = kk12 + 1;
  2607. kk21 = i*ly+j-1;
  2608. kk22 = kk21 + 1;
  2609. kk23 = kk22 + 1;
  2610. kk31 = (i+1)*ly+j-1;
  2611. kk32 = kk31 + 1;
  2612. kk33 = kk32 + 1;
  2613. if((g[kk12]&&g[kk21]&&g[kk23]&&g[kk32])!=0)
  2614. continue;
  2615. nrn = g[kk11] + g[kk12] + g[kk13] + g[kk21] + g[kk23] + 
  2616. g[kk31] + g[kk32] + g[kk33];
  2617. if(nrn <= 1)
  2618. {
  2619. f[kk22] = 2;
  2620. continue;
  2621. }
  2622. n[4] = f[kk11];
  2623. n[3] = f[kk12];
  2624. n[2] = f[kk13];
  2625. n[5] = f[kk21];
  2626. n[1] = f[kk23];
  2627. n[6] = f[kk31];
  2628. n[7] = f[kk32];
  2629. n[8] = f[kk33];
  2630. n[9] = n[1];
  2631. xx = 0;
  2632. for(k=1; k<8; k=k+2)
  2633. {
  2634. if((!n[k])&&(n[k+1]||n[k+2]))
  2635. xx++;
  2636. }
  2637. if(xx!=1)
  2638. {
  2639. f[kk22] = 2;
  2640. continue;
  2641. }
  2642. if(f[kk12] == -1)
  2643. {
  2644. f[kk12] = 0;
  2645. n[3] = 0;
  2646. xx = 0;
  2647. for(k=1; k<8; k=k+2)
  2648. {
  2649. if((!n[k])&&(n[k+1]||n[k+2]))
  2650. xx++;
  2651. }
  2652. if(xx != 1)
  2653. {
  2654. f[kk12] = -1;
  2655. continue;
  2656. }
  2657. f[kk12] = -1;
  2658. n[3] = -1;
  2659. }
  2660. if(f[kk21]!=-1)
  2661. {
  2662. f[kk22] = -1;
  2663. shori = 1;
  2664. continue;
  2665. }
  2666. f[kk21] = 0;
  2667. n[5] = 0;
  2668. xx = 0;
  2669. for(k=1; k<8; k=k+2)
  2670. {
  2671. if((!n[k])&&(n[k+1]||n[k+2]))
  2672. {
  2673. xx++;
  2674. }
  2675. }
  2676. if(xx == 1)
  2677. {
  2678. f[kk21] = -1;
  2679. f[kk22] = -1;
  2680. shori =1;
  2681. }
  2682. else
  2683. f[kk21] = -1;
  2684. }
  2685. }
  2686. }while(shori);
  2687. free(g);
  2688. }
  2689. // 细化算法
  2690. void CDipView::ThinImage(BYTE* image, int width, int height)
  2691. {
  2692. LONG x,y,k;
  2693. BYTE image1[10000];
  2694. k=0;
  2695. LONG digitWidth = width;
  2696. LONG digitHeight = height;
  2697. for(x=0; x<digitWidth; x++)
  2698. {
  2699. image[x*width+0] = (BYTE)0;
  2700. image[x*width+digitHeight-1] = (BYTE)0;
  2701. }
  2702. for(y=0; y<digitHeight; y++)
  2703. {
  2704. image[0*width+y] = (BYTE)0;
  2705. image[(digitWidth-1)*width+y] = (BYTE)0;
  2706. }
  2707. for(x=0; x<digitWidth; x++)
  2708. {
  2709. for(y=0; y<digitHeight; y++)
  2710. {
  2711. image1[k] = image[x*width+y];
  2712. if(image1[k] != 0)
  2713. image1[k] = (BYTE)1;
  2714. k++;
  2715. }
  2716. }
  2717. ThinnerHilditch((void *)image1, digitWidth, digitHeight);
  2718. k=0;
  2719. for(x=0; x<digitWidth; x++)
  2720. {
  2721. for(y=0; y<digitHeight; y++)
  2722. {
  2723. image[x*width+y] = image1[k];
  2724. if(image[x*width+y]!=0)
  2725. image[x*width+y] = (BYTE)1;
  2726. k++;
  2727. }
  2728. }
  2729. }
  2730. // 获取特征值的函数
  2731. void CDipView::GetFeature(BYTE* image, long width, long height, double* feature, int size)
  2732. {
  2733. int i,j;
  2734. for(i=0; i<13; i++)
  2735. feature[i] = 0;
  2736. //图象是20×36大小的,分成9块
  2737. //第一块
  2738. for(i=0; i<7; i++)
  2739. {
  2740. for(j=0; j<12; j++)
  2741. {
  2742. if(image[i*width+j]==1)
  2743. feature[0]+=1.0;
  2744. }
  2745. }
  2746. //第二块
  2747. for(i=0; i<7; i++)
  2748. {
  2749. for(j=12; j<24; j++)
  2750. {
  2751. if(image[i*width+j]==1)
  2752. feature[1]+=1.0;
  2753. }
  2754. }
  2755. //第三块
  2756. for(i=0; i<7; i++)
  2757. {
  2758. for(j=24; j<36; j++)
  2759. {
  2760. if(image[i*width+j]==1)
  2761. feature[2]+=1.0;
  2762. }
  2763. }
  2764. //第四块
  2765. for(i=7; i<13; i++)
  2766. {
  2767. for(j=0; j<12; j++)
  2768. {
  2769. if(image[i*width+j]==1)
  2770. feature[3]+=1.0;
  2771. }
  2772. }
  2773. //第五块
  2774. for(i=7; i<13; i++)
  2775. {
  2776. for(j=12; j<24; j++)
  2777. {
  2778. if(image[i*width+j]==1)
  2779. feature[4]+=1.0;
  2780. }
  2781. }
  2782. //第六块
  2783. for(i=7; i<13; i++)
  2784. {
  2785. for(j=24; j<36; j++)
  2786. {
  2787. if(image[i*width+j]==1)
  2788. feature[5]+=1.0;
  2789. }
  2790. }
  2791. //第七块
  2792. for(i=13; i<20; i++)
  2793. {
  2794. for(j=0; j<12; j++)
  2795. {
  2796. if(image[i*width+j]==1)
  2797. feature[6]+=1.0;
  2798. }
  2799. }
  2800. //第八块
  2801. for(i=13; i<20; i++)
  2802. {
  2803. for(j=12; j<24; j++)
  2804. {
  2805. if(image[i*width+j]==1)
  2806. feature[7]+=1.0;
  2807. }
  2808. }
  2809. //第九块
  2810. for(i=13; i<20; i++)
  2811. {
  2812. for(j=24; j<36; j++)
  2813. {
  2814. if(image[i*width+j]==1)
  2815. feature[8]+=1.0;
  2816. }
  2817. }
  2818. //下面统计方向交点特征
  2819. for(j=0; j<36; j++)
  2820. {
  2821. if(image[7*width+j]==1)
  2822. feature[9]+=1.0;
  2823. }
  2824. for(j=0; j<36; j++)
  2825. {
  2826. if(image[13*width+j]==1)
  2827. feature[10]+=1.0;
  2828. }
  2829. for(i=0; i<20; i++)
  2830. {
  2831. if(image[i*width+12]==1)
  2832. feature[11]+=1.0;
  2833. }
  2834. for(i=0; i<20; i++)
  2835. {
  2836. if(image[i*width+24]==1)
  2837. feature[12]+=1.0;
  2838. }
  2839. }
  2840. // 识别函数,第一个参数为LoadCharLib读出的数组,
  2841. //第二个参数为LoadCharLib的返回值(即样本个数),
  2842. //将上面获得的特征值传入第三个参数,返回为识别结果
  2843. CString CDipView::Recognize(sample* sa, int num, double* feature)
  2844. {
  2845. int j;
  2846. double min=100000.0;
  2847. CString Result;
  2848. for(int i=0;i<num;i++)
  2849. {
  2850. double diff = 0.0;
  2851. for(j=0; j<9; j++)
  2852. {
  2853. diff += fabs(feature[j] - sa[num].feature[j]);
  2854. }
  2855. for(j=9; j<13; j++)
  2856. {
  2857. diff += fabs(feature[j] - sa[num].feature[j])*9;
  2858. }
  2859. if(diff < min)
  2860. {
  2861. min = diff;
  2862. Result.Format("%s",sa[num].trueClass);
  2863. }
  2864. }
  2865. return Result;
  2866. }*/
  2867. // 字符识别
  2868. /*void CDipView::GetCharacter()
  2869. {
  2870. //CDipDoc *pDoc=GetDocument();
  2871. //int width,height;
  2872. //width=pDoc->ImgWidth;
  2873. //height=pDoc->ImgHeight;
  2874. //sample mysa[500];
  2875.  //   double myfeature[13];
  2876.  //   int num;
  2877.  //   CString result[10];
  2878. //BYTE*Img;
  2879. //int row=0;
  2880. //int col=0;
  2881. //int x=-1;
  2882. //int y=-1;
  2883. //int w=0;
  2884. //int h=0;
  2885. //int area=0;
  2886. //for(area=0;area<10;area++);
  2887. //{
  2888. // if(cRects[area].w>0)
  2889. // {
  2890. // x=cRects[area].x;
  2891. // y=cRects[area].y;
  2892. // w=cRects[area].w;
  2893. // h=cRects[area].h;
  2894.  //           Img=new BYTE[w*h];
  2895. // for(row=0;row<h;row++)
  2896. // {
  2897. // for(col=0;col<w;col++)
  2898. // {
  2899.  //        //           Img[row*w+col]=pDoc->ImgData[y*width+x];
  2900. // }
  2901. // }
  2902. //// //num=LoadCharLib(mysa);                         //获取样本库保存到mysa[500]中
  2903. //// //Zoom(Img,w,h);                                 //对切割出的图象进行大小归一化
  2904. //// //ThinImage(Img,w,h);                            //对大小归一化后的图象进行细化
  2905. //// //GetFeature(Img,w,h,myfeature,13);    //图象细化以后就可以提取特征了
  2906. //// //result[area]=Recognize(mysa,num,myfeature);
  2907. // }
  2908. //}
  2909. //delete []mysa;
  2910. //delete []myfeature;
  2911. //delete []result;
  2912. }*/
  2913. void CDipView::OnCharacterRecg()
  2914. {
  2915. CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent(); 
  2916. CCharView* pchview=(CCharView*)MainFrame->m_wndSplitter.GetPane(0,1); 
  2917. CDigitClass digitTest;
  2918. CString classResult;
  2919. CString tempstr;
  2920. CString strInfo, strTemp;
  2921. int recgpos=1;
  2922. for(int k=0;k<CharacterNum;k++)
  2923. {
  2924. if ((float) cDatas[k].h/cDatas[k].w>4)
  2925. {
  2926. if (recgpos!=1&&recgpos<8)
  2927. {
  2928. classResult=classResult+"1";
  2929. recgpos++;
  2930. }
  2931. continue;
  2932. }
  2933. for(int x=0;x<cDatas[k].h;x++)
  2934. {
  2935. for(int y=0;y<cDatas[k].w;y++)
  2936. {
  2937. digitTest.digitarray[y][x]=cDatas[k].Img[x*cDatas[k].w+y];
  2938. }
  2939. }
  2940. digitTest.digitHeight=cDatas[k].h;
  2941. digitTest.digitWidth=cDatas[k].w;
  2942. digitTest.FixSize();
  2943. digitTest.BinaryDigit();
  2944. //digitTest.MarrBinary();
  2945. digitTest.ThinDigit_1();
  2946. pchview->m_result.SetSel(0,-1);
  2947. pchview->m_result.ReplaceSel("");
  2948. CString strInfo, strTemp;
  2949. strInfo.Format("");
  2950. int i,j;
  2951. for(i=0; i<digitTest.digitHeight; i++)
  2952. {
  2953. for(j=0; j<digitTest.digitWidth; j++)
  2954. {
  2955. if(digitTest.digitarray[j][i] == 1)
  2956. strInfo += "■";
  2957. else
  2958. strInfo += "  ";
  2959. }
  2960. strInfo += "rn";
  2961. }
  2962. pchview->m_result.SetSel(0,-1);
  2963. pchview->m_result.ReplaceSel(strInfo);
  2964. // AfxMessageBox("hello");
  2965. digitTest.GetFeature();
  2966. if (recgpos==1)
  2967. {
  2968. double min=100000.0;
  2969. POSITION pos=hanList.GetHeadPosition();
  2970. while(pos!=NULL)
  2971. {
  2972. Sample sa;
  2973. sa=hanList.GetNext(pos);
  2974. double diff = 0.0;
  2975. for(j=0; j<9; j++)
  2976. {
  2977. diff += fabs(digitTest.feature[j] - sa.feature[j]);
  2978. }
  2979. for(j=9; j<13; j++)
  2980. {
  2981. diff += fabs(digitTest.feature[j] - sa.feature[j])*9;
  2982. }
  2983. if(diff < min)
  2984. {
  2985. min = diff;
  2986. tempstr.Format("%s",sa.trueClass);
  2987. }
  2988. }
  2989. classResult=classResult+tempstr;
  2990. }
  2991. if (recgpos==2)
  2992. {
  2993. double temp[13];
  2994. double result1[26];
  2995. bool t=0;
  2996. for (i=0;i<13;i++)
  2997. {
  2998. temp[i]=digitTest.feature[i]/15;
  2999. }
  3000. char_bp.Identify(temp,13,result1,26);
  3001. for(i=0;i<26;i++)
  3002. {
  3003. if (ABS(result1[i]-1)<0.1)
  3004. {
  3005. tempstr.Format("%c",i+'A');
  3006. classResult=classResult+tempstr;
  3007. t=1;
  3008. }
  3009. }
  3010. if(t!=1)
  3011. classResult=classResult+'?';
  3012. }
  3013. // strTemp.Format("%d", classResult);
  3014. if (recgpos==3)
  3015. {
  3016. double temp[13];
  3017. double result1[36];
  3018. bool t=0;
  3019. for (i=0;i<13;i++)
  3020. {
  3021. temp[i]=digitTest.feature[i]/15;
  3022. }
  3023. char_num_bp.Identify(temp,13,result1,36);
  3024. for(i=0;i<36;i++)
  3025. {
  3026. if (ABS(result1[i]-1)<0.2)
  3027. {
  3028. if(i<=9)
  3029. {
  3030. tempstr.Format("%c",i+'0');
  3031. classResult=classResult+tempstr;
  3032. t=1;
  3033. }
  3034. else
  3035. {
  3036. tempstr.Format("%c",i+'A'-10);
  3037. classResult=classResult+tempstr;
  3038. t=1;
  3039. }
  3040. // tempstr.Format("%c",i);
  3041. }
  3042. }
  3043. if(t!=1)
  3044. classResult=classResult+'?';
  3045. }
  3046. if (recgpos>3&&recgpos<8)
  3047. {
  3048. double temp[13];
  3049. double result1[10];
  3050. bool t=0;
  3051. for (i=0;i<13;i++)
  3052. {
  3053. temp[i]=digitTest.feature[i]/15;
  3054. }
  3055. char_num_bp.Identify(temp,13,result1,10);
  3056. for(i=0;i<10;i++)
  3057. {
  3058. if (ABS(result1[i]-1)<0.1)
  3059. {
  3060. tempstr.Format("%c",i+'0');
  3061. classResult=classResult+tempstr;
  3062. t=1;
  3063. }
  3064. }
  3065. if(t!=1)
  3066. classResult=classResult+'?';
  3067. }
  3068. // strInfo += "nr识别结果为:  ";
  3069. // strInfo += classResult;
  3070. recgpos++;
  3071. // pchview->m_result.SetSel(0,-1);
  3072. //    pchview->m_result.ReplaceSel(strInfo);
  3073. }
  3074. strInfo += "nr识别结果为:  ";
  3075.     strInfo += classResult;
  3076. pchview->m_result.SetSel(0,-1);
  3077. pchview->m_result.ReplaceSel(strInfo);
  3078. }
  3079. void CDipView::OnTrainfromvehicle() 
  3080. {
  3081. OnLocate();
  3082. OnVSplit();
  3083. CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent(); 
  3084. CCharView* pchview=(CCharView*)MainFrame->m_wndSplitter.GetPane(0,1); 
  3085. CDigitClass digitTrain;
  3086. CRecvChar dlg;
  3087. CString m_class;
  3088. for(int k=0;k<CharacterNum;k++)
  3089. {
  3090. for(int x=0;x<cDatas[k].h;x++)
  3091. {
  3092. for(int y=0;y<cDatas[k].w;y++)
  3093. {
  3094. digitTrain.digitarray[y][x]=cDatas[k].Img[x*cDatas[k].w+y];
  3095. }
  3096. }
  3097. digitTrain.digitHeight=cDatas[k].h;
  3098. digitTrain.digitWidth=cDatas[k].w;
  3099. digitTrain.FixSize();
  3100. digitTrain.BinaryDigit();
  3101. digitTrain.ThinDigit_1();
  3102. pchview->m_result.SetSel(0,-1);
  3103. pchview->m_result.ReplaceSel("");
  3104. CString strInfo, strTemp;
  3105. strInfo.Format("");
  3106. int i,j;
  3107. for(i=0; i<digitTrain.digitHeight; i++)
  3108. {
  3109. for(j=0; j<digitTrain.digitWidth; j++)
  3110. {
  3111. if(digitTrain.digitarray[j][i] == 1)
  3112. strInfo += "■";
  3113. else
  3114. strInfo += "  ";
  3115. }
  3116. strInfo += "rn";
  3117. }
  3118. pchview->m_result.SetSel(0,-1);
  3119. pchview->m_result.ReplaceSel(strInfo);
  3120. if(dlg.DoModal()==IDOK)
  3121. {
  3122. m_class=dlg.m_char;
  3123. m_class.TrimLeft();
  3124. m_class.TrimRight();
  3125. digitTrain.GetFeature();
  3126. Sample temp;
  3127. for(i=0; i<13; i++)
  3128. temp.feature[i] = digitTrain.feature[i];
  3129. memcpy(temp.trueClass,(const char*) m_class,3*sizeof(char));
  3130. if(temp.trueClass[1]=='')
  3131. {
  3132. if (temp.trueClass[0]>='0'&&temp.trueClass[0]<='9')
  3133. {
  3134. temp.serialnum=numList.GetCount();
  3135. numList.AddTail(temp);
  3136. }
  3137. if (temp.trueClass[0]>='A'&&temp.trueClass[0]<='Z')
  3138. {
  3139. temp.serialnum=charList.GetCount();
  3140. charList.AddTail(temp);
  3141. }
  3142. }
  3143. else if(temp.trueClass[2]=='')
  3144. {
  3145. temp.serialnum=hanList.GetCount();
  3146. hanList.AddTail(temp);
  3147. }
  3148. }
  3149. }
  3150. }
  3151. void CDipView::OnSave() 
  3152. {
  3153. CFile char_file,num_file,han_file;
  3154. if(char_file.Open(".\chdata.ch",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  3155. {
  3156. AfxMessageBox("打开字符文件失败");
  3157. }
  3158. try
  3159. {
  3160. Sample sampleTemp;
  3161. char_file.SeekToEnd();
  3162. if(char_ConnectPos!=NULL)
  3163. {
  3164. while(char_ConnectPos!=NULL)
  3165. {
  3166. sampleTemp=charList.GetNext(char_ConnectPos);
  3167. char_file.Write(&sampleTemp, sizeof(sample));
  3168. }
  3169. char_ConnectPos=charList.GetTailPosition();
  3170. }
  3171. else
  3172. {
  3173. // Sample sampleTemp;
  3174. POSITION pos=charList.GetHeadPosition();
  3175. while(pos!=NULL)
  3176. {
  3177. sampleTemp=charList.GetNext(pos);
  3178. char_file.Write(&sampleTemp, sizeof(sample));
  3179. }
  3180. char_ConnectPos=charList.GetTailPosition();
  3181. }
  3182. }
  3183. catch(CFileException *e){
  3184. //Alert user to error
  3185. e->Delete();
  3186. }//end try-catch
  3187. char_file.Close();
  3188. if(num_file.Open(".\numdata.num",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  3189. {
  3190. AfxMessageBox("打开数字文件失败");
  3191. }
  3192. try
  3193. {
  3194. Sample sampleTemp;
  3195. num_file.SeekToEnd();
  3196. if(num_ConnectPos!=NULL)
  3197. {
  3198. while(num_ConnectPos!=NULL)
  3199. {
  3200. sampleTemp=numList.GetNext(num_ConnectPos);
  3201. num_file.Write(&sampleTemp, sizeof(sample));
  3202. }
  3203. num_ConnectPos=numList.GetTailPosition();
  3204. }
  3205. else
  3206. {
  3207. // Sample sampleTemp;
  3208. POSITION pos=numList.GetHeadPosition();
  3209. while(pos!=NULL)
  3210. {
  3211. sampleTemp=numList.GetNext(pos);
  3212. num_file.Write(&sampleTemp, sizeof(sample));
  3213. }
  3214. num_ConnectPos=numList.GetTailPosition();
  3215. }
  3216. }
  3217. catch(CFileException *e){
  3218. //Alert user to error
  3219. e->Delete();
  3220. }//end try-catch
  3221. num_file.Close();
  3222. if(han_file.Open(".\handata.han",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  3223. {
  3224. AfxMessageBox("打开汉字文件失败");
  3225. }
  3226. try
  3227. {
  3228. Sample sampleTemp;
  3229. han_file.SeekToEnd();
  3230. if(han_ConnectPos!=NULL)
  3231. {
  3232. while(han_ConnectPos!=NULL)
  3233. {
  3234. sampleTemp=hanList.GetNext(han_ConnectPos);
  3235. han_file.Write(&sampleTemp, sizeof(sample));
  3236. }
  3237. han_ConnectPos=hanList.GetTailPosition();
  3238. }
  3239. else
  3240. {
  3241. // Sample sampleTemp;
  3242. POSITION pos=hanList.GetHeadPosition();
  3243. while(pos!=NULL)
  3244. {
  3245. sampleTemp=hanList.GetNext(pos);
  3246. han_file.Write(&sampleTemp, sizeof(sample));
  3247. }
  3248. han_ConnectPos=hanList.GetTailPosition();
  3249. }
  3250. }
  3251. catch(CFileException *e){
  3252. //Alert user to error
  3253. e->Delete();
  3254. }//end try-catch
  3255. han_file.Close();
  3256. }
  3257. void CDipView::OnLoad() 
  3258. {
  3259. if (charList.GetCount()!=0||numList.GetCount()!=0||hanList.GetCount()!=0)
  3260. {
  3261. int nReturn;
  3262. nReturn=
  3263. AfxMessageBox("训练样本不为空,现在读取会覆盖这些样本,确认覆盖吗?",MB_YESNO);
  3264. if(nReturn==IDNO)
  3265. return;
  3266. }
  3267. charList.RemoveAll();
  3268. numList.RemoveAll();
  3269. hanList.RemoveAll();
  3270. CFile char_file,num_file,han_file;
  3271. if(char_file.Open(".\chdata.ch",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  3272. {
  3273. AfxMessageBox("打开字符文件失败,您最好退出程序");
  3274. }
  3275. try
  3276. {
  3277. Sample sampleTemp;
  3278. char_file.SeekToBegin();
  3279. DWORD dwBytesRemaining=char_file.GetLength();
  3280. while(dwBytesRemaining)
  3281. {
  3282. UINT nBytesRead=char_file.Read(&sampleTemp,sizeof(sample));
  3283. charList.AddTail(sampleTemp);
  3284. dwBytesRemaining-=nBytesRead;
  3285. }
  3286. CString s;
  3287. s.Format("共读取字符数据%d个",charList.GetCount());
  3288. AfxMessageBox(s);
  3289. }
  3290. catch(CFileException *e){
  3291. e->ReportError();
  3292. e->Delete();
  3293. }
  3294. char_file.Close();
  3295. char_ConnectPos=charList.GetTailPosition();
  3296. if(num_file.Open(".\numdata.num",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  3297. {
  3298. AfxMessageBox("打开数字文件失败,您最好退出程序");
  3299. }
  3300. try
  3301. {
  3302. Sample sampleTemp;
  3303. num_file.SeekToBegin();
  3304. DWORD dwBytesRemaining=num_file.GetLength();
  3305. while(dwBytesRemaining)
  3306. {
  3307. UINT nBytesRead=num_file.Read(&sampleTemp,sizeof(sample));
  3308. numList.AddTail(sampleTemp);
  3309. dwBytesRemaining-=nBytesRead;
  3310. }
  3311. CString s;
  3312. s.Format("共读取数字数据%d个",numList.GetCount());
  3313. AfxMessageBox(s);
  3314. }
  3315. catch(CFileException *e){
  3316. e->ReportError();
  3317. e->Delete();
  3318. }
  3319. num_file.Close();
  3320. num_ConnectPos=numList.GetTailPosition();
  3321. if(han_file.Open(".\handata.han",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  3322. {
  3323. AfxMessageBox("打开汉字文件失败,您最好退出程序");
  3324. }
  3325. try
  3326. {
  3327. Sample sampleTemp;
  3328. han_file.SeekToBegin();
  3329. DWORD dwBytesRemaining=han_file.GetLength();
  3330. while(dwBytesRemaining)
  3331. {
  3332. UINT nBytesRead=han_file.Read(&sampleTemp,sizeof(sample));
  3333. hanList.AddTail(sampleTemp);
  3334. dwBytesRemaining-=nBytesRead;
  3335. }
  3336. CString s;
  3337. s.Format("共读取汉字数据%d个",hanList.GetCount());
  3338. AfxMessageBox(s);
  3339. }
  3340. catch(CFileException *e){
  3341. e->ReportError();
  3342. e->Delete();
  3343. }
  3344. han_file.Close();
  3345. han_ConnectPos=hanList.GetTailPosition();
  3346. }
  3347. void CDipView::OnChange() 
  3348. {
  3349. CFile cf;
  3350. if(cf.Open(".\mydata.dat",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0)
  3351. {
  3352. AfxMessageBox("打开文件失败,n您最好退出程序");
  3353. }
  3354. try
  3355. {
  3356. Sample sampleTemp;
  3357. cf.SeekToBegin();
  3358. DWORD dwBytesRemaining=cf.GetLength();
  3359. while(dwBytesRemaining)
  3360. {
  3361. UINT nBytesRead=cf.Read(&sampleTemp,sizeof(sample));
  3362. if(sampleTemp.trueClass[1]=='')
  3363. {
  3364. if (sampleTemp.trueClass[0]>='0'&&sampleTemp.trueClass[0]<='9')
  3365. {
  3366. numList.AddTail(sampleTemp);
  3367. }
  3368. if (sampleTemp.trueClass[0]>='A'&&sampleTemp.trueClass[0]<='Z')
  3369. {
  3370. sampleTemp.serialnum=sampleTemp.serialnum-32;
  3371. charList.AddTail(sampleTemp);
  3372. }
  3373. }
  3374. else if(sampleTemp.trueClass[2]=='')
  3375. {
  3376. sampleTemp.serialnum=sampleTemp.serialnum-48;
  3377. hanList.AddTail(sampleTemp);
  3378. }
  3379. dwBytesRemaining-=nBytesRead;
  3380. }
  3381. // CString s;
  3382. // s.Format("共读取数据%d个,最后一个的序列号为%d",
  3383. // TemplateList.GetCount(),sampleTemp.serialnum);
  3384. // AfxMessageBox(s);
  3385. }
  3386. catch(CFileException *e){
  3387. e->ReportError();
  3388. e->Delete();
  3389. }
  3390. cf.Close();
  3391. }
  3392. void CDipView::OnTrain() 
  3393. {
  3394. Sample temp;
  3395. Sample sa;
  3396. double target[36];
  3397. POSITION pos;
  3398. m_pdlg=new CTraining;
  3399. m_pdlg->Create(IDD_TRAINING);
  3400. m_pdlg->m_progress.SetRange32(0,2000);
  3401. m_pdlg->ShowWindow(SW_SHOW);
  3402. for (int num=0;num<2000;num++)
  3403. {
  3404. pos=charList.GetHeadPosition();
  3405. while(pos!=NULL)
  3406. {
  3407. temp=charList.GetNext(pos);
  3408. for(int i=0; i<13; i++)
  3409. sa.feature[i] = temp.feature[i]/15;
  3410. double eo=1,eh=1;
  3411. if(temp.trueClass[1]=='')
  3412. {
  3413. memset(target,0,36*sizeof(double));
  3414. target[map(&temp.trueClass[0])-10]=1;
  3415. char_bp.Train(sa.feature,13,target,26,&eo,&eh);
  3416. }
  3417. }
  3418. m_pdlg->m_output.SetWindowText("正在训练字母网络,请稍候……");
  3419. m_pdlg->m_progress.SetPos(num);
  3420. }
  3421. // bp.Save("bp.dat");
  3422. for (num=0;num<2000;num++)
  3423. {
  3424. pos=numList.GetHeadPosition();
  3425. while(pos!=NULL)
  3426. {
  3427. temp=numList.GetNext(pos);
  3428. for(int i=0; i<13; i++)
  3429. sa.feature[i] = temp.feature[i]/15;
  3430. double eo=1,eh=1;
  3431. if(temp.trueClass[1]=='')
  3432. {
  3433. memset(target,0,36*sizeof(double));
  3434. target[map(&temp.trueClass[0])]=1;
  3435. num_bp.Train(sa.feature,13,target,10,&eo,&eh);
  3436. }
  3437. }
  3438. m_pdlg->m_output.SetWindowText("正在训练数字网络,请稍候……");
  3439. m_pdlg->m_progress.SetPos(num);
  3440. }
  3441. // bp.Save("bp.dat");
  3442. for (num=0;num<2000;num++)
  3443. {
  3444. pos=charList.GetHeadPosition();
  3445. while(pos!=NULL)
  3446. {
  3447. temp=charList.GetNext(pos);
  3448. for(int i=0; i<13; i++)
  3449. sa.feature[i] = temp.feature[i]/15;
  3450. double eo=1,eh=1;
  3451. if(temp.trueClass[1]=='')
  3452. {
  3453. memset(target,0,36*sizeof(double));
  3454. target[map(&temp.trueClass[0])]=1;
  3455. char_num_bp.Train(sa.feature,13,target,36,&eo,&eh);
  3456. }
  3457. }
  3458. pos=numList.GetHeadPosition();
  3459. while(pos!=NULL)
  3460. {
  3461. temp=numList.GetNext(pos);
  3462. for(int i=0; i<13; i++)
  3463. sa.feature[i] = temp.feature[i]/15;
  3464. double eo=1,eh=1;
  3465. if(temp.trueClass[1]=='')
  3466. {
  3467. memset(target,0,36*sizeof(double));
  3468. target[map(&temp.trueClass[0])]=1;
  3469. char_num_bp.Train(sa.feature,13,target,36,&eo,&eh);
  3470. }
  3471. }
  3472. m_pdlg->m_output.SetWindowText("正在训练字母、数字网络,请稍候……");
  3473. m_pdlg->m_progress.SetPos(num);
  3474. }
  3475. // bp.Save("bp.dat");
  3476. m_pdlg->DestroyWindow();
  3477. }
  3478. int CDipView::map(char *character)
  3479. {
  3480. if(*character>='0'&&*character<='9')
  3481. return *character-'0';
  3482. if(*character>='A'&&*character<='Z')
  3483. return *character-'A'+10;
  3484. }
  3485. void CDipView::OnSavebp() 
  3486. {
  3487. char_bp.Save(".\char.bp");
  3488. num_bp.Save(".\num.bp");
  3489. char_num_bp.Save(".\char_num.bp");
  3490. }
  3491. void CDipView::OnReadbp() 
  3492. {
  3493. char_bp.Read(".\char.bp");
  3494. num_bp.Read(".\num.bp");
  3495. char_num_bp.Read(".\char_num.bp");
  3496. }