BlobTracker.cpp
上传用户:sdgangtie
上传日期:2020-03-07
资源大小:7324k
文件大小:24k
开发平台:

Visual C++

  1. #include "StdAfx.h"
  2. #include "BlobTracker.h"
  3. /************************************************************************/
  4. /*                        前景检测模块——背景差部分                    */
  5. /************************************************************************/
  6. // 仿射变换矩阵,主要用于前景检测模块中计算全局运动和轨迹生成模块中轨迹校正
  7. static CvMat *T = NULL;
  8. FGDetector::FGDetector(void)
  9. : m_FrameCount(0)
  10. , m_Transform(1)
  11. , m_Threshold(20.0)
  12. , m_pFramePre(NULL)
  13. , m_pFGMask(NULL)
  14. , m_pTransPre(NULL)
  15. {
  16. if(m_Transform) T = cvCreateMat( 2, 3, CV_64FC1 );
  17. else T = cvCreateMat( 3, 3, CV_64FC1 );
  18. cvZero(T);
  19. AddParam("Threshold",&m_Threshold);
  20. AddParam("Transform",&m_Transform);
  21. SetModuleName("FGDetector");
  22. }
  23. FGDetector::~FGDetector(void)
  24. {
  25. Release();
  26. }
  27. IplImage* FGDetector::GetMask(void)
  28. {
  29. return m_pFGMask;
  30. }
  31. void FGDetector::Process(IplImage* pFrame)
  32. {
  33. if(m_FrameCount == 0)
  34. {
  35. m_pFGMask = cvCreateImage(cvSize( pFrame->width, pFrame->height ), IPL_DEPTH_8U, 1);
  36. m_pTransPre = cvCreateImage(cvSize( pFrame->width, pFrame->height ), IPL_DEPTH_8U, 3);
  37. m_pFramePre = cvCloneImage(pFrame);
  38. }
  39. else if(m_FrameCount == 1)
  40. {
  41. GetMaskBySIFT(m_pFramePre, pFrame, m_Transform, T);
  42. if(m_Transform) cvWarpAffine(m_pFramePre, m_pTransPre, T, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); else cvWarpPerspective(m_pFramePre, m_pTransPre, T, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
  43. if(m_pFramePre) cvCopyImage(pFrame, m_pFramePre);
  44. else m_pFramePre = cvCloneImage(pFrame);
  45. }
  46. else
  47. {
  48. GetMaskBySIFT(m_pFramePre, pFrame, m_Transform, T);
  49. IplImage* m_pTransAft = cvCreateImage(cvSize( pFrame->width, pFrame->height ), IPL_DEPTH_8U, 3);
  50. if(m_Transform) cvWarpAffine(pFrame, m_pTransAft, T, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS + CV_WARP_INVERSE_MAP,cvScalarAll(0)); else cvWarpPerspective(pFrame, m_pTransAft, T, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS + CV_WARP_INVERSE_MAP, cvScalarAll(0));
  51. IplImage* diff1 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 3); IplImage* diff2 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 3); cvAbsDiff(m_pTransPre, m_pFramePre, diff1); cvAbsDiff(m_pTransAft, m_pFramePre, diff2); cvSmooth(diff1, diff1, CV_GAUSSIAN, 5, 0, 0, 0); cvSmooth(diff2, diff2, CV_GAUSSIAN, 5, 0, 0, 0); IplImage* gray1 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1); IplImage* gray2 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1); cvCvtColor(diff1, gray1, CV_BGR2GRAY); cvCvtColor(diff2, gray2, CV_BGR2GRAY); IplImage* mask1 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1); IplImage* mask2 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1); cvThreshold(gray1, mask1, m_Threshold, 255.0, CV_THRESH_BINARY); cvThreshold(gray2, mask2, m_Threshold, 255.0, CV_THRESH_BINARY); cvErode(mask1, mask1, 0, 2); cvDilate(mask1, mask1, 0, 2); cvErode(mask2, mask2, 0, 2); cvDilate(mask2, mask2, 0, 2);
  52. cvAnd(mask1, mask2, m_pFGMask, 0); if(m_Transform) cvWarpAffine(m_pFramePre, m_pTransPre, T, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); else cvWarpPerspective(m_pFramePre, m_pTransPre, T, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
  53. if(m_pFramePre) cvCopyImage(pFrame, m_pFramePre);
  54. else m_pFramePre = cvCloneImage(pFrame); cvReleaseImage(&diff1); cvReleaseImage(&diff2); cvReleaseImage(&gray1); cvReleaseImage(&gray2); cvReleaseImage(&mask1); cvReleaseImage(&mask2); cvReleaseImage(&m_pTransAft);
  55. }
  56. m_FrameCount++;
  57. }
  58. void FGDetector::Release(void)
  59. {
  60. if(m_pFramePre) cvReleaseImage(&m_pFramePre);
  61. if(m_pFGMask) cvReleaseImage(&m_pFGMask);
  62. if(m_pTransPre) cvReleaseImage(&m_pTransPre);
  63. }
  64. /************************************************************************/
  65. /*                      对象检测模块——连通分量方法                    */
  66. /************************************************************************/
  67. static int CompareContour(const void* a, const void* b, void* ) { float dx,dy; float h,w,ht,wt; CvPoint2D32f pa,pb; CvRect ra,rb; CvSeq* pCA = *(CvSeq**)a; CvSeq* pCB = *(CvSeq**)b; ra = ((CvContour*)pCA)->rect; rb = ((CvContour*)pCB)->rect; pa.x = ra.x + ra.width*0.5f; pa.y = ra.y + ra.height*0.5f; pb.x = rb.x + rb.width*0.5f; pb.y = rb.y + rb.height*0.5f; w = (ra.width+rb.width)*0.5f; h = (ra.height+rb.height)*0.5f; dx = (float)(fabs(pa.x - pb.x)-w); dy = (float)(fabs(pa.y - pb.y)-h); wt = MAX(ra.width, rb.width)*0.3f; // 宽度距离限制 ht = MAX(ra.height, rb.height)*0.3f; // 高度距离限制 return (dx < wt && dy < ht); }
  68. BlobDetector::BlobDetector(void)
  69. : m_HMin(0.05)
  70. , m_HMax(0.95)
  71. , m_WMin(0.05)
  72. , m_WMax(0.95)
  73. {
  74. AddParam("HMin", &m_HMin); AddParam("HMax", &m_HMax); AddParam("WMin", &m_WMin); AddParam("WMax", &m_WMax); SetParam("DebugWnd",0); SetModuleName("BD Detector");
  75. }
  76. BlobDetector::~BlobDetector(void)
  77. {
  78. }
  79. void BlobDetector::cvFindBlobsByCCClasters(IplImage* pFG, CvBlobSeq* pBlobs, CvMemStorage* storage)
  80. {
  81. IplImage* pIB = NULL; CvSeq* cnt = NULL; CvSeq* cnt_list = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvSeq*), storage); CvSeq* clasters = NULL; int claster_cur, claster_num; pIB = cvCloneImage(pFG); cvThreshold(pIB, pIB, 128, 255, CV_THRESH_BINARY); cvFindContours(pIB, storage, &cnt, sizeof(CvContour), CV_RETR_EXTERNAL); cvReleaseImage(&pIB); for(; cnt; cnt=cnt->h_next) { cvSeqPush(cnt_list, &cnt); } claster_num = cvSeqPartition(cnt_list, storage, &clasters, CompareContour, NULL); for(claster_cur=0; claster_cur<claster_num; claster_cur++) { CvBlob NewBlob; double M00,X,Y,XX,YY; CvMoments m; CvRect rect_res = cvRect(-1,-1,-1,-1); CvMat mat; for(int cnt_cur=0; cnt_cur<clasters->total; ++cnt_cur) { CvRect  rect; CvSeq*  cnt; int k = *(int*)cvGetSeqElem(clasters, cnt_cur); if(k!=claster_cur) continue; cnt = *(CvSeq**)cvGetSeqElem(cnt_list, cnt_cur); rect = ((CvContour*)cnt)->rect; if(rect_res.height<0) { rect_res = rect; } else { int x0,x1,y0,y1; x0 = MIN(rect_res.x, rect.x); y0 = MIN(rect_res.y, rect.y); x1 = MAX(rect_res.x+rect_res.width, rect.x+rect.width); y1 = MAX(rect_res.y+rect_res.height, rect.y+rect.height); rect_res.x = x0; rect_res.y = y0; rect_res.width = x1-x0; rect_res.height = y1-y0; } } if(rect_res.height < 1 || rect_res.width < 1) { X = 0; Y = 0; XX = 0; YY = 0; } else { cvMoments(cvGetSubRect(pFG,&mat,rect_res), &m, 0); M00 = cvGetSpatialMoment(&m, 0, 0); if(M00 <= 0 ) continue; X = cvGetSpatialMoment(&m, 1, 0)/M00; Y = cvGetSpatialMoment(&m, 0, 1)/M00; XX = (cvGetSpatialMoment(&m, 2, 0)/M00) - X*X; YY = (cvGetSpatialMoment(&m, 0, 2)/M00) - Y*Y; } NewBlob = cvBlob(rect_res.x+(float)X, rect_res.y+(float)Y, (float)(4*sqrt(XX)), (float)(4*sqrt(YY))); pBlobs->AddBlob(&NewBlob); }
  82. if(m_Wnd) {   // Debug info: IplImage* pI = cvCreateImage(cvSize(pFG->width,pFG->height),IPL_DEPTH_8U,3); cvZero(pI); for(claster_cur=0; claster_cur<claster_num; ++claster_cur) { int         cnt_cur; CvScalar    color = CV_RGB(rand()%256,rand()%256,rand()%256); for(cnt_cur=0; cnt_cur<clasters->total; ++cnt_cur) { CvSeq*  cnt; int k = *(int*)cvGetSeqElem( clasters, cnt_cur ); if(k!=claster_cur) continue; cnt = *(CvSeq**)cvGetSeqElem( cnt_list, cnt_cur ); cvDrawContours( pI, cnt, color, color, 0, CV_FILLED, 8); } CvBlob* pB = pBlobs->GetBlob(claster_cur); int x = cvRound(CV_BLOB_RX(pB)), y = cvRound(CV_BLOB_RY(pB)); cvEllipse( pI, cvPointFrom32f(CV_BLOB_CENTER(pB)), cvSize(MAX(1,x), MAX(1,y)), 0, 0, 360, color, 1 ); } cvNamedWindow( "Clusters", 0); cvResizeWindow( "Clusters", pI->width, pI->height) ; cvShowImage( "Clusters",pI ); cvReleaseImage(&pI); }   /* Debug info. */
  83. }
  84. int BlobDetector::DetectNewBlob(IplImage* pImg, IplImage* pFGMask, CvBlobSeq* pNewBlobList, CvBlobSeq* pOldBlobList)
  85. {
  86. int result = 0; CvSize S = cvSize(pFGMask->width,pFGMask->height); CvBlobSeq Blobs; CvMemStorage* storage = cvCreateMemStorage(); cvFindBlobsByCCClasters(pFGMask, &Blobs, storage ); for(int i=Blobs.GetBlobNum(); i>0; i--) { CvBlob* pB = Blobs.GetBlob(i-1); if(pB->h < pFGMask->height*m_HMin || pB->w < pFGMask->width*m_WMin) { Blobs.DelBlob(i-1); continue; } if(pB->h > pFGMask->height*m_HMax || pB->w > pFGMask->width*m_WMax) { Blobs.DelBlob(i-1); continue; } if(MIN(pB->x,pFGMask->width-pB->x) < CV_BLOB_RX(pB) || MIN(pB->y,pFGMask->height-pB->y) < CV_BLOB_RY(pB)) { Blobs.DelBlob(i-1); continue; } if(pOldBlobList) { for(int j=pOldBlobList->GetBlobNum(); j>0; j--) { CvBlob* pBOld = pOldBlobList->GetBlob(j-1); if((fabs(pBOld->x-pB->x) < (CV_BLOB_RX(pBOld)+CV_BLOB_RX(pB))) && (fabs(pBOld->y-pB->y) < (CV_BLOB_RY(pBOld)+CV_BLOB_RY(pB)))) { Blobs.DelBlob(i-1); break; } } } } {  int N = Blobs.GetBlobNum(); for(int i=1; i<N; i++) { for(int j=i; j>0; j--) { CvBlob  temp; float   AreaP, AreaN; CvBlob* pP = Blobs.GetBlob(j-1); CvBlob* pN = Blobs.GetBlob(j); AreaP = CV_BLOB_WX(pP)*CV_BLOB_WY(pP); AreaN = CV_BLOB_WX(pN)*CV_BLOB_WY(pN); if(AreaN < AreaP)break; temp = pN[0]; pN[0] = pP[0]; pP[0] = temp; } } for(int i=0; i<MIN(N,10); i++) { pNewBlobList->AddBlob(Blobs.GetBlob(i)); result = 1; } } #if 0 {   // 嵌入的人检测模块 IplImage *pImage = cvCloneImage(pImg); CvBlobSeq NewBlobLists; PeopleDetector(pImage, &NewBlobLists); for( int i = NewBlobLists.GetBlobNum(); i > 0 ; i-- ) { CvBlob *pB = NewBlobLists.GetBlob(i-1); pB->x = pB->x+pB->w*0.5; pB->y = pB->y+pB->h*0.5; CvPoint p1 = cvPoint(cvRound(pB->x-pB->w*0.5), cvRound(pB->y-pB->h*0.5)); CvPoint p2 = cvPoint(cvRound(pB->x+pB->w*0.5), cvRound(pB->y+pB->h*0.5)); CvScalar color = CV_RGB(0,255,0); cvRectangle(pImage,p1,p2,color); if(pOldBlobList) { for(int j=pOldBlobList->GetBlobNum(); j>0; j--) { CvBlob* pBOld = pOldBlobList->GetBlob(j-1); if((fabs(pBOld->x-pB->x) < (CV_BLOB_RX(pBOld)+CV_BLOB_RX(pB))) && (fabs(pBOld->y-pB->y) < (CV_BLOB_RY(pBOld)+CV_BLOB_RY(pB)))) { NewBlobLists.DelBlob(i-1); break; } } } } for(int i=0; i<MIN(NewBlobLists.GetBlobNum(),10); i++) { CvBlob *pB = NewBlobLists.GetBlob(i-1); pNewBlobList->AddBlob(pB); result = 1; } cvNamedWindow("People", 0); cvResizeWindow( "People", pImage->width, pImage->height) ; cvShowImage("People", pImage); cvReleaseImage(&pImage); } #endif cvReleaseMemStorage(&storage);
  87. return result;
  88. }
  89. void BlobDetector::Release(void)
  90. {
  91. delete this;
  92. }
  93. /************************************************************************/
  94. /*                     轨迹生成模块——对象特征方法                     */
  95. /************************************************************************/
  96. BlobTrackGen::BlobTrackGen(void)
  97. : m_FrameCount(0)
  98. , m_Transform(1)
  99. , m_pFileName(NULL)
  100. , m_TrackList(sizeof(DefBlobTrack))
  101. {
  102. m_Size = cvSize(2,2); AddParam("Transform", &m_Transform); SetParam("DebugWnd",0); SetModuleName("BlobTrackGen");
  103. }
  104. BlobTrackGen::~BlobTrackGen(void)
  105. {
  106. for(int i=m_TrackList.GetBlobNum(); i>0; i--) { DefBlobTrack* pTrack = (DefBlobTrack*)m_TrackList.GetBlob(i-1); delete pTrack->pSeq; pTrack->pSeq = NULL; }
  107. }
  108. CvPoint2D64f BlobTrackGen::affine_xform_pt(CvPoint2D64f pt, CvMat* T)
  109. {
  110. CvMat XY, UV;
  111. double xy[3] = {pt.x, pt.y, 1.0}, uv[2] = {0};
  112. cvInitMatHeader(&XY, 3, 1, CV_64FC1, xy, CV_AUTOSTEP);
  113. cvInitMatHeader(&UV, 2, 1, CV_64FC1, uv, CV_AUTOSTEP);
  114. cvMatMul(T, &XY, &UV);
  115. return cvPoint2D64f(uv[0] , uv[1]);
  116. }
  117. CvPoint2D64f BlobTrackGen::persp_xform_pt(CvPoint2D64f pt, CvMat* T)
  118. {
  119. CvMat XY, UV;
  120. double xy[3] = {pt.x, pt.y, 1.0}, uv[3] = {0};
  121. cvInitMatHeader(&XY, 3, 1, CV_64FC1, xy, CV_AUTOSTEP);
  122. cvInitMatHeader(&UV, 3, 1, CV_64FC1, uv, CV_AUTOSTEP);
  123. cvMatMul(T, &XY, &UV);
  124. return cvPoint2D64f(uv[0] / uv[2], uv[1] / uv[2]);
  125. }
  126. void BlobTrackGen::SaveAll(void)
  127. { int     ObjNum = m_TrackList.GetBlobNum(); int     i; char    video_name[1024]; char*   struct_name = NULL; CvFileStorage* storage = cvOpenFileStorage(m_pFileName, NULL,CV_STORAGE_WRITE_TEXT); if(storage == NULL) { printf("WARNING!!! Cannot open %s file for trajectory output.", m_pFileName); } for(i=0; i<1024 && m_pFileName[i]!='.' && m_pFileName[i]!=0; i++)  video_name[i]=m_pFileName[i]; video_name[i] = 0; for(; i>0; i--) { if(video_name[i-1] == '\') break; if(video_name[i-1] == '/') break; if(video_name[i-1] == ':') break; } struct_name = video_name + i; int tail_length = 3; for(i=0; i<ObjNum; i++) { char            obj_name[1024]; DefBlobTrack*   pTrack = (DefBlobTrack*)m_TrackList.GetBlob(i); if(pTrack == NULL || pTrack->Saved == 1) continue; if ( pTrack->FrameLast - pTrack->FrameLast > tail_length) continue; sprintf(obj_name, "%s_obj%d", struct_name, i+1); cvStartWriteStruct(storage, struct_name, CV_NODE_MAP); CvBlobSeq*      pSeq = pTrack->pSeq; cvWriteString(storage, "VideoObj", obj_name); cvWriteInt(storage, "FrameBegin", pTrack->FrameBegin); cvWriteInt(storage, "FrameLast", pTrack->FrameLast - tail_length); {  int             j; CvPoint2D32f    p; cvStartWriteStruct( storage, "Pos", CV_NODE_SEQ|CV_NODE_FLOW ); for(j=0; j<pSeq->GetBlobNum() - tail_length;j++) { CvBlob* pB = pSeq->GetBlob(j); p.x = pB->x/(m_Size.width-1); p.y = pB->y/(m_Size.height-1); cvWriteRawData(storage, &p, 1 ,"ff"); } cvEndWriteStruct(storage); } {  int             j; CvPoint2D32f    p; cvStartWriteStruct( storage, "Size", CV_NODE_SEQ|CV_NODE_FLOW ); for(j=0; j<pSeq->GetBlobNum() - tail_length; j++) { CvBlob* pB = pSeq->GetBlob(j); p.x = pB->w/(m_Size.width-1); p.y = pB->h/(m_Size.height-1); cvWriteRawData(storage, &p, 1 ,"ff"); } cvEndWriteStruct(storage); } cvEndWriteStruct(storage); /* pTrack->Saved = 1;*/ } cvReleaseFileStorage(&storage);
  128. }
  129. void BlobTrackGen::SetFileName(char* pFileName)
  130. {
  131. m_pFileName = pFileName;
  132. }
  133. void BlobTrackGen::AddBlob(CvBlob* pBlob)
  134. {
  135. DefBlobTrack* pTrack = (DefBlobTrack*)m_TrackList.GetBlobByID(CV_BLOB_ID(pBlob)); if(pTrack == NULL) { DefBlobTrack    Track; Track.blob = pBlob[0]; Track.FrameBegin = m_FrameCount; Track.pSeq = new CvBlobSeq; Track.Saved = 0; m_TrackList.AddBlob((CvBlob*)&Track); pTrack = (DefBlobTrack*)m_TrackList.GetBlobByID(CV_BLOB_ID(pBlob)); }  assert(pTrack); pTrack->FrameLast = m_FrameCount; assert(pTrack->pSeq); pTrack->pSeq->AddBlob(pBlob);
  136. }
  137. void BlobTrackGen::Process(IplImage* pImg, IplImage* pFG)
  138. {
  139. m_Size = cvSize(pImg->width, pImg->height); if (T) { for(int i=m_TrackList.GetBlobNum(); i>0; i--) { DefBlobTrack* pTrack = (DefBlobTrack*)m_TrackList.GetBlob(i-1); CvBlobSeq* pSeq = pTrack->pSeq; for(int j=0; j<pSeq->GetBlobNum()-1; j++) { CvBlob* pB = pSeq->GetBlob(j); CvPoint2D64f pt = cvPoint2D64f(pB->x, pB->y); CvPoint2D64f ptT; if(m_Transform) ptT = affine_xform_pt(pt, T); else ptT = persp_xform_pt(pt, T); pB->x = ptT.x; pB->y = ptT.y; } } } SaveAll(); if (m_Wnd) { IplImage *pI = cvCloneImage(pImg); for(int i=m_TrackList.GetBlobNum(); i>0; i--) { DefBlobTrack* pTrack = (DefBlobTrack*)m_TrackList.GetBlob(i-1); CvBlobSeq* pSeq = pTrack->pSeq; if (pTrack->FrameLast < m_FrameCount || pTrack->FrameLast-pTrack->FrameBegin < 5) continue; int j; for(j=0; j<pSeq->GetBlobNum()-1; j++) { CvBlob* pB1 = pSeq->GetBlob(j); CvBlob* pB2 = pSeq->GetBlob(j+1); CvPoint p1 =cvPoint(cvRound(pB1->x),cvRound(pB1->y)); CvPoint p2 =cvPoint(cvRound(pB2->x),cvRound(pB2->y)); cvLine(pI, p1, p2, CV_RGB(0,255,0), 1); } if (pTrack->FrameLast == m_FrameCount) { CvBlob* pB = pSeq->GetBlob(j); CvPoint p = cvPoint(cvRound(pB->x),cvRound(pB->y)); CvSize  s = cvSize(MAX(1,cvRound(CV_BLOB_RX(pB))), MAX(1,cvRound(CV_BLOB_RY(pB)))); cvEllipse( pI, p, s, 0, 0, 360, CV_RGB(0,255,0), 1); #if 0 {   // 对象的颜色柱状图信息
  140. CvMat mat;
  141. CvRect r;
  142. r.width = cvRound(pB->w*1.5+0.5); r.height = cvRound(pB->h*1.5+0.5); r.x = MAX(1,cvRound(pB->x - 0.5*r.width)); r.y = MAX(1,cvRound(pB->y - 0.5*r.height)); IplImage* src = cvCloneImage(pImg);
  143. cvSetImageROI(src,r);
  144. if(src)
  145. {
  146. IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 );
  147. IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 );
  148. IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 );
  149. IplImage* planes[] = { h_plane, s_plane, v_plane };
  150. IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 );
  151. int h_bins = 16, s_bins = 4, v_bins = 4;
  152. int hist_size[] = {h_bins, s_bins, v_bins};
  153. float h_ranges[] = { 0, 180 };
  154. float s_ranges[] = { 0, 256 };
  155. float v_ranges[] = { 0, 256 };
  156. float* ranges[] = { h_ranges, s_ranges, v_ranges };
  157. int scale = 20;
  158. IplImage* hist_img = cvCreateImage( cvSize(h_bins*v_bins*scale*0.25,h_bins*s_bins*scale*0.25), 8, 3 );
  159. CvHistogram* hist;
  160. float min_value = 0, max_value = 0, sum_all = 0;
  161. int h, s, v;
  162. cvCvtColor( src, hsv, CV_RGB2HSV );
  163. cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );
  164. hist = cvCreateHist( 3, hist_size, CV_HIST_ARRAY, ranges, 1 );
  165. cvCalcHist( planes, hist, 0, 0 );
  166. cvGetMinMaxHistValue( hist, &min_value, &max_value, 0, 0 );
  167. cvZero( hist_img );
  168. for( h = 0; h < h_bins; h++ )
  169. {
  170. for( s = 0; s < s_bins; s++ )
  171. {
  172. for( v = 0; v < v_bins; v++ )
  173. {
  174. float bin_val = cvQueryHistValue_3D( hist, h, s ,v);
  175. sum_all += bin_val;
  176. int intensity = 255-cvRound(bin_val*255/max_value);
  177. cvRectangle( hist_img, cvPoint( (v+(h%4)*v_bins)*scale,(s+(h/4)*s_bins)*scale ),
  178. cvPoint( (v+(h%4)*v_bins+1)*scale - 2,(s+(h/4)*s_bins+1)*scale - 2),
  179. CV_RGB(intensity,intensity,intensity),CV_FILLED );
  180. }
  181. }
  182. }
  183. char str[1024];
  184. sprintf(str,"Object %d",pTrack->blob.ID);
  185. cvNamedWindow( str, 1 );
  186. //cvResizeWindow(str,src->width,src->height);
  187. cvShowImage( str, src );
  188. char str2[1024];
  189. sprintf(str2,"Hist %d",pTrack->blob.ID);
  190. cvNamedWindow( str2, 1 );
  191. //cvResizeWindow(str2,hist_img->width,hist_img->height);
  192. cvShowImage( str2, hist_img );
  193. cvReleaseImage(&h_plane);
  194. cvReleaseImage(&s_plane);
  195. cvReleaseImage(&v_plane);
  196. cvReleaseImage(&hist_img);
  197. } cvReleaseImage(&src); } #endif } } cvNamedWindow("TrackGen"); cvResizeWindow("TrackGen",pI->width,pI->height); cvShowImage("TrackGen",pI); cvReleaseImage(&pI); } m_FrameCount++;
  198. }
  199. void BlobTrackGen::Release(void)
  200. {
  201. delete this;
  202. }
  203. /************************************************************************/
  204. /*                主模块——各个子模块综合模块                          */
  205. /************************************************************************/
  206. #define TIME_BEGIN() #define TIME_END(_name_)
  207. BlobTrackerAuto::BlobTrackerAuto(CvBlobTrackerAutoParam* param):m_BlobList(sizeof(CvBlobTrackAuto))
  208. {
  209. m_BlobList.AddFormat("i");
  210. m_NextBlobID = 1;
  211. m_pFGMask = NULL;
  212. m_FrameCount = 0;
  213. m_FGTrainFrames = param?param->FGTrainFrames:0;
  214. m_pFG = param?param->pFG:NULL;
  215. m_pBD = param?param->pBD:NULL;
  216. m_pBT = param?param->pBT:NULL;
  217. m_pBTGen = param?param->pBTGen:NULL;
  218. m_pBTA = param?param->pBTA:NULL;
  219. m_pBTPostProc = param?param->pBTPP:NULL;
  220. m_UsePPData = param?param->UsePPData:0;
  221. SetModuleName("BlobTrack Auto");
  222. }
  223. BlobTrackerAuto::~BlobTrackerAuto()
  224. {
  225. }
  226. void BlobTrackerAuto::Process(IplImage* pImg, IplImage* pMask)
  227. {
  228. int         CurBlobNum = 0;
  229. int         i;
  230. IplImage*   pFG = pMask;
  231. m_FrameCount++;
  232. TIME_BEGIN();
  233. if(m_pFG)
  234. m_pFG->Process(pImg);
  235. pFG = m_pFG->GetMask();
  236. }
  237. TIME_END("FGDetector");
  238. m_pFGMask = pFG;
  239. #if 0
  240. static int frame = 1;
  241. static IplImage* pITemp;
  242. static IplImage* pITempRes = cvCreateImage(cvSize(pImg->width,pImg->height),pImg->depth,pImg->nChannels);
  243. if (frame == 1)
  244. {
  245. pITemp = cvCloneImage(pImg);
  246. cvZero(pITemp);
  247. }
  248. else
  249. {
  250. double alpha = (double)(frame-1)/(double)frame;
  251. double belta = (double)1/(double)frame;
  252. cvAddWeighted(pITemp,alpha,pImg,belta,0,pITempRes);
  253. cvCopyImage(pITempRes, pITemp);
  254. }
  255. cvSaveImage("E:\BG.bmp",pITemp);
  256. frame++;
  257. #endif
  258. TIME_BEGIN();
  259. if(m_pBT)
  260. {
  261. int i;
  262. m_pBT->Process(pImg, pFG);
  263. for(i=m_BlobList.GetBlobNum(); i>0; --i)
  264. CvBlob* pB = m_BlobList.GetBlob(i-1);
  265. int     BlobID = CV_BLOB_ID(pB);
  266. int     i = m_pBT->GetBlobIndexByID(BlobID);
  267. m_pBT->ProcessBlob(i, pB, pImg, pFG);
  268. pB->ID = BlobID;
  269. }
  270. CurBlobNum = m_pBT->GetBlobNum();
  271. }
  272. TIME_END("BlobTracker");
  273. TIME_BEGIN();
  274. if(m_pBTPostProc)
  275. {
  276. int i;
  277. for(i=m_BlobList.GetBlobNum(); i>0; --i)
  278. CvBlob* pB = m_BlobList.GetBlob(i-1);
  279. m_pBTPostProc->AddBlob(pB);
  280. }
  281. m_pBTPostProc->Process();
  282. for(i=m_BlobList.GetBlobNum(); i>0; --i)
  283. CvBlob* pB = m_BlobList.GetBlob(i-1);
  284. int     BlobID = CV_BLOB_ID(pB);
  285. CvBlob* pBN = m_pBTPostProc->GetBlobByID(BlobID);
  286. if(pBN && m_UsePPData && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
  287. {
  288. m_pBT->SetBlobByID(BlobID, pBN );
  289. }
  290. if(pBN)
  291. {
  292. pB[0] = pBN[0];
  293. }
  294. }
  295. }
  296. TIME_END("PostProcessing");
  297. TIME_BEGIN();
  298. if(pFG)
  299. int i;
  300. for(i=m_BlobList.GetBlobNum();i>0;--i)
  301. {
  302. CvBlobTrackAuto* pB = (CvBlobTrackAuto*)(m_BlobList.GetBlob(i-1));
  303. int     Good = 0;
  304. int     w=pFG->width;
  305. int     h=pFG->height;
  306. CvRect  r = CV_BLOB_RECT(pB);
  307. CvMat   mat;
  308. double  aver = 0;
  309. double  area = CV_BLOB_WX(pB)*CV_BLOB_WY(pB);
  310. if(r.x < 0){r.width += r.x;r.x = 0;}
  311. if(r.y < 0){r.height += r.y;r.y = 0;}
  312. if(r.x+r.width>=w){r.width = w-r.x-1;}
  313. if(r.y+r.height>=h){r.height = h-r.y-1;}
  314. if(r.width > 4 && r.height > 4 && r.x < w && r.y < h &&
  315. r.x >=0 && r.y >=0 &&
  316. r.x+r.width < w && r.y+r.height < h && area > 0)
  317. {
  318. aver = cvSum(cvGetSubRect(pFG,&mat,r)).val[0] / area;
  319. if(aver > 0.1*255)Good = 1;
  320. }
  321. else
  322. {
  323. pB->BadFrames+=2;
  324. }
  325. if(Good)
  326. {
  327. pB->BadFrames = 0;
  328. }
  329. else
  330. {
  331. pB->BadFrames++;
  332. }
  333. }
  334. for(i=0; i<m_BlobList.GetBlobNum(); ++i)
  335. {
  336. CvBlobTrackAuto* pB = (CvBlobTrackAuto*)m_BlobList.GetBlob(i);
  337. if(pB->BadFrames>3)
  338. {
  339. m_pBT->DelBlobByID(CV_BLOB_ID(pB));
  340. m_BlobList.DelBlob(i);
  341. i--;
  342. }
  343. }
  344. TIME_END("BlobDeleter");
  345. TIME_BEGIN();
  346. if(m_pBT)
  347. m_pBT->Update(pImg, pFG);
  348. TIME_END("BlobTrackerUpdate");
  349. TIME_BEGIN();
  350. if(m_pBD && pFG && (m_FrameCount > m_FGTrainFrames) )
  351. {
  352. static CvBlobSeq    NewBlobList;
  353. CvBlobTrackAuto     NewB;
  354. NewBlobList.Clear();
  355. if(m_pBD->DetectNewBlob(pImg, pFG, &NewBlobList, &m_BlobList))
  356. {  
  357. int i;
  358. IplImage* pMask = pFG;
  359. for(i=0; i<NewBlobList.GetBlobNum(); ++i)
  360. {
  361. CvBlob* pBN = NewBlobList.GetBlob(i);
  362. pBN->ID = m_NextBlobID;
  363. if(pBN && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
  364. {
  365. CvBlob* pB = m_pBT->AddBlob(pBN, pImg, pMask );
  366. if(pB)
  367. {
  368. NewB.blob = pB[0];
  369. NewB.BadFrames = 0;
  370. m_BlobList.AddBlob((CvBlob*)&NewB);
  371. m_NextBlobID++;
  372. }
  373. }
  374. if(pMask != pFG) cvReleaseImage(&pMask);
  375. TIME_END("BlobDetector");
  376. TIME_BEGIN();
  377. if(m_pBTGen)
  378. for(i=m_BlobList.GetBlobNum(); i>0; --i)
  379. {
  380. CvBlob* pB = m_BlobList.GetBlob(i-1);
  381. m_pBTGen->AddBlob(pB);
  382. }
  383. m_pBTGen->Process(pImg, pFG);
  384. }
  385. TIME_END("TrajectoryGeneration");
  386. TIME_BEGIN();
  387. if(m_pBTA)
  388. {
  389. int i;
  390. for(i=m_BlobList.GetBlobNum(); i>0; i--)
  391. m_pBTA->AddBlob(m_BlobList.GetBlob(i-1));
  392. m_pBTA->Process(pImg, pFG);
  393. }
  394. TIME_END("TrackAnalysis");
  395. }