ChildView.cpp
上传用户:zjyq009
上传日期:2022-07-10
资源大小:3154k
文件大小:14k
源码类别:

图形/文字识别

开发平台:

Visual C++

  1. // ChildView.cpp : implementation of the CChildView class
  2. //
  3. #include "stdafx.h"
  4. #include "DigitRec.h"
  5. #include "ChildView.h"
  6. #include "INPUT1.h"
  7. #include "mydiblib.h"
  8. #include "Bp.h"
  9. #include "DBpParamater.h"
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15. void ThiningDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CChildView
  18. CChildView::CChildView()
  19. {
  20. fileloaded=false;
  21. gyhinfoinput=false;
  22. gyhfinished=false;
  23. m_hDIB=NULL;
  24. }
  25. CChildView::~CChildView()
  26. {
  27. }
  28. BEGIN_MESSAGE_MAP(CChildView,CWnd )
  29. //{{AFX_MSG_MAP(CChildView)
  30. ON_WM_PAINT()
  31. ON_COMMAND(IDmy_FILE_OPEN_BMP, OnFileOpenBmp)
  32. ON_COMMAND(IDmy_FILE_SAVE_BMP, OnFileSaveBmp)
  33. ON_COMMAND(IDmy_IMGPRC_SHRINK_ALIGN, OnImgprcShrinkAlign)
  34. ON_COMMAND(IDmy_IMGPRC_ALL, OnImgprcAll)
  35. ON_COMMAND(IDmy_IMGPRC_256ToGray, OnIMGPRC256ToGray)
  36. ON_COMMAND(IDmy_IMGPRC_DIVIDE, OnImgprcDivide)
  37. ON_COMMAND(IDmy_IMGPRC_TO_DIB_AND_SAVE, OnImgprcToDibAndSave)
  38. ON_COMMAND(IDmy_IMGPRC_REMOVE_NOISE, OnImgprcRemoveNoise)
  39. ON_COMMAND(IDmy_IMGPRC_STANDARIZE, OnImgprcStandarize)
  40. ON_COMMAND(IDmy_IMGPRC_THINNING, OnImgprcThinning)
  41. ON_COMMAND(IDmy_IMGPRC_ADJUST_SLOPE, OnImgprcAdjustSlope)
  42. ON_COMMAND(IDmy_IMGPRC_GrayToWhiteBlack, OnIMGPRCGrayToWhiteBlack)
  43. ON_COMMAND(IDmy_IMGPRC_SHARP, OnImgprcSharp)
  44. ON_COMMAND(IDmy_FILE_RE_LOAD_BMP, OnFileReLoadBmp)
  45. ON_COMMAND(ID_INPUT1, OnInputGuiyihuaInfo)
  46. ON_COMMAND(IDmy_BPNET_TRAIN, OnBpnetTrain)
  47. ON_COMMAND(IDmy_BPNET_RECOGNIZE, OnBpnetRecognize)
  48. ON_COMMAND(ID_aver, Onaver)
  49. ON_COMMAND(ID_Gass, OnGass)
  50. ON_COMMAND(ID_Mid, OnMid)
  51. ON_COMMAND(IDmy_IMGPRC_EQUALIZE, OnImgprcEqualize)
  52. //}}AFX_MSG_MAP
  53. END_MESSAGE_MAP()
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CChildView message handlers
  56. BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
  57. {
  58. if (!CWnd::PreCreateWindow(cs))
  59. return FALSE;
  60. cs.dwExStyle |= WS_EX_CLIENTEDGE;
  61. cs.style &= ~WS_BORDER;
  62. cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
  63. ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);
  64. return TRUE;
  65. }
  66. void CChildView::OnPaint() 
  67. {
  68. CPaintDC dc(this); // device context for painting
  69. OnDraw(&dc);
  70. // Do not call CWnd::OnPaint() for painting messages
  71. }
  72. //打开256色位图文件
  73. void CChildView::OnFileOpenBmp() 
  74. {
  75. //创建一个打开文件对话框,并返回完整的文件路径
  76. static char BASED_CODE szFilter[] = "256色位图文件(*.bmp)|";
  77. CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL);
  78.     if(dlg.DoModal() == IDOK)
  79.    strPathName = dlg.GetPathName();
  80. else return;
  81. //创建一个文件对象
  82.     CFile file;
  83. //以只读模式打开文件
  84. file.Open (strPathName,CFile::modeRead);
  85. //读取文件到HDIB句柄中. 注意:此时只是读取位图文件中文件头之后的部分,不含文件头
  86. m_hDIB=::ReadDIBFile (file);
  87. //HDIB句柄: 就是一块存储位图数据的内存区域的地址
  88. //HDIB句柄包含:位图信息头、调色板(如果有的话)、DIB图像数据
  89. //关闭文件
  90. file.Close ();
  91. //指向DIB的指针(指向位图信息头)
  92. BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)m_hDIB);
  93. // 获取DIB中颜色表中的颜色数目
  94. WORD wNumColors;
  95. wNumColors = ::DIBNumColors((char*)lpDIB);
  96. // 判断是否是256色位图
  97. if (wNumColors != 256)
  98. {
  99. // 提示用户
  100. MessageBox("非256色位图!", "系统提示" , MB_ICONINFORMATION | MB_OK);
  101. // 解除锁定
  102. ::GlobalUnlock((HGLOBAL)m_hDIB);
  103. // 返回
  104. return;
  105. }
  106. //在屏幕上显示位图
  107. CDC* pDC=GetDC();
  108. DisplayDIB(pDC,m_hDIB);
  109. //更改位图文件是否已加载的标志
  110. fileloaded=true;
  111.     //gyhinfoinput=false;          //2004.4.26修改
  112. gyhfinished=false;
  113. }
  114. //取消一切更改,重新加载位图文件
  115. void CChildView::OnFileReLoadBmp() 
  116. {
  117. //判断位图文件是否已加载。如果尚未加载,则弹出文件打开对话框
  118. if(fileloaded==false)
  119. {
  120. OnFileOpenBmp();
  121. if(fileloaded==false)
  122. return;
  123. }
  124. //创建一个文件对象
  125.     CFile file;
  126. //以只读模式打开文件
  127. file.Open (strPathName,CFile::modeReadWrite);
  128. m_hDIB=::ReadDIBFile (file);
  129. //关闭文件
  130. file.Close ();
  131. //在屏幕上显示位图
  132. CDC* pDC=GetDC();
  133. DisplayDIB(pDC,m_hDIB);
  134. }
  135. void CChildView::OnFileSaveBmp() 
  136. {
  137. //创建一个保存文件对话框,并返回完整的文件路径
  138. static char BASED_CODE szFilter[] = "256色位图文件(*.bmp)|";
  139. CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL);
  140.     if(dlg.DoModal() == IDOK)
  141.    strPathNameSave = dlg.GetPathName();
  142. else return;
  143. //在文件名后添加.bmp后缀
  144. //strPathNameSave+=".bmp";
  145. //以读写模式打开一个文件。如果文件不存在,则创建之
  146.     CFile file(strPathNameSave, CFile::modeReadWrite|CFile::modeCreate);
  147. ::SaveDIB (m_hDIB,file);
  148. //关闭文件
  149. file.Close ();
  150. }
  151. //一次性预处理
  152. void CChildView::OnImgprcAll() 
  153. {
  154. if(fileloaded==false)
  155. {
  156. if(::AfxMessageBox ("请先打开一个图像文件再进行此操作!",MB_YESNO|MB_ICONSTOP)==IDNO)
  157.    return;
  158. }
  159. //打开文件
  160. OnFileReLoadBmp();
  161. //判断用户是否已输入归一化高度和宽度信息
  162. if(gyhinfoinput==false) OnInputGuiyihuaInfo();
  163. //将256色图转换为灰度图
  164. OnIMGPRC256ToGray();
  165. //将灰度图二值化
  166. OnIMGPRCGrayToWhiteBlack();
  167. //梯度锐化
  168. //OnImgprcSharp();
  169. //去除离散杂点噪声
  170. OnImgprcRemoveNoise();
  171. //调整数字字符的整体倾斜
  172. OnImgprcAdjustSlope();
  173. //分割并画框标识
  174. OnImgprcDivide();
  175. //将分割后的数字字符宽、高标准化,以便于下一步与BP网络的输入兼容
  176. OnImgprcStandarize();
  177. ConvertGrayToWhiteBlack(m_hDIB);
  178. //紧缩重排数字字符
  179. OnImgprcShrinkAlign();
  180. //分别保存这些已经经过分割、标准后的单个的数字字符到bmp文件,以便后续过程使用
  181. //OnImgprcToDibAndSave();
  182. //OnPreprocThin();
  183. }
  184. //图像预处理第1步:将256色图像转化为灰度图像
  185. void CChildView::OnIMGPRC256ToGray() 
  186. {
  187. Convert256toGray(m_hDIB);
  188. //在屏幕上显示位图
  189. CDC* pDC=GetDC();
  190. DisplayDIB(pDC,m_hDIB);
  191. }
  192. //图像预处理第2步:将灰度图二值化
  193. void CChildView::OnIMGPRCGrayToWhiteBlack()
  194. {
  195. ConvertGrayToWhiteBlack(m_hDIB);
  196. //在屏幕上显示位图
  197. CDC* pDC=GetDC();
  198. DisplayDIB(pDC,m_hDIB);
  199. }
  200. //图像预处理第3步:梯度锐化
  201. void CChildView::OnImgprcSharp() 
  202. {
  203. GradientSharp(m_hDIB);
  204. //在屏幕上显示位图
  205. CDC* pDC=GetDC();
  206. DisplayDIB(pDC,m_hDIB);
  207. }
  208. //图像预处理第4步:去离散杂点噪声
  209. void CChildView::OnImgprcRemoveNoise() 
  210. {
  211. RemoveScatterNoise(m_hDIB);
  212. //在屏幕上显示位图
  213. CDC* pDC=GetDC();
  214. DisplayDIB(pDC,m_hDIB);
  215. }
  216. //图像预处理第5步:倾斜度调整
  217. void CChildView::OnImgprcAdjustSlope() 
  218. {
  219.     SlopeAdjust(m_hDIB);
  220. //在屏幕上显示位图
  221. CDC* pDC=GetDC();
  222. DisplayDIB(pDC,m_hDIB);
  223. }
  224. //图像预处理第6步:分割,并在分割出来的字符外面画框以标识
  225. void CChildView::OnImgprcDivide() 
  226. {
  227. m_charRect=CharSegment(m_hDIB);
  228. //在屏幕上显示位图
  229. CDC* pDC=GetDC();
  230. DisplayDIB(pDC,m_hDIB);
  231. DrawFrame(pDC,m_hDIB,m_charRect,2,RGB(20,60,200));
  232. }
  233. //图像预处理第7步:标准归一化
  234. //将分割出来的各个不同宽、高的数字字符宽、高统一
  235. void CChildView::OnImgprcStandarize() 
  236. {
  237. StdDIBbyRect(m_hDIB,w_sample,h_sample);
  238. //在屏幕上显示位图
  239. CDC* pDC=GetDC();
  240. DisplayDIB(pDC,m_hDIB);
  241. DrawFrame(pDC,m_hDIB,m_charRect,2,RGB(21,255,25));
  242. gyhfinished=true;
  243. }
  244. //图像预处理第8步:紧缩重排已经分割完毕的数字字符,并形成新的位图句柄
  245. void CChildView::OnImgprcShrinkAlign() 
  246. {
  247. m_hDIB=AutoAlign(m_hDIB);
  248. //在屏幕上显示位图
  249. CDC* pDC=GetDC();
  250. DisplayDIB(pDC,m_hDIB);
  251. DrawFrame(pDC,m_hDIB,m_charRect,1,RGB(252,115,27));
  252. }
  253. //图像预处理第9步:将最终标准化后的字符图像分为单个单个的HDIB保存,并存为.bmp文件
  254. void CChildView::OnImgprcToDibAndSave() 
  255. {
  256. unsigned char* lpSrc;
  257. int w,h;
  258. w=m_charRect.front ().Width() ;
  259. h=m_charRect.front ().Height() ;
  260. m_dibRect.clear ();
  261. m_dibRectCopy.clear ();
  262. int i_src,j_src;
  263. int i,j;
  264. int counts=0;
  265. CRect rect,rectnew;
  266. BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)m_hDIB);
  267. BYTE* lpDIBBits=(BYTE*)::FindDIBBits ((char*)lpDIB);
  268. BYTE* lpNewDIBBits;
  269. BYTE* lpDst;
  270. LONG lLineBytes=(digicount*w+3)/4*4;
  271. LONG lLineBytesnew =(w+3)/4*4;
  272. HDIB hDIB=NULL;
  273. while(!m_charRect.empty ())
  274. {
  275. hDIB=::NewDIB (w,h,8);
  276. lpDIB=(BYTE*) ::GlobalLock((HGLOBAL)hDIB);
  277. lpNewDIBBits = (BYTE*)::FindDIBBits((char*)lpDIB);
  278. lpDst=(BYTE*)lpNewDIBBits;
  279. memset(lpDst,(BYTE)255,lLineBytesnew * h);
  280. rect=m_charRect.front ();
  281. m_charRect.pop_front ();
  282. for(i=0;i<h;i++)
  283. for(j=0;j<w;j++)
  284. {
  285. i_src=rect.top + i;
  286. j_src=j+counts*w;
  287. lpSrc=(BYTE *)lpDIBBits + lLineBytes *  i_src + j_src;
  288. lpDst=(BYTE *)lpNewDIBBits + lLineBytesnew * i + j;
  289. *lpDst=*lpSrc;
  290. }
  291. ::GlobalUnlock (hDIB);
  292. m_dibRect.push_back (hDIB);
  293. counts++;
  294. }
  295. m_charRect=m_charRectCopy;
  296. m_dibRectCopy=m_dibRect;
  297. //输出为.bmp文件
  298. CString str;
  299. counts=1;
  300. while(!m_dibRect.empty ())
  301. {
  302. str.Format ("part%d.bmp",counts);
  303. //str=strPath+"\"+str;
  304.     CFile file(str, CFile::modeReadWrite|CFile::modeCreate);
  305. hDIB=m_dibRect.front ();
  306. ::SaveDIB (hDIB,file);
  307. m_dibRect.pop_front ();
  308. file.Close ();
  309. counts++;
  310. }
  311. m_dibRect=m_dibRectCopy;
  312. }
  313. void CChildView::OnImgprcThinning() 
  314. {
  315.  Thinning(m_hDIB);
  316. //在屏幕上显示位图
  317. CDC* pDC=GetDC();
  318. DisplayDIB(pDC,m_hDIB);
  319. }
  320. void CChildView::OnInputGuiyihuaInfo() 
  321. {
  322. CINPUT1 input;
  323. input.w =8;
  324. input.h =16;
  325. if(input.DoModal ()!=IDOK) return;
  326. w_sample=input.w;
  327. h_sample=input.h;
  328. gyhinfoinput=true;
  329. }
  330. void CChildView::OnBpnetTrain() 
  331. {
  332. OnImgprcAll();
  333. //判断是否经过了归一划的处理
  334. if(gyhfinished==false)
  335. {
  336. //如果没有进行提示错误并返回
  337. ::MessageBox(NULL,"没有进行归一划预处理",NULL,MB_ICONSTOP);
  338. return;
  339. }
  340. //建立BP网络训练参数对话框
  341. CDBpParamater BpPa;
  342. //初始化变量
  343. BpPa.m_a=0;
  344. BpPa.m_eta=0.015;
  345. BpPa.m_ex=0.001;
  346. BpPa.m_hn=10;
  347. // 显示对话框
  348. if(BpPa.DoModal()!=IDOK)
  349. {
  350. //返回
  351. return;
  352. }
  353. //用户获得参数信息
  354. //相关系数
  355. double  momentum=BpPa.m_a; 
  356. //最小均方误差
  357. double  min_ex=BpPa.m_ex; 
  358. //隐层数目
  359. int  n_hidden=BpPa.m_hn; 
  360. //训练步长
  361. double eta=BpPa.m_eta;
  362. //获得指向DIB的指针
  363. BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) m_hDIB);
  364. //获得指向DIB象素的指针,并指向象素的起始位置
  365. BYTE *lpDIBBits =(BYTE*)::FindDIBBits((char *)lpDIB);
  366. //获得颜色信息
  367. int numColors=(int) ::DIBNumColors((char *)lpDIB);
  368. //不是灰度图返回
  369.     if (numColors!=256) 
  370. {
  371. ::GlobalUnlock((HGLOBAL) m_hDIB);
  372. ::MessageBox(NULL,"只能处理灰度图像",NULL,MB_ICONSTOP);
  373. return;
  374. }
  375. //获取图像的宽度
  376.     LONG lWidth = (LONG) ::DIBWidth((char *)lpDIB); 
  377. //获取图像的高度
  378. LONG lHeight = (LONG) ::DIBHeight((char *)lpDIB);
  379. //计算图像每行的字节数
  380. LONG lLineByte = (lWidth+3)/4*4; 
  381. //归一化的宽度
  382. LONG lSwidth = w_sample;
  383. //归一化的高度
  384. LONG LSheight = h_sample;
  385. //指向输入样本的特征向量的指针  
  386. double **data_in;
  387. //从输入的训练样本中提取特征向量
  388. data_in = code ( lpDIBBits, digicount,  lLineByte, lSwidth, LSheight);
  389. //计算输入层结点的数目
  390. int n_in = LSheight*lSwidth;
  391. double out[][4]={      0.1,0.1,0.1,0.1,
  392. 0.1,0.1,0.1,0.9,
  393. 0.1,0.1,0.9,0.1,
  394. 0.1,0.1,0.9,0.9,
  395. 0.1,0.9,0.1,0.1,
  396. 0.1,0.9,0.1,0.9,
  397. 0.1,0.9,0.9,0.1,
  398. 0.1,0.9,0.9,0.9,
  399. 0.9,0.1,0.1,0.1,
  400. 0.9,0.1,0.1,0.9};
  401. double **data_out;
  402. data_out = alloc_2d_dbl(digicount,4);
  403. for(int i=0;i<digicount;i++)
  404. {
  405. for(int j=0;j<4;j++)
  406. data_out[i][j]=out[i%10][j];
  407. }
  408. BpTrain( data_in, data_out, n_in,n_hidden,min_ex,momentum,eta,digicount);
  409. ::GlobalUnlock(m_hDIB);
  410. CDC* pDC=GetDC();
  411. DisplayDIB(pDC,m_hDIB);
  412. }
  413. void CChildView::OnBpnetRecognize() 
  414. {
  415. // TODO: Add your command handler code here
  416. OnImgprcAll();
  417. //判断是否经过了归一划的处理
  418. if(gyhfinished==false)
  419. {
  420. //如果没有进行提示错误并返回
  421. ::MessageBox(NULL,"没有进行归一划预处理",NULL,MB_ICONSTOP);
  422. return;
  423. }
  424. //获得指向DIB的指针
  425. BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) m_hDIB);
  426. //获得指向DIB象素的指针,并指向象素的起始位置
  427. BYTE *lpDIBBits =(BYTE*)::FindDIBBits((char *)lpDIB);
  428. //获得颜色信息
  429. int numColors=(int) ::DIBNumColors((char *)lpDIB);
  430. //不是灰度图返回
  431.     if (numColors!=256) 
  432. {
  433. ::GlobalUnlock((HGLOBAL) m_hDIB);
  434. ::MessageBox(NULL,"只能处理256色图像",NULL,MB_ICONSTOP);
  435. return;
  436. }
  437. //获取图像的宽度
  438.     LONG lWidth = (LONG) ::DIBWidth((char *)lpDIB); 
  439. //获取图像的高度
  440. LONG lHeight = (LONG) ::DIBHeight((char *)lpDIB);
  441. //计算图像每行的字节数
  442. LONG lLineByte = (lWidth+3)/4*4; 
  443. //归一化的宽度
  444. LONG lSwidth = w_sample;
  445. //归一化的高度
  446. LONG LSheight = h_sample;
  447. // 读取结点信息
  448. int n[3];
  449. if(r_num(n,"num")==false)
  450. return;
  451. //获得输入层结点数目
  452. int  n_in=n[0];
  453. //获得隐层结点数目
  454. int  n_hidden=n[1];
  455. //获得输出层结点数目
  456. int  n_out=n[2];  
  457. //判断待识别样本的归一划信息是否与训练时相同
  458. if(n_in!=lSwidth*LSheight)
  459. {
  460. //如果不相同提示错误并返回
  461. ::MessageBox(NULL,"归一划尺寸与上一次训练时不一致",NULL,MB_ICONSTOP);
  462. return;
  463. }
  464. //指向输入样本的特征向量的指针  
  465. double **data_in;
  466. //从输入的训练样本中提取特征向量
  467. data_in = code ( lpDIBBits, digicount,  lLineByte, lSwidth, LSheight);
  468. //根据提取的特征进行样本识别
  469. CodeRecognize(data_in, digicount,n_in,n_hidden,n_out);
  470. ::GlobalUnlock(m_hDIB);
  471. CDC* pDC=GetDC();
  472. DisplayDIB(pDC,m_hDIB);
  473. }
  474. void CChildView::OnDraw(CDC *pDC)
  475. {
  476. if(m_hDIB!=NULL) 
  477. DisplayDIB(pDC,m_hDIB);
  478. }
  479. void CChildView::Onaver() 
  480. {
  481. // TODO: Add your command handler code here
  482. //设定模板参数
  483. double tem[9]={1,1,1,
  484.            1,1,1,
  485.    1,1,1};
  486.     //设定模板系数
  487.     double  xishu = 0.111111;   
  488.     //进行模板操作
  489. m_hDIB =Template(m_hDIB,tem ,3,3, xishu);
  490. //显示图像
  491. CDC* pDC=GetDC();
  492. DisplayDIB(pDC,m_hDIB);
  493. }
  494. void CChildView::OnGass() 
  495. {
  496. // TODO: Add your command handler code here
  497.    
  498. //设定模板参数
  499. double tem[9]={1,2,1,
  500.            2,4,2,
  501.    1,2,1};
  502.     //设定模板系数
  503.     double  xishu = 0.0625;   
  504.     //进行模板操作
  505. m_hDIB =Template(m_hDIB,tem ,3,3, xishu);
  506. //显示图像
  507. CDC* pDC=GetDC();
  508. DisplayDIB(pDC,m_hDIB);
  509. }
  510. void CChildView::OnMid() 
  511. {
  512. // TODO: Add your command handler code here
  513. //进行中值滤波
  514. m_hDIB =MidFilter(m_hDIB,3,3);
  515. //显示图像
  516. CDC* pDC=GetDC();
  517. DisplayDIB(pDC,m_hDIB);
  518. }
  519. void CChildView::OnImgprcEqualize() 
  520. {
  521. Equalize(m_hDIB);
  522. //显示图像
  523. CDC* pDC=GetDC();
  524. DisplayDIB(pDC,m_hDIB);
  525. }