TrackandIDDlg.cpp
上传用户:wfkeli
上传日期:2014-02-03
资源大小:3091k
文件大小:14k
源码类别:

OpenCV

开发平台:

Visual C++

  1. // TrackandIDDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include <string>
  5. #include "TrackandID.h"
  6. #include "TrackandIDDlg.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. using namespace std;
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CAboutDlg dialog used for App About
  15. class CAboutDlg : public CDialog
  16. {
  17. public:
  18. CAboutDlg();
  19. // Dialog Data
  20. //{{AFX_DATA(CAboutDlg)
  21. enum { IDD = IDD_ABOUTBOX };
  22. //}}AFX_DATA
  23. // ClassWizard generated virtual function overrides
  24. //{{AFX_VIRTUAL(CAboutDlg)
  25. protected:
  26. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  27. //}}AFX_VIRTUAL
  28. // Implementation
  29. protected:
  30. //{{AFX_MSG(CAboutDlg)
  31. //}}AFX_MSG
  32. DECLARE_MESSAGE_MAP()
  33. };
  34. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  35. {
  36. //{{AFX_DATA_INIT(CAboutDlg)
  37. //}}AFX_DATA_INIT
  38. }
  39. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  40. {
  41. CDialog::DoDataExchange(pDX);
  42. //{{AFX_DATA_MAP(CAboutDlg)
  43. //}}AFX_DATA_MAP
  44. }
  45. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  46. //{{AFX_MSG_MAP(CAboutDlg)
  47. // No message handlers
  48. //}}AFX_MSG_MAP
  49. END_MESSAGE_MAP()
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CTrackandIDDlg dialog
  52. CTrackandIDDlg::CTrackandIDDlg(CWnd* pParent /*=NULL*/)
  53. : CDialog(CTrackandIDDlg::IDD, pParent)
  54. {
  55. //{{AFX_DATA_INIT(CTrackandIDDlg)
  56. // NOTE: the ClassWizard will add member initialization here
  57. //}}AFX_DATA_INIT
  58. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  59. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  60. }
  61. void CTrackandIDDlg::DoDataExchange(CDataExchange* pDX)
  62. {
  63. CDialog::DoDataExchange(pDX);
  64. //{{AFX_DATA_MAP(CTrackandIDDlg)
  65. // NOTE: the ClassWizard will add DDX and DDV calls here
  66. //}}AFX_DATA_MAP
  67. }
  68. BEGIN_MESSAGE_MAP(CTrackandIDDlg, CDialog)
  69. //{{AFX_MSG_MAP(CTrackandIDDlg)
  70. ON_WM_SYSCOMMAND()
  71. ON_WM_PAINT()
  72. ON_WM_QUERYDRAGICON()
  73. ON_BN_CLICKED(IDC_StartTrackandID, OnStartTrackandID)
  74. //}}AFX_MSG_MAP
  75. END_MESSAGE_MAP()
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CTrackandIDDlg message handlers
  78. BOOL CTrackandIDDlg::OnInitDialog()
  79. {
  80. CDialog::OnInitDialog();
  81. // Add "About..." menu item to system menu.
  82. // IDM_ABOUTBOX must be in the system command range.
  83. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  84. ASSERT(IDM_ABOUTBOX < 0xF000);
  85. CMenu* pSysMenu = GetSystemMenu(FALSE);
  86. if (pSysMenu != NULL)
  87. {
  88. CString strAboutMenu;
  89. strAboutMenu.LoadString(IDS_ABOUTBOX);
  90. if (!strAboutMenu.IsEmpty())
  91. {
  92. pSysMenu->AppendMenu(MF_SEPARATOR);
  93. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  94. }
  95. }
  96. // Set the icon for this dialog.  The framework does this automatically
  97. //  when the application's main window is not a dialog
  98. SetIcon(m_hIcon, TRUE); // Set big icon
  99. SetIcon(m_hIcon, FALSE); // Set small icon
  100. // TODO: Add extra initialization here
  101. return TRUE;  // return TRUE  unless you set the focus to a control
  102. }
  103. void CTrackandIDDlg::OnSysCommand(UINT nID, LPARAM lParam)
  104. {
  105. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  106. {
  107. CAboutDlg dlgAbout;
  108. dlgAbout.DoModal();
  109. }
  110. else
  111. {
  112. CDialog::OnSysCommand(nID, lParam);
  113. }
  114. }
  115. void CTrackandIDDlg::OnPaint() 
  116. {
  117. if (IsIconic())
  118. {
  119. CPaintDC dc(this); // device context for painting
  120. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  121. // Center icon in client rectangle
  122. int cxIcon = GetSystemMetrics(SM_CXICON);
  123. int cyIcon = GetSystemMetrics(SM_CYICON);
  124. CRect rect;
  125. GetClientRect(&rect);
  126. int x = (rect.Width() - cxIcon + 1) / 2;
  127. int y = (rect.Height() - cyIcon + 1) / 2;
  128. // Draw the icon
  129. dc.DrawIcon(x, y, m_hIcon);
  130. }
  131. else
  132. {
  133. CDialog::OnPaint();
  134. }
  135. }
  136. // The system calls this to obtain the cursor to display while the user drags
  137. //  the minimized window.
  138. HCURSOR CTrackandIDDlg::OnQueryDragIcon()
  139. {
  140. return (HCURSOR) m_hIcon;
  141. }
  142. /////////////////////////////////////////////////////////////////////////////////////
  143. //打开视频文件以及车辆跟踪和识别
  144. void CTrackandIDDlg::OnStartTrackandID() 
  145. {
  146. // TODO: Add your control notification handler code here
  147.     int argc=2;
  148. ////打开文件///////////////////////////////////////////////////
  149. CString FilePathName;
  150. CFileDialog dlg(TRUE);
  151. if(dlg.DoModal()==IDOK)
  152. FilePathName=dlg.GetPathName();
  153.     IplImage* pFrame = NULL;
  154.     IplImage* pFrImg = NULL;
  155.     IplImage* pBkImg = NULL;
  156. IplImage* pFrImg1 = NULL;
  157.     CvMat* pFrameMat = NULL;
  158.     CvMat* pFrMat = NULL;
  159.     CvMat* pBkMat = NULL;
  160. CvMat* pFrMat1 = NULL;
  161. CvMemStorage * storage = cvCreateMemStorage(0);//轮廓边缘提取时的参数
  162.     CvSeq * contour = 0;//轮廓边缘提取时的参数
  163.     int mode = CV_RETR_EXTERNAL;//轮廓边缘提取时的参数
  164. //形态学处理时内核的大小
  165. IplConvKernel* Element = cvCreateStructuringElementEx(13,13,1,1,CV_SHAPE_RECT,NULL);
  166. CvFont font1;//初始化字体格式
  167. int linetype=CV_AA;
  168. cvInitFont(&font1, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, 8);
  169. //用字符串时一定要把using namespace std;写在前面,否则不能用,下面是用于显示的字符串
  170. string msg[10]={"JGD01","JGD02","JGD03","JGD04","JGD05","JGD06","JGD07","JGD08","JGD09","JGD10"};
  171. int No=0;//用于记录显示车辆
  172. bool FindCar=false;
  173.   
  174. //在视频中画出感兴趣的区域,怎么样才能沿车道画线???????
  175. CvPoint pt1,pt2,pt3,pt4,pt5;
  176. pt1.x=292;//(视频中左下点)
  177. pt1.y=100;
  178. pt2.x=412;//(视频中右上点)
  179. pt2.y=280;
  180. CvRect bndRect=cvRect(0,0,0,0);//用cvBoundingRect画出外接矩形时需要的矩形
  181. int avgX = 0;//The midpoint X position of the rectangle surrounding the moving objects
  182. int avgY = 0;//The midpoint Y position of the rectangle surrounding the moving objects
  183. int avgX1=0;//用来合并相近的车辆
  184. int avgY1=0;             
  185. for(int i=0;i<10;i++)
  186. {
  187. TrackBlock[i]=NULL;
  188. if((TrackBlock[i]=(struct AvTrackBlock *) malloc(sizeof(struct AvTrackBlock)))==NULL)
  189. {
  190. MessageBox("内存分配错误");
  191. exit(1);
  192. }  
  193. }////////////////////
  194.     CvCapture* pCapture = NULL;  
  195.     int nFrmNum = 0;//表示图像的帧数
  196.     //创建窗口
  197.     cvNamedWindow("video", 1);
  198.          //cvNamedWindow("background",1);
  199.     cvNamedWindow("foreground",1);
  200.     //使窗口有序排列
  201.     cvMoveWindow("video", 30, 0);
  202.         //cvMoveWindow("background", 360, 0);
  203.     cvMoveWindow("foreground", 690, 0);
  204.     if( argc > 2 ){
  205.         fprintf(stderr, "Usage: bkgrd [video_file_name]n");
  206.         //return -1;
  207.     }
  208.     ////打开摄像头///////////////////////////////////////////////////
  209.     if (argc ==1)
  210.         if( !(pCapture = cvCaptureFromCAM(-1))){
  211.         fprintf(stderr, "Can not open camera.n");
  212.         //return -2;
  213. }
  214.     ///打开视频文件//////////////////////////////////////////////////
  215.     if(argc == 2)
  216.         if( !(pCapture = cvCaptureFromFile(FilePathName))){
  217. fprintf(stderr, "Can not open video file %sn", FilePathName);
  218. //return -2;
  219. }
  220.   
  221.     //逐帧读取视频,cvQueryFrame从摄像头或者文件中抓取并返回一帧
  222.     while(pFrame = cvQueryFrame(pCapture))
  223.     {
  224.         nFrmNum++; 
  225.         //如果是第一帧,需要申请内存,并初始化
  226.         if(nFrmNum == 1)
  227. {
  228. pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
  229. pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
  230.  pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
  231.  pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
  232.  pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
  233. cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);
  234. cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
  235. cvConvert(pFrImg, pFrameMat);
  236. cvConvert(pFrImg, pFrMat);
  237. cvConvert(pFrImg, pBkMat);
  238. }
  239. else if(nFrmNum == 3)
  240. {
  241. cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
  242. cvConvert(pFrImg, pFrameMat);
  243. //高斯滤波先,以平滑图像
  244. cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);
  245. //在视频中设置并画出感兴趣的区域
  246. cvRectangle(pFrame,pt1,pt2,CV_RGB(255,0,0),2, 8, 0 );
  247. //当前帧跟背景图相减,cvAbsDiff计算两个数组差的绝对值
  248. cvAbsDiff(pFrameMat, pBkMat, pFrMat);
  249. //二值化前景图
  250. cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);
  251. //通过查找边界找出ROI矩形区域内的运动车辆,建立完全目标档案
  252. //cvCanny(pFrImg, pBkImg, 50, 150, 3);
  253. cvDilate(pFrImg,pBkImg,Element,1);
  254. cvFindContours(pBkImg, storage, &contour, sizeof(CvContour),
  255. mode, CV_CHAIN_APPROX_SIMPLE);
  256. //process each moving contour in the current frame用函数cvBoundingRect
  257. for(;contour!=0;contour=contour->h_next)
  258. {
  259. //Get a bounding rectangle around the moving object.
  260. bndRect = cvBoundingRect(contour, 0);
  261. //Get an average X position of the moving contour.
  262. avgX = (bndRect.x + bndRect.x + bndRect.width) / 2; 
  263. avgY = (bndRect.y + bndRect.y + bndRect.height) / 2;
  264. pt5.x = bndRect.x;//写字的左下角点
  265. pt5.y = avgY;
  266. //If the center of contour is within ROI than show it
  267. if(avgX>300 && avgX<400 && avgY<300 && avgY>80)
  268. {
  269. pt3.x = bndRect.x;
  270. pt3.y = bndRect.y;
  271. pt4.x = bndRect.x + bndRect.width;
  272. pt4.y = bndRect.y + bndRect.height;
  273. if(bndRect.height>35) //把长度小于某个阀值的干扰矩形去掉
  274. {
  275. cvRectangle(pFrame,pt3,pt4,CV_RGB(255,0,0),1, 8, 0 );
  276. //在车辆的中心写编号
  277. cvPutText( pFrame, msg[No].c_str(), pt5, &font1, cvScalar(0,255,0));
  278. //把当前车辆存入跟踪数组
  279. TrackBlock[No]->Direction=1;
  280. TrackBlock[No]->FramesTracked=nFrmNum;
  281. TrackBlock[No]->avgX=avgX;
  282. TrackBlock[No]->avgY=avgY;
  283. No++;
  284. }
  285. }
  286. }/////查找边界的for 循环结束
  287. //更新背景///////////////////////////////////////////////////
  288. cvRunningAvg(pFrameMat, pBkMat, 0.005, 0);
  289. //将背景转化为图像格式,用以显示
  290. cvConvert(pBkMat, pBkImg);
  291. //显示图像////////////////////////////////////////////////////
  292. cvShowImage("video", pFrame);
  293. //cvShowImage("background", pBkImg);
  294. //cvShowImage("foreground", pFrImg);
  295. //如果有按键事件,则跳出循环,此等待也为cvShowImage函数提供时间完成显示,等待时间可以根据CPU速度调整
  296. if( cvWaitKey(2) >= 0 )
  297. break;
  298. }
  299.         else if(nFrmNum > 3)//从第三帧开始,根据完全目标档案来新增或删除运动车辆档案。
  300. {
  301.  cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
  302.  cvConvert(pFrImg, pFrameMat);
  303. //高斯滤波先,以平滑图像
  304.  cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);
  305. //在视频中设置并画出感兴趣的区域
  306. //cvSetImageROI(pFrame,rect1);
  307. cvRectangle(pFrame,pt1,pt2,CV_RGB(255,0,0),2, 8, 0 );
  308. //当前帧跟背景图相减,cvAbsDiff计算两个数组差的绝对值
  309. cvAbsDiff(pFrameMat, pBkMat, pFrMat);
  310. //二值化前景图,void cvThreshold( const CvArr* src, CvArr* dst, double threshold,
  311.             //double max_value, int threshold_type );
  312. cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);
  313. //通过查找边界找出ROI矩形区域内的运动车辆,建立完全目标档案
  314. //cvCanny(pFrImg, pBkImg, 50, 150, 3);
  315. cvDilate(pFrImg,pBkImg,Element,1);
  316. cvFindContours( pBkImg, storage, &contour, sizeof(CvContour),
  317. mode, CV_CHAIN_APPROX_SIMPLE);
  318. //process each moving contour in the current frame用函数cvBoundingRect
  319. for(;contour!=0;contour=contour->h_next)
  320. {
  321. //Get a bounding rectangle around the moving object.
  322. bndRect = cvBoundingRect(contour, 0);
  323. //Get an average X position of the moving contour.
  324. avgX = (bndRect.x + bndRect.x + bndRect.width) / 2; 
  325. avgY = (bndRect.y + bndRect.y + bndRect.height) / 2;
  326. pt5.x=bndRect.x;//写字的左下角点
  327. pt5.y=avgY;
  328. //If the center of contour is within ROI than show it
  329. if(avgX > 300 && avgX < 400 && avgY < 280 && avgY > 100)
  330. {
  331. pt3.x = bndRect.x;
  332. pt3.y = bndRect.y;
  333. pt4.x = bndRect.x + bndRect.width;
  334. pt4.y = bndRect.y + bndRect.height;
  335. if(bndRect.height>35) //把长度小于某个阀值的干扰矩形去掉
  336. {
  337. cvRectangle(pFrame,pt3,pt4,CV_RGB(255,0,0),1, 8, 0 );
  338. //cvPutText(pFrame,msg[No].c_str(), pt5, &font1, cvScalar(0,255,0));
  339. //在跟踪数组中寻找看是否有匹配的车辆,没有则表示是新车辆
  340. for(int i=0;i<10;i++)
  341. {
  342. if(TrackBlock[i]->avgX !=0 && abs(avgX-TrackBlock[i]->avgX)<20 && 
  343.  abs(avgY-TrackBlock[i]->avgY)<50)
  344. {
  345.     cvPutText(pFrame,msg[i].c_str(), pt5, &font1, cvScalar(0,255,0));
  346. TrackBlock[i]->FramesTracked=nFrmNum;
  347. TrackBlock[i]->avgX=avgX;
  348. TrackBlock[i]->avgY=avgY;
  349. i=10;//使跳出for循环
  350. FindCar=true;
  351. }
  352. }
  353. if(FindCar!=true && avgY<120)//表示没有找到车辆
  354. {
  355. TrackBlock[No]->Direction=1;
  356. TrackBlock[No]->FramesTracked=nFrmNum;
  357. TrackBlock[No]->avgX=avgX;
  358. TrackBlock[No]->avgY=avgY;
  359. if(No==9){
  360. No=0;
  361. }
  362. else
  363. No++;
  364. }
  365. FindCar=false;//赋值为false为下一次寻找车辆做准备
  366. }
  367. }
  368. }//轮廓分for循环结束
  369. //对于没有匹配的车辆,表示已经出了边界,清空数组
  370. for(int j=0;j<10;j++)
  371. {
  372. if(TrackBlock[j]->FramesTracked != nFrmNum)
  373. {
  374. //虽然置为零,但是可能零和当前中心的值在设定的范围内,所以不行。
  375. //TrackBlock[j]=NULL;为何用NULL不行。
  376. TrackBlock[j]->Direction=0;
  377. TrackBlock[j]->FramesTracked=0;
  378. TrackBlock[j]->avgX=0;
  379. TrackBlock[j]->avgY=0;
  380. }
  381. }
  382. //更新背景///////////////////////////////////////////////////
  383. cvRunningAvg(pFrameMat, pBkMat, 0.005, 0);
  384. //将背景转化为图像格式,用以显示
  385. cvConvert(pBkMat, pBkImg);
  386. //显示图像////////////////////////////////////////////////////
  387. cvShowImage("video", pFrame);
  388. cvShowImage("background", pBkImg);
  389. cvShowImage("foreground", pFrImg);
  390. /*if(nFrmNum/2 ==0)
  391. pBkMat=pFrameMat;*/
  392. //如果有按键事件,则跳出循环,此等待也为cvShowImage函数提供时间完成显示,等待时间可以根据CPU速度调整
  393. if( cvWaitKey(2) >= 0 )
  394. break;
  395. }//
  396.     }//while循环结束
  397. cvReleaseStructuringElement(&Element);//删除结构元素
  398.     //销毁窗口
  399.     cvDestroyWindow("video");
  400.     cvDestroyWindow("background");
  401.     cvDestroyWindow("foreground");
  402.     //释放图像和矩阵
  403.     cvReleaseImage(&pFrImg);
  404.     cvReleaseImage(&pBkImg);
  405.     cvReleaseMat(&pFrameMat);
  406.     cvReleaseMat(&pFrMat);
  407.     cvReleaseMat(&pBkMat);
  408. }