#define HIST_INDEX(_pData) (((_pData)[0]>>m_ByteShift) + (((_pData)[1]>>(m_ByteShift))<<m_BinBit)+((pImgData[2]>>m_ByteShift)<<(m_BinBit*2)))
void calcKernelEpanechnikov(CvMat* pK)
-{/* allocate kernel for histogramm creation */
+{ /* Allocate kernel for histogramm creation: */
int x,y;
int w = pK->width;
int h = pK->height;
float x0 = 0.5f*(w-1);
float y0 = 0.5f*(h-1);
- for(y=0;y<h;++y)for(x=0;x<w;++x)
+
+ for(y=0; y<h; ++y) for(x=0; x<w; ++x)
{
// float r2 = ((x-x0)*(x-x0)/(x0*x0)+(y-y0)*(y-y0)/(y0*y0));
float r2 = ((x-x0)*(x-x0)+(y-y0)*(y-y0))/((x0*x0)+(y0*y0));
CV_MAT_ELEM(pK[0],DefHistType, y, x) = (DefHistType)((r2<1)?(1-r2):0);
}
-}/* allocate kernel for histogramm creation */
+} /* Allocate kernel for histogram creation. */
class CvBlobTrackerOneMSFGS:public CvBlobTrackerOne
{
private:
- /* parameters */
+ /* Parameters: */
float m_FGWeight;
float m_Alpha;
CvSize m_ObjSize;
float m_HistCandidateVolume;
CvMat* m_HistTemp;
CvBlob m_Blob;
+
void ReAllocHist(int Dim, int BinBit)
{
m_BinBit = BinBit;
m_HistModelVolume = 0.0f;
m_HistCandidateVolume = 0.0f;
}
+
void ReAllocKernel(int w, int h, float sigma=0.4)
{
double ScaleToObj = sigma*1.39;
m_KernelMeanShiftSize = cvSize(kernel_width,kernel_height);
- /* create kernels for histogramm calculation */
+ /* Create kernels for histogram calculation: */
if(m_KernelHistModel) cvReleaseMat(&m_KernelHistModel);
m_KernelHistModel = cvCreateMat(h, w, DefHistTypeMat);
calcKernelEpanechnikov(m_KernelHistModel);
if(m_Weights) cvReleaseMat(&m_Weights);
m_Weights = cvCreateMat(kernel_height, kernel_width, CV_32F);
- for(s=-SCALE_RANGE;s<=SCALE_RANGE;++s)
- {/* allocate kernwl for meanshifts in space and scale */
+ for(s=-SCALE_RANGE; s<=SCALE_RANGE; ++s)
+ { /* Allocate kernel for meanshifts in space and scale: */
int si = s+SCALE_RANGE;
double cur_sigma = sigma * pow(SCALE_BASE,s);
double cur_sigma2 = cur_sigma*cur_sigma;
if(m_KernelMeanShiftG[si]) cvReleaseMat(&m_KernelMeanShiftG[si]);
m_KernelMeanShiftK[si] = cvCreateMat(kernel_height, kernel_width, DefHistTypeMat);
m_KernelMeanShiftG[si] = cvCreateMat(kernel_height, kernel_width, DefHistTypeMat);
- for(y=0;y<kernel_height;++y)
+
+ for(y=0; y<kernel_height; ++y)
{
DefHistType* pK = (DefHistType*)CV_MAT_ELEM_PTR_FAST( m_KernelMeanShiftK[si][0], y, 0, sizeof(DefHistType) );
DefHistType* pG = (DefHistType*)CV_MAT_ELEM_PTR_FAST( m_KernelMeanShiftG[si][0], y, 0, sizeof(DefHistType) );
- for(x=0;x<kernel_width;++x)
+
+ for(x=0; x<kernel_width; ++x)
{
double r2 = ((x-x0)*(x-x0)/(x0*x0)+(y-y0)*(y-y0)/(y0*y0));
double sigma12 = cur_sigma2 / 2.56;
pK[x] = (DefHistType)(Gaussian2D(r2, sigma12)/sigma12 - Gaussian2D(r2, sigma22)/sigma22);
pG[x] = (DefHistType)(Gaussian2D(r2, cur_sigma2/1.6) - Gaussian2D(r2, cur_sigma2*1.6));
}
- }/* next line */
+ } /* Next line. */
}
- }/* ReallocKernel*/
+ } /* ReallocKernel */
+
inline double Gaussian2D(double x, double sigma2)
{
return (exp(-x/(2*sigma2)) / (2*3.1415926535897932384626433832795*sigma2) );
}
+
void calcHist(IplImage* pImg, IplImage* pMask, CvPoint Center, CvMat* pKernel, CvMat* pHist, DefHistType* pHistVolume)
{
int w = pKernel->width;
if(m_Dim == 3)
{
- for(y=0;y<h;++y)
+ for(y=0; y<h; ++y)
{
unsigned char* pImgData = NULL;
unsigned char* pMaskData = NULL;
pImgData = &CV_IMAGE_ELEM(pImg,unsigned char,y+y0,x0*3);
pMaskData = pMask?(&CV_IMAGE_ELEM(pMask,unsigned char,y+y0,x0)):NULL;
pKernelData = (DefHistType*)CV_MAT_ELEM_PTR_FAST(pKernel[0],y,0,sizeof(DefHistType));
- for(x=0;x<w;++x,pImgData+=3)
+
+ for(x=0; x<w; ++x, pImgData+=3)
{
if((x0+x)>=pImg->width) continue;
if((x0+x)<0)continue;
+
if(pMaskData==NULL || pMaskData[x]>128)
{
DefHistType K = pKernelData[x];
assert(index >= 0 && index < pHist->cols);
Volume += K;
((DefHistType*)(pHist->data.ptr))[index] += K;
- }/* only masked pixels */
- }/* next column */
- }/* next row */
- }/* if m_Dim == 3 */
+
+ } /* Only masked pixels. */
+ } /* Next column. */
+ } /* Next row. */
+ } /* if m_Dim == 3. */
+
if(pHistVolume)pHistVolume[0] = Volume;
- };/*calcHist*/
+
+ }; /* calcHist */
+
double calcBhattacharyya()
{
cvMul(m_HistCandidate,m_HistModel,m_HistTemp);
cvPow(m_HistTemp,m_HistTemp,0.5);
return cvSum(m_HistTemp).val[0] / sqrt(m_HistCandidateVolume*m_HistModelVolume);
- } /* calcBhattacharyyaCoefficient */
+ } /* calcBhattacharyyaCoefficient */
+
void calcWeights(IplImage* pImg, IplImage* pImgFG, CvPoint Center)
{
cvZero(m_Weights);
- /* calc new pos */
+
+ /* Calculate new position: */
if(m_Dim == 3)
{
int x0 = Center.x - m_KernelMeanShiftSize.width/2;
assert(m_Weights->width == m_KernelMeanShiftSize.width);
assert(m_Weights->height == m_KernelMeanShiftSize.height);
- /*calc shift vector */
- for(y=0;y<m_KernelMeanShiftSize.height;++y)
+ /* Calcualte shift vector: */
+ for(y=0; y<m_KernelMeanShiftSize.height; ++y)
{
unsigned char* pImgData = NULL;
unsigned char* pMaskData = NULL;
pMaskData = pImgFG?(&CV_IMAGE_ELEM(pImgFG,unsigned char,y+y0,x0)):NULL;
pWData = (float*)CV_MAT_ELEM_PTR_FAST(m_Weights[0],y,0,sizeof(float));
- for(x=0;x<m_KernelMeanShiftSize.width;++x,pImgData+=3)
+ for(x=0; x<m_KernelMeanShiftSize.width; ++x, pImgData+=3)
{
double V = 0;
double HM = 0;
if(m_HistModelVolume>0)
HM = ((DefHistType*)m_HistModel->data.ptr)[index]/m_HistModelVolume;
+
if(m_HistCandidateVolume>0)
HC = ((DefHistType*)m_HistCandidate->data.ptr)[index]/m_HistCandidateVolume;
V = (HC>0)?sqrt(HM / HC):0;
V += m_FGWeight*(pMaskData?((pMaskData[x]/255.0f)):0);
pWData[x] = (float)MIN(V,100000);
- }/* next column */
- }/* next row */
- }/* if m_Dim == 3 */
- }/* calcWeights */
+
+ } /* Next column. */
+ } /* Next row. */
+ } /* if m_Dim == 3. */
+ } /* calcWeights */
public:
CvBlobTrackerOneMSFGS()
m_FGWeight = 0;
m_Alpha = 0.0;
- /* add several parameters for external use */
+ /* Add several parameters for external use: */
AddParam("FGWeight", &m_FGWeight);
CommentParam("FGWeight","Weight of FG mask using (0 - mask will not be used for tracking)");
AddParam("Alpha", &m_Alpha);
m_KernelHistModel = NULL;
m_KernelHistCandidate = NULL;
m_Weights = NULL;
- for(i=0;i<SCALE_NUM;++i)
+
+ for(i=0; i<SCALE_NUM; ++i)
{
m_KernelMeanShiftK[i] = NULL;
m_KernelMeanShiftG[i] = NULL;
}
- ReAllocHist(3,5); /* 3D hist, each dim has 2^5 bins*/
+ ReAllocHist(3,5); /* 3D hist, each dimension has 2^5 bins. */
}
+
~CvBlobTrackerOneMSFGS()
{
int i;
if(m_HistCandidate) cvReleaseMat(&m_HistCandidate);
if(m_HistTemp) cvReleaseMat(&m_HistTemp);
if(m_KernelHistModel) cvReleaseMat(&m_KernelHistModel);
- for(i=0;i<SCALE_NUM;++i)
+
+ for(i=0; i<SCALE_NUM; ++i)
{
if(m_KernelMeanShiftK[i]) cvReleaseMat(&m_KernelMeanShiftK[i]);
if(m_KernelMeanShiftG[i]) cvReleaseMat(&m_KernelMeanShiftG[i]);
}
}
- /* interface */
+
+ /* Interface: */
virtual void Init(CvBlob* pBlobInit, IplImage* pImg, IplImage* pImgFG = NULL)
{
int w = cvRound(CV_BLOB_WX(pBlobInit));
calcHist(pImg, pImgFG, cvPointFrom32f(CV_BLOB_CENTER(pBlobInit)), m_KernelHistModel, m_HistModel, &m_HistModelVolume);
m_Blob = pBlobInit[0];
};
+
virtual CvBlob* Process(CvBlob* pBlobPrev, IplImage* pImg, IplImage* pImgFG = NULL)
{
int iter;
{
m_Blob = pBlobPrev[0];
}
- for(iter=0;iter<10;++iter)
+
+ for(iter=0; iter<10; ++iter)
{
// float newx=0,newy=0,sum=0;
float dx=0,dy=0,sum=0;
int x,y,si;
+
CvPoint Center = cvPoint(cvRound(m_Blob.x),cvRound(m_Blob.y));
- CvSize Size = cvSize(cvRound(m_Blob.w),cvRound(m_Blob.h));
+ CvSize Size = cvSize(cvRound(m_Blob.w),cvRound(m_Blob.h));
if(m_ObjSize.width != Size.width || m_ObjSize.height != Size.height)
- { /* realloc kernels */
+ { /* Reallocate kernels: */
ReAllocKernel(Size.width,Size.height);
- } /* realloc kernels */
+ } /* Reallocate kernels. */
- /* mean shift in coordinate space */
+ /* Mean shift in coordinate space: */
calcHist(pImg, NULL, Center, m_KernelHistCandidate, m_HistCandidate, &m_HistCandidateVolume);
calcWeights(pImg, pImgFG, Center);
- for(si=1;si<(SCALE_NUM-1);++si)
+
+ for(si=1; si<(SCALE_NUM-1); ++si)
{
CvMat* pKernel = m_KernelMeanShiftK[si];
float sdx = 0, sdy=0, ssum=0;
int s = si-SCALE_RANGE;
float factor = (1.0f-( float(s)/float(SCALE_RANGE) )*( float(s)/float(SCALE_RANGE) ));
- for(y=0;y<m_KernelMeanShiftSize.height;++y)
- for(x=0;x<m_KernelMeanShiftSize.width;++x)
+ for(y=0; y<m_KernelMeanShiftSize.height; ++y)
+ for(x=0; x<m_KernelMeanShiftSize.width; ++x)
{
float W = *(float*)CV_MAT_ELEM_PTR_FAST(m_Weights[0],y,x,sizeof(float));
float K = *(float*)CV_MAT_ELEM_PTR_FAST(pKernel[0],y,x,sizeof(float));
ssum += (float)fabs(KW);
sdx += KW*(x-m_KernelMeanShiftSize.width*0.5f);
sdy += KW*(y-m_KernelMeanShiftSize.height*0.5f);
- }/* next pixel */
+ } /* Next pixel. */
+
dx += sdx * factor;
dy += sdy * factor;
sum += ssum * factor;
- }/* next scale */
+
+ } /* Next scale. */
+
if(sum > 0)
{
dx /= sum;
m_Blob.x += dx;
m_Blob.y += dy;
- { /* mean shift in scale space */
+ { /* Mean shift in scale space: */
float news = 0;
float sum = 0;
float scale;
calcHist(pImg, NULL, Center, m_KernelHistCandidate, m_HistCandidate, &m_HistCandidateVolume);
calcWeights(pImg, pImgFG, Center);
//cvSet(m_Weights,cvScalar(1));
+
for(si=0; si<SCALE_NUM; si++)
{
double W = cvDotProduct(m_Weights, m_KernelMeanShiftG[si]);;
sum += (float)fabs(W);
news += (float)(s*W);
}
+
if(sum>0)
{
news /= sum;
}
+
scale = (float)pow((double)SCALE_BASE,(double)news);
m_Blob.w *= scale;
m_Blob.h *= scale;
- } /* mean shift in scale space */
+ } /* Mean shift in scale space. */
- /* check fo finish */
+ /* Check fo finish: */
if(fabs(dx)<0.1 && fabs(dy)<0.1) break;
- }/* next iteration */
+
+ } /* Next iteration. */
if(m_Alpha>0)
- {/* update hist */
+ { /* Update histogram: */
double Vol, WM, WC;
CvPoint Center = cvPoint(cvRound(m_Blob.x),cvRound(m_Blob.y));
calcHist(pImg, pImgFG, Center, m_KernelHistModel, m_HistCandidate, &m_HistCandidateVolume);
WC = Vol*(m_Alpha)/m_HistCandidateVolume;
cvAddWeighted(m_HistModel, WM, m_HistCandidate,WC,0,m_HistModel);
m_HistModelVolume = (float)cvSum(m_HistModel).val[0];
- }/* update hist */
+ } /* Update histogram. */
return &m_Blob;
- }; /* Process */
+
+ }; /* Process */
+
virtual void Release(){delete this;};
}; /*CvBlobTrackerOneMSFGS*/
{
return (CvBlobTrackerOne*) new CvBlobTrackerOneMSFGS;
}
+
CvBlobTracker* cvCreateBlobTrackerMSFGS()
{
return cvCreateBlobTrackerList(cvCreateBlobTrackerOneMSFGS);