X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fcvaux%2Fvs%2Fblobtrackingmsfgs.cpp;fp=src%2Fcvaux%2Fvs%2Fblobtrackingmsfgs.cpp;h=36e835bfdcaf210a8828fe3557ad9e5d5879d6c4;hb=e4c14cdbdf2fe805e79cd96ded236f57e7b89060;hp=0000000000000000000000000000000000000000;hpb=454138ff8a20f6edb9b65a910101403d8b520643;p=opencv diff --git a/src/cvaux/vs/blobtrackingmsfgs.cpp b/src/cvaux/vs/blobtrackingmsfgs.cpp new file mode 100644 index 0000000..36e835b --- /dev/null +++ b/src/cvaux/vs/blobtrackingmsfgs.cpp @@ -0,0 +1,457 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "_cvaux.h" + +#define SCALE_BASE 1.1 +#define SCALE_RANGE 2 +#define SCALE_NUM (2*SCALE_RANGE+1) +typedef float DefHistType; +#define DefHistTypeMat CV_32F +#define HIST_INDEX(_pData) (((_pData)[0]>>m_ByteShift) + (((_pData)[1]>>(m_ByteShift))<>m_ByteShift)<<(m_BinBit*2))) + +void calcKernelEpanechnikov(CvMat* pK) +{ /* 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; y0); + assert(h>0); + m_ObjSize = cvSize(w,h); + m_KernelMeanShiftSize = cvSize(kernel_width,kernel_height); + + + /* Create kernels for histogram calculation: */ + if(m_KernelHistModel) cvReleaseMat(&m_KernelHistModel); + m_KernelHistModel = cvCreateMat(h, w, DefHistTypeMat); + calcKernelEpanechnikov(m_KernelHistModel); + if(m_KernelHistCandidate) cvReleaseMat(&m_KernelHistCandidate); + m_KernelHistCandidate = cvCreateMat(kernel_height, kernel_width, DefHistTypeMat); + calcKernelEpanechnikov(m_KernelHistCandidate); + + if(m_Weights) cvReleaseMat(&m_Weights); + m_Weights = cvCreateMat(kernel_height, kernel_width, CV_32F); + + 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; + double x0 = 0.5*(kernel_width-1); + double y0 = 0.5*(kernel_height-1); + if(m_KernelMeanShiftK[si]) cvReleaseMat(&m_KernelMeanShiftK[si]); + 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; ywidth; + int h = pKernel->height; + DefHistType Volume = 0; + int x0 = Center.x - w/2; + int y0 = Center.y - h/2; + int x,y; + + //cvZero(pHist); + cvSet(pHist,cvScalar(1.0/m_BinNumTotal)); /* no zero bins, all bins have very small value*/ + Volume = 1; + + if(m_Dim == 3) + { + for(y=0; y=pImg->height) continue; + if((y0+y)<0)continue; + 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=pImg->width) continue; + if((x0+x)<0)continue; + + if(pMaskData==NULL || pMaskData[x]>128) + { + DefHistType K = pKernelData[x]; + int index = HIST_INDEX(pImgData); + 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. */ + + if(pHistVolume)pHistVolume[0] = Volume; + + }; /* 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 */ + + void calcWeights(IplImage* pImg, IplImage* pImgFG, CvPoint Center) + { + cvZero(m_Weights); + + /* Calculate new position: */ + if(m_Dim == 3) + { + int x0 = Center.x - m_KernelMeanShiftSize.width/2; + int y0 = Center.y - m_KernelMeanShiftSize.height/2; + int x,y; + + assert(m_Weights->width == m_KernelMeanShiftSize.width); + assert(m_Weights->height == m_KernelMeanShiftSize.height); + + /* Calcualte shift vector: */ + for(y=0; y= pImg->height) continue; + + pImgData = &CV_IMAGE_ELEM(pImg,unsigned char,y+y0,x0*3); + 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= pImg->width) continue; + + index = HIST_INDEX(pImgData); + assert(index >= 0 && index < m_BinNumTotal); + + 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 */ + +public: + CvBlobTrackerOneMSFGS() + { + int i; + m_FGWeight = 0; + m_Alpha = 0.0; + + /* 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); + CommentParam("Alpha","Coefficient for model histogramm updating (0 - hist is not upated)"); + + m_BinBit=0; + m_Dim = 0; + m_HistModel = NULL; + m_HistCandidate = NULL; + m_HistTemp = NULL; + m_KernelHistModel = NULL; + m_KernelHistCandidate = NULL; + m_Weights = NULL; + + for(i=0; ipImg->width)w=pImg->width; + if(h>pImg->height)h=pImg->height; + ReAllocKernel(w,h); + 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; + + if(pBlobPrev) + { + m_Blob = pBlobPrev[0]; + } + + 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)); + + if(m_ObjSize.width != Size.width || m_ObjSize.height != Size.height) + { /* Reallocate kernels: */ + ReAllocKernel(Size.width,Size.height); + } /* Reallocate kernels. */ + + /* 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) + { + 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 0) + { + dx /= sum; + dy /= sum; + } + + m_Blob.x += dx; + m_Blob.y += dy; + + { /* Mean shift in scale space: */ + float news = 0; + float sum = 0; + float scale; + + Center = cvPoint(cvRound(m_Blob.x),cvRound(m_Blob.y)); + calcHist(pImg, NULL, Center, m_KernelHistCandidate, m_HistCandidate, &m_HistCandidateVolume); + calcWeights(pImg, pImgFG, Center); + //cvSet(m_Weights,cvScalar(1)); + + for(si=0; si0) + { + news /= sum; + } + + scale = (float)pow((double)SCALE_BASE,(double)news); + m_Blob.w *= scale; + m_Blob.h *= scale; + } /* Mean shift in scale space. */ + + /* Check fo finish: */ + if(fabs(dx)<0.1 && fabs(dy)<0.1) break; + + } /* Next iteration. */ + + if(m_Alpha>0) + { /* 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); + Vol = 0.5*(m_HistModelVolume + m_HistCandidateVolume); + WM = Vol*(1-m_Alpha)/m_HistModelVolume; + 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 histogram. */ + + return &m_Blob; + + }; /* Process */ + + virtual void Release(){delete this;}; +}; /*CvBlobTrackerOneMSFGS*/ + +CvBlobTrackerOne* cvCreateBlobTrackerOneMSFGS() +{ + return (CvBlobTrackerOne*) new CvBlobTrackerOneMSFGS; +} + +CvBlobTracker* cvCreateBlobTrackerMSFGS() +{ + return cvCreateBlobTrackerList(cvCreateBlobTrackerOneMSFGS); +} +