mymfcDlg.cpp
上传用户:wjt888999
上传日期:2022-08-11
资源大小:5225k
文件大小:16k
源码类别:

OpenCV

开发平台:

Visual C++

  1. // mymfcDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "mymfc.h"
  5. #include "mymfcDlg.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #endif
  9. // CAboutDlg dialog used for App About
  10. class CAboutDlg : public CDialog
  11. {
  12. public:
  13. CAboutDlg();
  14. // Dialog Data
  15. enum { IDD = IDD_ABOUTBOX };
  16. protected:
  17. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  18. // Implementation
  19. protected:
  20. DECLARE_MESSAGE_MAP()
  21. };
  22. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  23. {
  24. }
  25. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  26. {
  27. CDialog::DoDataExchange(pDX);
  28. }
  29. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  30. END_MESSAGE_MAP()
  31. // CmymfcDlg dialog
  32. CmymfcDlg::CmymfcDlg(CWnd* pParent /*=NULL*/)
  33. : CDialog(CmymfcDlg::IDD, pParent)
  34. , TheImage(NULL)
  35. , vPath(_T(""))
  36. , pCapture(NULL)
  37. , m_run(0)
  38. , mCamIndex(0)
  39. {
  40. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  41. }
  42. void CmymfcDlg::DoDataExchange(CDataExchange* pDX)
  43. {
  44. CDialog::DoDataExchange(pDX);
  45. DDX_Control(pDX, IDC_CamList, m_camList);
  46. }
  47. BEGIN_MESSAGE_MAP(CmymfcDlg, CDialog)
  48. ON_WM_SYSCOMMAND()
  49. ON_WM_PAINT()
  50. ON_WM_QUERYDRAGICON()
  51. //}}AFX_MSG_MAP
  52. ON_BN_CLICKED(IDC_ReadImg, &CmymfcDlg::OnBnClickedReadimg)
  53. ON_BN_CLICKED(IDC_EdgeDetect, &CmymfcDlg::OnBnClickedEdgedetect)
  54. ON_BN_CLICKED(IDC_ReadVideo, &CmymfcDlg::OnBnClickedReadvideo)
  55. ON_BN_CLICKED(IDC_Play, &CmymfcDlg::OnBnClickedPlayVideo)
  56. ON_CBN_SELCHANGE(IDC_CamList, &CmymfcDlg::OnCbnSelchangeCamlist)
  57. ON_BN_CLICKED(IDC_Pause, &CmymfcDlg::OnBnClickedPause)
  58. ON_BN_CLICKED(IDOK, &CmymfcDlg::OnBnClickedOk)
  59. ON_BN_CLICKED(IDCANCEL, &CmymfcDlg::OnBnClickedCancel)
  60. ON_BN_CLICKED(IDC_StopCam, &CmymfcDlg::OnBnClickedStopcam)
  61. ON_BN_CLICKED(IDC_RunCam, &CmymfcDlg::OnBnClickedRuncam)
  62. END_MESSAGE_MAP()
  63. // CmymfcDlg message handlers
  64. BOOL CmymfcDlg::OnInitDialog()
  65. {
  66. CDialog::OnInitDialog();
  67. // Add "About..." menu item to system menu.
  68. // IDM_ABOUTBOX must be in the system command range.
  69. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  70. ASSERT(IDM_ABOUTBOX < 0xF000);
  71. CMenu* pSysMenu = GetSystemMenu(FALSE);
  72. if (pSysMenu != NULL)
  73. {
  74. CString strAboutMenu;
  75. strAboutMenu.LoadString(IDS_ABOUTBOX);
  76. if (!strAboutMenu.IsEmpty())
  77. {
  78. pSysMenu->AppendMenu(MF_SEPARATOR);
  79. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  80. }
  81. }
  82. // Set the icon for this dialog.  The framework does this automatically
  83. //  when the application's main window is not a dialog
  84. SetIcon(m_hIcon, TRUE); // Set big icon
  85. SetIcon(m_hIcon, FALSE); // Set small icon
  86. // TODO: Add extra initialization here
  87. // 初始化 创建 TheImage
  88. CvSize ImgSize;
  89. ImgSize.height = IMAGE_HEIGHT;
  90. ImgSize.width = IMAGE_WIDTH;
  91. TheImage = cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS );
  92. /*
  93. // 初始化 BMP 的显示缓存
  94. bmi = ( BITMAPINFO* )buffer;
  95. bmih = &( bmi->bmiHeader );
  96. memset( bmih, 0, sizeof( *bmih ) ); // 把bmih里的内容清零,返回bmih
  97. bmih->biSize = sizeof( BITMAPINFOHEADER );
  98. bmih->biWidth = IMAGE_WIDTH;
  99. bmih->biHeight = -IMAGE_HEIGHT;
  100. bmih->biPlanes = 1;
  101. bmih->biCompression = BI_RGB;
  102. bmih->biBitCount = 8 * TheImage->nChannels;
  103. palette = bmi->bmiColors;
  104. if( TheImage->nChannels == 1 )
  105. {
  106. for( int i = 0; i < 256; i++ )
  107. {
  108. palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
  109. palette[i].rgbReserved = 0;
  110. }
  111. }
  112. */
  113. // 初始化视频、摄像头显示循环的执行和中断(m_run)
  114. m_run = 0;
  115. // 获取摄像头数目
  116. int cam_count = CCameraDS::CameraCount();
  117. // 在组合框CamList中添加摄像头名称的字符串
  118. for(int i=0; i < cam_count; i++)
  119. {
  120. char camera_name[1024];  
  121. int retval = CCameraDS::CameraName(i, camera_name, sizeof(camera_name) );
  122. char istr[25];
  123. sprintf_s(istr, " # %d", i);
  124. //strcat_s( camera_name, istr );
  125. CString camstr;
  126. camstr.Format("%s%s",camera_name, istr );
  127. if(retval >0)
  128. m_camList.AddString( camstr );
  129. else
  130. AfxMessageBox(_T("不能获取摄像头的名称"));
  131. }
  132. UpdateData( FALSE );
  133. // 使边缘检测按钮、视频播放和暂停按钮失效
  134. GetDlgItem( IDC_EdgeDetect )->EnableWindow( FALSE );
  135. GetDlgItem( IDC_Play )->EnableWindow( FALSE );
  136. GetDlgItem( IDC_Pause )->EnableWindow( FALSE );
  137. GetDlgItem( IDC_RunCam )->EnableWindow( FALSE );
  138. GetDlgItem( IDC_StopCam )->EnableWindow( FALSE );
  139. return TRUE;  // return TRUE  unless you set the focus to a control
  140. }
  141. void CmymfcDlg::OnSysCommand(UINT nID, LPARAM lParam)
  142. {
  143. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  144. {
  145. CAboutDlg dlgAbout;
  146. dlgAbout.DoModal();
  147. }
  148. else
  149. {
  150. CDialog::OnSysCommand(nID, lParam);
  151. }
  152. }
  153. // If you add a minimize button to your dialog, you will need the code below
  154. //  to draw the icon.  For MFC applications using the document/view model,
  155. //  this is automatically done for you by the framework.
  156. void CmymfcDlg::OnPaint()
  157. {
  158. if (IsIconic())
  159. {
  160. CPaintDC dc(this); // device context for painting
  161. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  162. // Center icon in client rectangle
  163. int cxIcon = GetSystemMetrics(SM_CXICON);
  164. int cyIcon = GetSystemMetrics(SM_CYICON);
  165. CRect rect;
  166. GetClientRect(&rect);
  167. int x = (rect.Width() - cxIcon + 1) / 2;
  168. int y = (rect.Height() - cyIcon + 1) / 2;
  169. // Draw the icon
  170. dc.DrawIcon(x, y, m_hIcon);
  171. }
  172. else
  173. {
  174. CDialog::OnPaint(); // 重绘对话框
  175. CDialog::UpdateWindow(); // 更新windows窗口,如果无这步调用,图片显示还会出现问题
  176. ShowImage( TheImage, IDC_ShowImg ); // 重绘图片函数
  177. }
  178. }
  179. // The system calls this function to obtain the cursor to display while the user drags
  180. //  the minimized window.
  181. HCURSOR CmymfcDlg::OnQueryDragIcon()
  182. {
  183. return static_cast<HCURSOR>(m_hIcon);
  184. }
  185. /*=======================================
  186. *************图片读取处理****************
  187. ========================================*/
  188. void CmymfcDlg::OnBnClickedReadimg()
  189. {
  190. // TODO: Add your control notification handler code here
  191. CFileDialog dlg(
  192. TRUE, _T("*.bmp"), NULL,
  193. OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
  194. _T("image files (*.bmp; *.jpg) |*.bmp; *.jpg; *.jpeg | All Files (*.*) |*.*||"), NULL
  195. ); // 选项图片的约定
  196. dlg.m_ofn.lpstrTitle = _T("Open Image"); // 打开文件对话框的标题名
  197. if( dlg.DoModal() != IDOK ) // 判断是否获得图片
  198. return;
  199. CString mPath = dlg.GetPathName(); // 获取图片路径
  200. IplImage* ipl = cvLoadImage( mPath, 1 ); // 读取图片、缓存到一个局部变量 ipl 中
  201. if( !ipl ) // 判断是否成功读取图片
  202. return;
  203. if( TheImage ) // 对上一幅显示的图片数据清零
  204. cvZero( TheImage );
  205. // 使边缘检测按钮生效
  206. GetDlgItem( IDC_EdgeDetect )->EnableWindow( TRUE );
  207. ResizeImage( ipl ); // 对读入的图片进行缩放,使其宽或高最大值者刚好等于 256,再复制到 TheImage 中
  208. ShowImage( TheImage, IDC_ShowImg ); // 调用显示图片函数
  209. cvReleaseImage( &ipl ); // 释放 ipl 占用的内存
  210. }
  211. void CmymfcDlg::OnBnClickedEdgedetect()
  212. {
  213. // TODO: Add your control notification handler code here
  214. IplImage *gray = 0, *edge = 0;
  215. gray = cvCreateImage( cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 1 );
  216. edge = cvCreateImage( cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 1 );
  217. cvCvtColor( TheImage, gray, CV_BGR2GRAY );
  218. cvCanny( gray, edge, 30, 100, 3 );
  219. cvCvtColor( edge, TheImage, CV_GRAY2BGR );
  220. ShowImage( TheImage, IDC_ShowImg ); // 调用显示图片函数
  221. // 边缘检测只执行一次,完成后则令按钮失效
  222. GetDlgItem( IDC_EdgeDetect )->EnableWindow( FALSE );
  223. cvReleaseImage( &gray );
  224. cvReleaseImage( &edge );
  225. }
  226. void CmymfcDlg::ShowImage( IplImage* img, UINT ID ) // ID 是Picture Control控件的ID号
  227. {
  228. CDC* pDC = GetDlgItem( ID ) ->GetDC(); // 获得显示控件的 DC
  229. HDC hDC = pDC ->GetSafeHdc(); // 获取 HDC(设备句柄) 来进行绘图操作
  230. CRect rect;
  231. GetDlgItem(ID) ->GetClientRect( &rect );
  232. int rw = rect.right - rect.left; // 求出图片控件的宽和高
  233. int rh = rect.bottom - rect.top;
  234. int iw = img->width; // 读取图片的宽和高
  235. int ih = img->height;
  236. int tx = (int)(rw - iw)/2; // 使图片的显示位置正好在控件的正中
  237. int ty = (int)(rh - ih)/2;
  238. SetRect( rect, tx, ty, tx+iw, ty+ih );
  239. CvvImage cimg;
  240. cimg.CopyOf( img ); // 复制图片
  241. cimg.DrawToHDC( hDC, &rect ); // 将图片绘制到显示控件的指定区域内
  242. ReleaseDC( pDC );
  243. }
  244. void CmymfcDlg::ResizeImage(IplImage* img)
  245. {
  246. // 读取图片的宽和高
  247.     int w = img->width;
  248. int h = img->height;
  249. // 找出宽和高中的较大值者
  250. int max = (w > h)? w: h;
  251. // 计算将图片缩放到TheImage区域所需的比例因子
  252. float scale = (float) ( (float) max / 256.0f );
  253. // 缩放后图片的宽和高
  254. int nw = (int)( w/scale );
  255. int nh = (int)( h/scale );
  256. // 为了将缩放后的图片存入 TheImage 的正中部位,需计算图片在 TheImage 左上角的期望坐标值
  257. int tlx = (nw > nh)? 0: (int)(256-nw)/2;
  258. int tly = (nw > nh)? (int)(256-nh)/2: 0;
  259. // 设置 TheImage 的 ROI 区域,用来存入图片 img
  260. cvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );
  261. // 对图片 img 进行缩放,并存入到 TheImage 中
  262. cvResize( img, TheImage );
  263. // 重置 TheImage 的 ROI 准备读入下一幅图片
  264. cvResetImageROI( TheImage );
  265. }
  266. /*=======================================
  267. *************本地视频处理****************
  268. ========================================*/
  269. void CmymfcDlg::OnBnClickedReadvideo()
  270. {
  271. // TODO: Add your control notification handler code here
  272. CFileDialog dlg(
  273. TRUE, _T("*.avi"), NULL,
  274. OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
  275. _T("*.avi|*.avi|*.rmvb|*.rmvb|*.mp4|*.mp4|*.wmv|*.wmv| All Files (*.*) |*.*||"), NULL
  276. ); // 选项视频的约定
  277. dlg.m_ofn.lpstrTitle = _T("Open Video"); // 打开文件对话框的标题名
  278. if( dlg.DoModal() != IDOK ) // 判断是否获得视频
  279. return;
  280. vPath = dlg.GetPathName(); // 获取视频路径
  281. // 使能视频播放按钮
  282. GetDlgItem( IDC_Play )->EnableWindow( TRUE );
  283. GetDlgItem( IDC_Pause )->EnableWindow( TRUE );
  284. }
  285. void CmymfcDlg::OnBnClickedPlayVideo()
  286. {
  287. // TODO: Add your control notification handler code here
  288. CvCapture *pCapture = NULL;
  289.     IplImage *pFrame = NULL;
  290.         
  291. if( vPath == "" )  //判断文件路径是否为空
  292. {
  293. MessageBox("请先选择视频文件!");
  294. return;
  295. }
  296. else
  297. {
  298. if(!(pCapture = cvCreateFileCapture( vPath )))
  299. {
  300. MessageBox("打开视频文件失败!");
  301. return;
  302. }
  303. }
  304. // 播放视频时令读入图片和视频、以及播放的按钮失效
  305. GetDlgItem( IDC_ReadImg )->EnableWindow( FALSE );
  306. GetDlgItem( IDC_ReadVideo )->EnableWindow( FALSE );
  307. GetDlgItem( IDC_Play )->EnableWindow( FALSE );
  308. GetDlgItem( IDC_CamList )->EnableWindow( FALSE );
  309. GetDlgItem( IDC_RunCam )->EnableWindow( FALSE );
  310. GetDlgItem( IDC_StopCam )->EnableWindow( FALSE );
  311. cvNamedWindow("video");
  312. cvResizeWindow("video",1,1);
  313. HWND hWnd = (HWND) cvGetWindowHandle("video");
  314. HWND hParent = ::GetParent(hWnd);
  315. HWND hwnd1=::FindWindow("CmymfcDlg","mymfc");
  316. ::SetParent(hWnd, hwnd1);
  317. ::ShowWindow(hParent, SW_HIDE);
  318. // 读取视频文件的帧数
  319. int frames = (int) cvGetCaptureProperty( pCapture, CV_CAP_PROP_FRAME_COUNT );
  320. int numfrm = 0;
  321. // 对图像数据清零
  322. if( TheImage )
  323. cvZero( TheImage );
  324. m_run = 1;
  325.     while( (numfrm < frames) & (m_run == 1) )
  326.     { 
  327. pFrame = cvQueryFrame( pCapture );
  328. IplImage* newframe = cvCloneImage(pFrame);
  329. ResizeImage( newframe );
  330. ShowImage( TheImage, IDC_ShowImg );
  331. if (cvWaitKey(20) == 27) break;
  332. numfrm++;
  333. cvReleaseImage( &newframe );
  334. }
  335. m_run = 0;
  336. // 对图像数据清零
  337. if( TheImage )
  338. {
  339. cvZero( TheImage );
  340. ShowImage( TheImage, IDC_ShowImg );
  341. }
  342. // 视频结束后令读入图片和视频按钮生效
  343. GetDlgItem( IDC_ReadImg )->EnableWindow( TRUE );
  344. GetDlgItem( IDC_ReadVideo )->EnableWindow( TRUE );
  345. GetDlgItem( IDC_Play )->EnableWindow( TRUE );
  346. GetDlgItem( IDC_CamList )->EnableWindow( TRUE );
  347.     cvReleaseCapture(&pCapture);
  348. cvDestroyWindow("video");
  349. return;
  350. }
  351. void CmymfcDlg::OnBnClickedPause()
  352. {
  353. // TODO: Add your control notification handler code here
  354. m_run = 0;
  355. return;
  356. }
  357. /*=======================================
  358. 摄像头处理区
  359. ========================================*/
  360. void CmymfcDlg::OnCbnSelchangeCamlist()
  361. {
  362. // TODO: Add your control notification handler code here
  363. mCamIndex = m_camList.GetCurSel();
  364. GetDlgItem( IDC_RunCam )->EnableWindow( TRUE );
  365. return;
  366. }
  367. void CmymfcDlg::OnBnClickedStopcam()
  368. {
  369. // TODO: Add your control notification handler code here
  370. m_run = 0;
  371. return;
  372. }
  373. void CmymfcDlg::OnBnClickedRuncam()
  374. {
  375. // TODO: Add your control notification handler code here
  376. CString camName;
  377. camName.Format("%s%d","Camera # ", mCamIndex );
  378. UpdateData( FALSE );
  379. // 创建1个摄像头实例
  380. CCameraDS camera;
  381. //打开第一个摄像头
  382. //if(! camera.OpenCamera(0, true)) //弹出属性选择窗口
  383. if( (! camera.OpenCamera(mCamIndex, false, 320,240) ) ) //不弹出属性选择窗口,用代码制定图像宽和高
  384. {
  385. AfxMessageBox(_T("Can not open camera.n"));
  386. return;
  387. }
  388. // 读取摄像头数据时令读入图片和视频、播放、暂停的按钮失效
  389. GetDlgItem( IDC_ReadImg )->EnableWindow( FALSE );
  390. GetDlgItem( IDC_ReadVideo )->EnableWindow( FALSE );
  391. GetDlgItem( IDC_Play )->EnableWindow( FALSE );
  392. GetDlgItem( IDC_Pause )->EnableWindow( FALSE );
  393. // 使关闭摄像头按钮生效
  394. GetDlgItem( IDC_StopCam )->EnableWindow( TRUE );
  395. // 创建一个Ipl图像指针来读取摄像头的帧画面
  396. IplImage* cFrame;
  397. // 创建一个视频播放窗口
  398. cvNamedWindow("camera");
  399. // 将这个窗口缩至最小
  400. cvResizeWindow("camera",1,1);
  401. // 获取窗口句柄
  402. HWND hWnd = (HWND) cvGetWindowHandle("camera");
  403. // 获取该窗口的父窗口句柄
  404. HWND hParent = ::GetParent(hWnd);
  405. // 获取mymfc的GUI窗口句柄
  406. HWND hwnd1=::FindWindow("CmymfcDlg","mymfc");
  407. // 将GUI窗口设置为视频播放窗口的父窗口,使视频在 GUI 的指定区域播放
  408. ::SetParent(hWnd, hwnd1);
  409. // 隐藏所创建的视频播放窗口
  410. ::ShowWindow(hParent, SW_HIDE);
  411. // 对图像数据清零
  412. if( TheImage )
  413. cvZero( TheImage );
  414. // 初始化在图像中显示字符的字体格式
  415. CvFont tFont;
  416. cvInitFont(&tFont,  CV_FONT_HERSHEY_COMPLEX, 0.5f,0.7f,0,1,8);
  417. // 为读取系统时间信息分配内存
  418. char timestr[26];
  419. memset(timestr, 0, 26 * sizeof(char));
  420. m_run = 1;
  421. while( m_run )
  422. //获取一帧
  423. cFrame = camera.QueryFrame();
  424. IplImage* newframe = cvCloneImage(cFrame);
  425. // 获取系统时间信息
  426. __time64_t rawtime; 
  427. struct tm timeinfo ; 
  428. errno_t err;
  429. // Get time as 64-bit integer
  430. _time64( &rawtime );
  431. // Convert to local time
  432. err = _localtime64_s( &timeinfo, &rawtime );
  433. // Convert to an ASCII representation
  434. asctime_s( timestr, 26, &timeinfo );
  435. CString strTime;
  436. strTime.Format( "%s", timestr );
  437. strTime.Replace( "n", "" );
  438. /*rawtime = time( NULL ); 
  439. timeinfo = localtime( &rawtime ); 
  440. char* p = asctime( timeinfo );
  441. // 字符串 p 的第25个字符是换行符 'n',但在图像中将乱码显示
  442. // 故仅读取 p 的前 24 个字符
  443. for (int i = 0; i < 24; i++)
  444. {
  445. timestr[i] = *p;
  446. p++;
  447. }
  448. p = NULL; */
  449. // 在图像上显示摄像头序号以及系统时间信息
  450. cvPutText( newframe, camName, cvPoint(95,15), &tFont,  CV_RGB(255,0,0) );
  451. cvPutText( newframe, strTime, cvPoint(5,225), &tFont,  CV_RGB(255,0,0) );
  452. ResizeImage( newframe );
  453. ShowImage( TheImage, IDC_ShowImg );
  454. if (cvWaitKey(20) == 27) break;
  455. cvReleaseImage( &newframe );
  456. }
  457. // 对图像数据清零
  458. if( TheImage )
  459. {
  460. cvZero( TheImage );
  461. ShowImage( TheImage, IDC_ShowImg );
  462. }
  463. camera.CloseCamera();
  464. cvDestroyWindow("camera");
  465. // 读取摄像头数据时令读入图片和视频、播放、暂停的按钮失效
  466. GetDlgItem( IDC_ReadImg )->EnableWindow( TRUE );
  467. GetDlgItem( IDC_ReadVideo )->EnableWindow( TRUE );
  468. GetDlgItem( IDC_Play )->EnableWindow( TRUE );
  469. GetDlgItem( IDC_Pause )->EnableWindow( TRUE );
  470. return;
  471. }
  472. /*=======================================
  473. *************退出GUI窗口****************
  474. ========================================*/
  475. void CmymfcDlg::OnBnClickedOk()
  476. {
  477. // TODO: Add your control notification handler code here
  478. m_run = 0;
  479. cvDestroyAllWindows();
  480. OnOK();
  481. }
  482. void CmymfcDlg::OnBnClickedCancel()
  483. {
  484. // TODO: Add your control notification handler code here
  485. m_run = 0;
  486. cvDestroyAllWindows();
  487. OnCancel();
  488. }