getcharDlg.cpp
上传用户:kennygump
上传日期:2022-07-22
资源大小:347k
文件大小:12k
源码类别:

图形/文字识别

开发平台:

Visual C++

  1. // getcharDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "getchar.h"
  5. #include "getcharDlg.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. /////////////////////////////////////////////////////////////////////////////
  16. // CGetcharDlg dialog
  17. CGetcharDlg::CGetcharDlg(CWnd* pParent /*=NULL*/)
  18. : CDialog(CGetcharDlg::IDD, pParent)
  19. {
  20. //{{AFX_DATA_INIT(CGetcharDlg)
  21. // NOTE: the ClassWizard will add member initialization here
  22. //}}AFX_DATA_INIT
  23. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  24. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  25. }
  26. void CGetcharDlg::DoDataExchange(CDataExchange* pDX)
  27. {
  28. CDialog::DoDataExchange(pDX);
  29. //{{AFX_DATA_MAP(CGetcharDlg)
  30. // NOTE: the ClassWizard will add DDX and DDV calls here
  31. //}}AFX_DATA_MAP
  32. }
  33. BEGIN_MESSAGE_MAP(CGetcharDlg, CDialog)
  34. //{{AFX_MSG_MAP(CGetcharDlg)
  35. ON_WM_PAINT()
  36. ON_WM_QUERYDRAGICON()
  37. ON_BN_CLICKED(IDC_BTNOPENBMP, OnBtnopenbmp)
  38. ON_BN_CLICKED(IDC_BTNRELOAD, OnBtnreload)
  39. ON_BN_CLICKED(IDC_BTN_ALL, OnBtnAll)
  40. ON_BN_CLICKED(IDC_ImgprcAll, OnImgprcAll)
  41. ON_BN_CLICKED(IDC_IMGPRC256ToGray, OnIMGPRC256ToGray)
  42. ON_BN_CLICKED(IDC_IMGPRCGrayToWhiteBlack, OnIMGPRCGrayToWhiteBlack)
  43. ON_BN_CLICKED(IDC_InputGuiyihuaInfo, OnInputGuiyihuaInfo)
  44. ON_BN_CLICKED(IDC_BpnetTrain, OnBpnetTrain)
  45. ON_BN_CLICKED(IDC_BpnetRecognize, OnBpnetRecognize)
  46. ON_BN_CLICKED(IDC_ImgprcSharp, OnImgprcSharp)
  47. ON_BN_CLICKED(IDC_ImgprcRemoveNoise, OnImgprcRemoveNoise)
  48. ON_BN_CLICKED(IDC_ImgprcAdjustSlope, OnImgprcAdjustSlope)
  49. ON_BN_CLICKED(IDC_ImgprcDivide, OnImgprcDivide)
  50. ON_BN_CLICKED(IDC_ImgprcStandarize, OnImgprcStandarize)
  51. ON_BN_CLICKED(IDC_ImgprcShrinkAlign, OnImgprcShrinkAlign)
  52. //}}AFX_MSG_MAP
  53. END_MESSAGE_MAP()
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CGetcharDlg message handlers
  56. BOOL CGetcharDlg::OnInitDialog()
  57. {
  58. CDialog::OnInitDialog();
  59. // Set the icon for this dialog.  The framework does this automatically
  60. //  when the application's main window is not a dialog
  61. SetIcon(m_hIcon, TRUE); // Set big icon
  62. SetIcon(m_hIcon, FALSE); // Set small icon
  63. // TODO: Add extra initialization here
  64. return TRUE;  // return TRUE  unless you set the focus to a control
  65. }
  66. // If you add a minimize button to your dialog, you will need the code below
  67. //  to draw the icon.  For MFC applications using the document/view model,
  68. //  this is automatically done for you by the framework.
  69. void CGetcharDlg::OnPaint() 
  70. {
  71. if (IsIconic())
  72. {
  73. CPaintDC dc(this); // device context for painting
  74. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  75. // Center icon in client rectangle
  76. int cxIcon = GetSystemMetrics(SM_CXICON);
  77. int cyIcon = GetSystemMetrics(SM_CYICON);
  78. CRect rect;
  79. GetClientRect(&rect);
  80. int x = (rect.Width() - cxIcon + 1) / 2;
  81. int y = (rect.Height() - cyIcon + 1) / 2;
  82. // Draw the icon
  83. dc.DrawIcon(x, y, m_hIcon);
  84. }
  85. else
  86. {
  87. CDialog::OnPaint();
  88. }
  89. }
  90. // The system calls this to obtain the cursor to display while the user drags
  91. //  the minimized window.
  92. HCURSOR CGetcharDlg::OnQueryDragIcon()
  93. {
  94. return (HCURSOR) m_hIcon;
  95. }
  96. void CGetcharDlg::OnBtnopenbmp() 
  97. {
  98. // TODO: Add your control notification handler code here
  99. //创建一个打开文件对话框,并返回完整的文件路径
  100. static char BASED_CODE szFilter[] = "256色位图文件(*.bmp)|";
  101. CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL);
  102.     if(dlg.DoModal() == IDOK)
  103.    strPathName = dlg.GetPathName();
  104. else return;
  105. //创建一个文件对象
  106.     CFile file;
  107. //以只读模式打开文件
  108. file.Open (strPathName,CFile::modeRead);
  109. //读取文件到HDIB句柄中. 注意:此时只是读取位图文件中文件头之后的部分,不含文件头
  110. m_hDIB=::ReadDIBFile (file);
  111. //HDIB句柄: 就是一块存储位图数据的内存区域的地址
  112. //HDIB句柄包含:位图信息头、调色板(如果有的话)、DIB图像数据
  113. //关闭文件
  114. file.Close ();
  115. //指向DIB的指针(指向位图信息头)
  116. BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)m_hDIB);
  117. // 获取DIB中颜色表中的颜色数目
  118. WORD wNumColors;
  119. wNumColors = ::DIBNumColors((char*)lpDIB);
  120. // 判断是否是256色位图
  121. if (wNumColors != 256)
  122. {
  123. // 提示用户
  124. MessageBox("非256色位图!", "系统提示" , MB_ICONINFORMATION | MB_OK);
  125. // 解除锁定
  126. ::GlobalUnlock((HGLOBAL)m_hDIB);
  127. // 返回
  128. return;
  129. }
  130. //在屏幕上显示位图
  131. CDC* pDC=GetDC();
  132. DisplayDIB(pDC,m_hDIB);
  133. //更改位图文件是否已加载的标志
  134. fileloaded=true;
  135.     //gyhinfoinput=false;
  136. gyhfinished=false;
  137. }
  138. void CGetcharDlg::OnBtnreload() 
  139. {
  140. // TODO: Add your control notification handler code here
  141. //判断位图文件是否已加载。如果尚未加载,则弹出文件打开对话框
  142. if(fileloaded==false)
  143. {
  144. OnBtnopenbmp();
  145. if(fileloaded==false)
  146. return;
  147. }
  148. //创建一个文件对象
  149.     CFile file;
  150. //以只读模式打开文件
  151. file.Open (strPathName,CFile::modeReadWrite);
  152. m_hDIB=::ReadDIBFile (file);
  153. //关闭文件
  154. file.Close ();
  155. //在屏幕上显示位图
  156. CDC* pDC=GetDC();
  157. DisplayDIB(pDC,m_hDIB);
  158. }
  159. //一次性预处理
  160. void CGetcharDlg::OnImgprcAll() 
  161. {
  162. // TODO: Add your control notification handler code here
  163. if(fileloaded==false)
  164. {
  165. if(::AfxMessageBox ("请先打开一个图像文件再进行此操作!",MB_YESNO|MB_ICONSTOP)==IDNO)
  166.    return;
  167. }
  168. //打开文件
  169. OnBtnreload();
  170. //判断用户是否已输入归一化高度和宽度信息
  171. if(gyhinfoinput==false) OnInputGuiyihuaInfo();
  172. //将256色图转换为灰度图
  173. OnIMGPRC256ToGray();
  174. //将灰度图二值化
  175. OnIMGPRCGrayToWhiteBlack();
  176. //梯度锐化
  177. //OnImgprcSharp();
  178. //去除离散杂点噪声
  179. OnImgprcRemoveNoise();
  180. //调整数字字符的整体倾斜
  181. OnImgprcAdjustSlope();
  182. //分割并画框标识
  183. OnImgprcDivide();
  184. //将分割后的数字字符宽、高标准化,以便于下一步与BP网络的输入兼容
  185. OnImgprcStandarize();
  186. ConvertGrayToWhiteBlack(m_hDIB);
  187. //紧缩重排数字字符
  188. OnImgprcShrinkAlign();
  189. //分别保存这些已经经过分割、标准后的单个的数字字符到bmp文件,以便后续过程使用
  190. //OnImgprcToDibAndSave();
  191. //OnPreprocThin();
  192. }
  193. //图像预处理第1步:将256色图像转化为灰度图像
  194. void CGetcharDlg::OnIMGPRC256ToGray() 
  195. {
  196. // TODO: Add your control notification handler code here
  197. Convert256toGray(m_hDIB);
  198. //在屏幕上显示位图
  199. CDC* pDC=GetDC();
  200. DisplayDIB(pDC,m_hDIB);
  201. }
  202. //图像预处理第2步:将灰度图二值化
  203. void CGetcharDlg::OnIMGPRCGrayToWhiteBlack() 
  204. {
  205. // TODO: Add your control notification handler code here
  206. ConvertGrayToWhiteBlack(m_hDIB);
  207. //在屏幕上显示位图
  208. CDC* pDC=GetDC();
  209. DisplayDIB(pDC,m_hDIB);
  210. }
  211. //图像预处理第3步:梯度锐化
  212. void CGetcharDlg::OnImgprcSharp() 
  213. {
  214. // TODO: Add your control notification handler code here
  215. GradientSharp(m_hDIB);
  216. //在屏幕上显示位图
  217. CDC* pDC=GetDC();
  218. DisplayDIB(pDC,m_hDIB);
  219. }
  220. //图像预处理第4步:去离散杂点噪声
  221. void CGetcharDlg::OnImgprcRemoveNoise() 
  222. {
  223. // TODO: Add your control notification handler code here
  224. RemoveScatterNoise(m_hDIB);
  225. //在屏幕上显示位图
  226. CDC* pDC=GetDC();
  227. DisplayDIB(pDC,m_hDIB);
  228. }
  229. //图像预处理第5步:倾斜度调整
  230. void CGetcharDlg::OnImgprcAdjustSlope() 
  231. {
  232. // TODO: Add your control notification handler code here
  233. SlopeAdjust(m_hDIB);
  234. //在屏幕上显示位图
  235. CDC* pDC=GetDC();
  236. DisplayDIB(pDC,m_hDIB);
  237. }
  238. //图像预处理第6步:分割,并在分割出来的字符外面画框以标识
  239. void CGetcharDlg::OnImgprcDivide() 
  240. {
  241. // TODO: Add your control notification handler code here
  242. m_charRect=CharSegment(m_hDIB);
  243. //在屏幕上显示位图
  244. CDC* pDC=GetDC();
  245. DisplayDIB(pDC,m_hDIB);
  246. DrawFrame(pDC,m_hDIB,m_charRect,2,RGB(20,60,200));
  247. }
  248. //图像预处理第7步:标准归一化
  249. //将分割出来的各个不同宽、高的数字字符宽、高统一
  250. void CGetcharDlg::OnImgprcStandarize() 
  251. {
  252. // TODO: Add your control notification handler code here
  253. StdDIBbyRect(m_hDIB,w_sample,h_sample);
  254. //在屏幕上显示位图
  255. CDC* pDC=GetDC();
  256. DisplayDIB(pDC,m_hDIB);
  257. DrawFrame(pDC,m_hDIB,m_charRect,2,RGB(21,255,25));
  258. gyhfinished=true;
  259. }
  260. //图像预处理第8步:紧缩重排已经分割完毕的数字字符,并形成新的位图句柄
  261. void CGetcharDlg::OnImgprcShrinkAlign() 
  262. {
  263. // TODO: Add your control notification handler code here
  264. m_hDIB=AutoAlign(m_hDIB);
  265. //在屏幕上显示位图
  266. CDC* pDC=GetDC();
  267. DisplayDIB(pDC,m_hDIB);
  268. DrawFrame(pDC,m_hDIB,m_charRect,1,RGB(252,115,27));
  269. }
  270. void CGetcharDlg::OnInputGuiyihuaInfo() 
  271. {
  272. // TODO: Add your control notification handler code here
  273. CINPUT1 input;
  274. input.w =8;
  275. input.h =16;
  276. if(input.DoModal ()!=IDOK) return;
  277. w_sample=input.w;
  278. h_sample=input.h;
  279. gyhinfoinput=true;
  280. }
  281. void CGetcharDlg::OnBpnetTrain() 
  282. {
  283. // TODO: Add your control notification handler code here
  284. OnImgprcAll();
  285. //判断是否经过了归一划的处理
  286. if(gyhfinished==false)
  287. {
  288. //如果没有进行提示错误并返回
  289. ::MessageBox(NULL,"没有进行归一划预处理",NULL,MB_ICONSTOP);
  290. return;
  291. }
  292. //建立BP网络训练参数对话框
  293. CDBpParamater BpPa;
  294. //初始化变量
  295. BpPa.m_a=0;
  296. BpPa.m_eta=0.015;
  297. BpPa.m_ex=0.001;
  298. BpPa.m_hn=10;
  299. // 显示对话框
  300. if(BpPa.DoModal()!=IDOK)
  301. {
  302. //返回
  303. return;
  304. }
  305. //用户获得参数信息
  306. //相关系数
  307. double  momentum=BpPa.m_a; 
  308. //最小均方误差
  309. double  min_ex=BpPa.m_ex; 
  310. //隐层数目
  311. int  n_hidden=BpPa.m_hn; 
  312. //训练步长
  313. double eta=BpPa.m_eta;
  314. //获得指向DIB的指针
  315. BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) m_hDIB);
  316. //获得指向DIB象素的指针,并指向象素的起始位置
  317. BYTE *lpDIBBits =(BYTE*)::FindDIBBits((char *)lpDIB);
  318. //获得颜色信息
  319. int numColors=(int) ::DIBNumColors((char *)lpDIB);
  320. //不是灰度图返回
  321.     if (numColors!=256) 
  322. {
  323. ::GlobalUnlock((HGLOBAL) m_hDIB);
  324. ::MessageBox(NULL,"只能处理灰度图像",NULL,MB_ICONSTOP);
  325. return;
  326. }
  327. //获取图像的宽度
  328.     LONG lWidth = (LONG) ::DIBWidth((char *)lpDIB); 
  329. //获取图像的高度
  330. LONG lHeight = (LONG) ::DIBHeight((char *)lpDIB);
  331. //计算图像每行的字节数
  332. LONG lLineByte = (lWidth+3)/4*4; 
  333. //归一化的宽度
  334. LONG lSwidth = w_sample;
  335. //归一化的高度
  336. LONG LSheight = h_sample;
  337. //指向输入样本的特征向量的指针  
  338. double **data_in;
  339. //从输入的训练样本中提取特征向量
  340. data_in = code ( lpDIBBits, digicount,  lLineByte, lSwidth, LSheight);
  341. //计算输入层结点的数目
  342. int n_in = LSheight*lSwidth;
  343. double out[][4]={      
  344. 0.1,0.1,0.1,0.1,
  345. 0.1,0.1,0.1,0.9,
  346. 0.1,0.1,0.9,0.1,
  347. 0.1,0.1,0.9,0.9,
  348. 0.1,0.9,0.1,0.1,
  349. 0.1,0.9,0.1,0.9,
  350. 0.1,0.9,0.9,0.1,
  351. 0.1,0.9,0.9,0.9,
  352. 0.9,0.1,0.1,0.1,
  353. 0.9,0.1,0.1,0.9
  354. };
  355. double **data_out;
  356. data_out = alloc_2d_dbl(digicount,4);
  357. for(int i=0;i<digicount;i++)
  358. {
  359. for(int j=0;j<4;j++)
  360. data_out[i][j]=out[i%10][j];
  361. }
  362. BpTrain( data_in, data_out, n_in,n_hidden,min_ex,momentum,eta,digicount);
  363. ::GlobalUnlock(m_hDIB);
  364. CDC* pDC=GetDC();
  365. DisplayDIB(pDC,m_hDIB);
  366. }
  367. void CGetcharDlg::OnBpnetRecognize() 
  368. {
  369. // TODO: Add your control notification handler code here
  370. OnImgprcAll();
  371. //判断是否经过了归一划的处理
  372. if(gyhfinished==false)
  373. {
  374. //如果没有进行提示错误并返回
  375. ::MessageBox(NULL,"没有进行归一划预处理",NULL,MB_ICONSTOP);
  376. return;
  377. }
  378. //获得指向DIB的指针
  379. BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) m_hDIB);
  380. //获得指向DIB象素的指针,并指向象素的起始位置
  381. BYTE *lpDIBBits =(BYTE*)::FindDIBBits((char *)lpDIB);
  382. //获得颜色信息
  383. int numColors=(int) ::DIBNumColors((char *)lpDIB);
  384. //不是灰度图返回
  385.     if (numColors!=256) 
  386. {
  387. ::GlobalUnlock((HGLOBAL) m_hDIB);
  388. ::MessageBox(NULL,"只能处理256色图像",NULL,MB_ICONSTOP);
  389. return;
  390. }
  391. //获取图像的宽度
  392.     LONG lWidth = (LONG) ::DIBWidth((char *)lpDIB); 
  393. //获取图像的高度
  394. LONG lHeight = (LONG) ::DIBHeight((char *)lpDIB);
  395. //计算图像每行的字节数
  396. LONG lLineByte = (lWidth+3)/4*4; 
  397. //归一化的宽度
  398. LONG lSwidth = w_sample;
  399. //归一化的高度
  400. LONG LSheight = h_sample;
  401. // 读取结点信息
  402. int n[3];
  403. if(r_num(n,"num")==false)
  404. return;
  405. //获得输入层结点数目
  406. int  n_in=n[0];
  407. //获得隐层结点数目
  408. int  n_hidden=n[1];
  409. //获得输出层结点数目
  410. int  n_out=n[2];  
  411. //判断待识别样本的归一划信息是否与训练时相同
  412. if(n_in!=lSwidth*LSheight)
  413. {
  414. //如果不相同提示错误并返回
  415. ::MessageBox(NULL,"归一划尺寸与上一次训练时不一致",NULL,MB_ICONSTOP);
  416. return;
  417. }
  418. //指向输入样本的特征向量的指针  
  419. double **data_in;
  420. //从输入的训练样本中提取特征向量
  421. data_in = code ( lpDIBBits, digicount,  lLineByte, lSwidth, LSheight);
  422. //根据提取的特征进行样本识别
  423. CodeRecognize(data_in, digicount,n_in,n_hidden,n_out);
  424. ::GlobalUnlock(m_hDIB);
  425. CDC* pDC=GetDC();
  426. DisplayDIB(pDC,m_hDIB);
  427. }
  428. void CGetcharDlg::OnBtnAll() 
  429. {
  430. // TODO: Add your control notification handler code here
  431. CGetcharDlg::OnImgprcAll();
  432. }