/******************************************************************* Bilkent University: Mean-shift Tracker based Moving Object Tracker in Video Version: 1.0 Compiler: Microsoft Visual C++ 6.0 (tested in both debug and release mode) **********************************************************************/ #include "ObjectTracker.h" #include #include #include #define GetRValue(rgb) ((UBYTE8) (rgb)) #define GetGValue(rgb) ((UBYTE8) (((ULONG_32) (rgb)) >> 8)) #define GetBValue(rgb) ((UBYTE8) ((rgb) >> 16)) #define RGB(r, g ,b) ((ULONG_32) (((UBYTE8) (r) | ((UBYTE8) (g) << 8)) | (((ULONG_32) (UBYTE8) (b)) << 16))) #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) #define MEANSHIFT_ITARATION_NO 5 #define DISTANCE_ITARATION_NO 1 #define ALPHA 1 #define EDGE_DETECT_TRESHOLD 32 CObjectTracker::CObjectTracker(INT32 imW,INT32 imH,IMAGE_TYPE eImageType) { m_nImageWidth = imW; m_nImageHeight = imH; m_eIMAGE_TYPE = eImageType; m_cSkipValue = 0; for (UBYTE8 i=0;i> 8) & 0xFF); *(frame+(y*m_nImageWidth+x)*m_cSkipValue) = UBYTE8((pixelValues >> 16) & 0xFF); } // returns box color ULONG_32 CObjectTracker::GetBoxColor() { ULONG_32 pixelValues = 0; switch(m_cActiveObject) { case 0: pixelValues = RGB(255,0,0); break; case 1: pixelValues = RGB(0,255,0); break; case 2: pixelValues = RGB(0,0,255); break; case 3: pixelValues = RGB(255,255,0); break; case 4: pixelValues = RGB(255,0,255); break; case 5: pixelValues = RGB(0,255,255); break; case 6: pixelValues = RGB(255,255,255); break; case 7: pixelValues = RGB(128,0,128); break; case 8: pixelValues = RGB(128,128,0); break; case 9: pixelValues = RGB(128,128,128); break; case 10: pixelValues = RGB(255,128,0); break; case 11: pixelValues = RGB(0,128,128); break; case 12: pixelValues = RGB(123,50,10); break; case 13: pixelValues = RGB(10,240,126); break; case 14: pixelValues = RGB(0,128,255); break; case 15: pixelValues = RGB(128,200,20); break; default: break; } return(pixelValues); } //initializes the object parameters void CObjectTracker::ObjectTrackerInitObjectParameters(SINT16 x,SINT16 y,SINT16 Width,SINT16 Height) { m_cActiveObject = 0; m_sTrackingObjectTable[m_cActiveObject].X = x; m_sTrackingObjectTable[m_cActiveObject].Y = y; m_sTrackingObjectTable[m_cActiveObject].W = Width; m_sTrackingObjectTable[m_cActiveObject].H = Height; m_sTrackingObjectTable[m_cActiveObject].vectorX = 0; m_sTrackingObjectTable[m_cActiveObject].vectorY = 0; m_sTrackingObjectTable[m_cActiveObject].Status = true; m_sTrackingObjectTable[m_cActiveObject].assignedAnObject = false; } void CObjectTracker::ObjeckTrackerHandlerByUser(UBYTE8 *frame) { m_cActiveObject = 0; if (m_sTrackingObjectTable[m_cActiveObject].Status) { if (!m_sTrackingObjectTable[m_cActiveObject].assignedAnObject) { FindHistogram(frame,m_sTrackingObjectTable[m_cActiveObject].initHistogram); m_sTrackingObjectTable[m_cActiveObject].assignedAnObject = true; } else { FindNextLocation(frame); DrawObjectBox(frame); } } } //Extracts the histogram of box void CObjectTracker::FindHistogram(UBYTE8 *frame, FLOAT32 (*histogram)) { SINT16 i = 0; SINT16 x = 0; SINT16 y = 0; UBYTE8 E = 0; UBYTE8 qR = 0,qG = 0,qB = 0; ULONG_32 pixelValues = 0; UINT32 numberOfPixel = 0; for (i=0;i0.0 ) weights[i] = m_sTrackingObjectTable[m_cActiveObject].initHistogram[i]/histogram[i]; else weights[i] = 0.0; } for (y=max(m_sTrackingObjectTable[m_cActiveObject].Y-m_sTrackingObjectTable[m_cActiveObject].H/2,0);y<=min(m_sTrackingObjectTable[m_cActiveObject].Y+m_sTrackingObjectTable[m_cActiveObject].H/2,m_nImageHeight-1);y++) for (x=max(m_sTrackingObjectTable[m_cActiveObject].X-m_sTrackingObjectTable[m_cActiveObject].W/2,0);x<=min(m_sTrackingObjectTable[m_cActiveObject].X+m_sTrackingObjectTable[m_cActiveObject].W/2,m_nImageWidth-1);x++) { E = CheckEdgeExistance(frame,x,y); pixelValues = GetPixelValues(frame,x,y); qR = GetRValue(pixelValues)/16; qG = GetGValue(pixelValues)/16; qB = GetBValue(pixelValues)/16; ptr = 4096*E+256*qR+16*qG+qB; newX += (weights[ptr]*x); newY += (weights[ptr]*y); sumOfWeights += weights[ptr]; } if (sumOfWeights>0) { m_sTrackingObjectTable[m_cActiveObject].X = SINT16((newX/sumOfWeights) + 0.5); m_sTrackingObjectTable[m_cActiveObject].Y = SINT16((newY/sumOfWeights) + 0.5); } delete[] weights, weights = 0; } // Returns the distance between two histograms. FLOAT32 CObjectTracker::FindDistance(UBYTE8 (*histogram)) { SINT16 i = 0; FLOAT32 distance = 0; for(i=0;i0) distance += difference; else distance -= difference; } return(distance); } // Returns the edge insformation of a pixel at (x,y) UBYTE8 CObjectTracker::CheckEdgeExistance(UBYTE8 *frame,SINT16 _x,SINT16 _y) { UBYTE8 E = 0; SINT16 GrayCenter = 0; SINT16 GrayLeft = 0; SINT16 GrayRight = 0; SINT16 GrayUp = 0; SINT16 GrayDown = 0; ULONG_32 pixelValues = 0; pixelValues = GetPixelValues(frame,_x,_y); GrayCenter = SINT16(3*GetRValue(pixelValues)+6*GetGValue(pixelValues)+GetGValue(pixelValues)); if (_x>0) { pixelValues = GetPixelValues(frame,_x-1,_y); GrayLeft = SINT16(3*GetRValue(pixelValues)+6*GetGValue(pixelValues)+GetGValue(pixelValues)); } if (_x < (m_nImageWidth-1)) { pixelValues = GetPixelValues(frame,_x+1,_y); GrayRight = SINT16(3*GetRValue(pixelValues)+6*GetGValue(pixelValues)+GetGValue(pixelValues)); } if (_y>0) { pixelValues = GetPixelValues(frame,_x,_y-1); GrayUp = SINT16(3*GetRValue(pixelValues)+6*GetGValue(pixelValues)+GetGValue(pixelValues)); } if (_y<(m_nImageHeight-1)) { pixelValues = GetPixelValues(frame,_x,_y+1); GrayDown = SINT16(3*GetRValue(pixelValues)+6*GetGValue(pixelValues)+GetGValue(pixelValues)); } if (abs((GrayCenter-GrayLeft)/10)>EDGE_DETECT_TRESHOLD) E = 1; if (abs((GrayCenter-GrayRight)/10)>EDGE_DETECT_TRESHOLD) E = 1; if (abs((GrayCenter-GrayUp)/10)>EDGE_DETECT_TRESHOLD) E = 1; if (abs((GrayCenter-GrayDown)/10)>EDGE_DETECT_TRESHOLD) E = 1; return(E); } // Alpha blending: used to update initial histogram by the current histogram void CObjectTracker::UpdateInitialHistogram(UBYTE8 (*histogram)) { SINT16 i = 0; for (i=0; i