/*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. // // // License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2013, OpenCV Foundation, 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 the copyright holders 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 "precomp.hpp" #include <time.h> #include "PFSolver.hpp" #include "TrackingFunctionPF.hpp" #ifdef _WIN32 #define TIME( arg ) (((double) clock()) / CLOCKS_PER_SEC) #else #define TIME( arg ) (time( arg )) #endif namespace cv { /* * TrackerSamplerAlgorithm */ TrackerSamplerAlgorithm::~TrackerSamplerAlgorithm() { } bool TrackerSamplerAlgorithm::sampling( const Mat& image, Rect boundingBox, std::vector<Mat>& sample ) { if( image.empty() ) return false; return samplingImpl( image, boundingBox, sample ); } Ptr<TrackerSamplerAlgorithm> TrackerSamplerAlgorithm::create( const String& trackerSamplerType ) { if( trackerSamplerType.find( "CSC" ) == 0 ) { return Ptr<TrackerSamplerCSC>( new TrackerSamplerCSC() ); } if( trackerSamplerType.find( "CS" ) == 0 ) { return Ptr<TrackerSamplerCS>( new TrackerSamplerCS() ); } CV_Error( -1, "Tracker sampler algorithm type not supported" ); } String TrackerSamplerAlgorithm::getClassName() const { return className; } /** * TrackerSamplerCSC */ /** * Parameters */ TrackerSamplerCSC::Params::Params() { initInRad = 3; initMaxNegNum = 65; searchWinSize = 25; trackInPosRad = 4; trackMaxNegNum = 65; trackMaxPosNum = 100000; } TrackerSamplerCSC::TrackerSamplerCSC( const TrackerSamplerCSC::Params ¶meters ) : params( parameters ) { className = "CSC"; mode = MODE_INIT_POS; rng = RNG( uint64( TIME( 0 ) ) ); } TrackerSamplerCSC::~TrackerSamplerCSC() { } bool TrackerSamplerCSC::samplingImpl( const Mat& image, Rect boundingBox, std::vector<Mat>& sample ) { float inrad = 0; float outrad = 0; int maxnum = 0; switch ( mode ) { case MODE_INIT_POS: inrad = params.initInRad; sample = sampleImage( image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad ); break; case MODE_INIT_NEG: inrad = 2.0f * params.searchWinSize; outrad = 1.5f * params.initInRad; maxnum = params.initMaxNegNum; sample = sampleImage( image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad, outrad, maxnum ); break; case MODE_TRACK_POS: inrad = params.trackInPosRad; outrad = 0; maxnum = params.trackMaxPosNum; sample = sampleImage( image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad, outrad, maxnum ); break; case MODE_TRACK_NEG: inrad = 1.5f * params.searchWinSize; outrad = params.trackInPosRad + 5; maxnum = params.trackMaxNegNum; sample = sampleImage( image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad, outrad, maxnum ); break; case MODE_DETECT: inrad = params.searchWinSize; sample = sampleImage( image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad ); break; default: inrad = params.initInRad; sample = sampleImage( image, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height, inrad ); break; } return false; } void TrackerSamplerCSC::setMode( int samplingMode ) { mode = samplingMode; } std::vector<Mat> TrackerSamplerCSC::sampleImage( const Mat& img, int x, int y, int w, int h, float inrad, float outrad, int maxnum ) { int rowsz = img.rows - h - 1; int colsz = img.cols - w - 1; float inradsq = inrad * inrad; float outradsq = outrad * outrad; int dist; uint minrow = max( 0, (int) y - (int) inrad ); uint maxrow = min( (int) rowsz - 1, (int) y + (int) inrad ); uint mincol = max( 0, (int) x - (int) inrad ); uint maxcol = min( (int) colsz - 1, (int) x + (int) inrad ); //fprintf(stderr,"inrad=%f minrow=%d maxrow=%d mincol=%d maxcol=%d\n",inrad,minrow,maxrow,mincol,maxcol); std::vector<Mat> samples; samples.resize( ( maxrow - minrow + 1 ) * ( maxcol - mincol + 1 ) ); int i = 0; float prob = ( (float) ( maxnum ) ) / samples.size(); for ( int r = minrow; r <= int( maxrow ); r++ ) for ( int c = mincol; c <= int( maxcol ); c++ ) { dist = ( y - r ) * ( y - r ) + ( x - c ) * ( x - c ); if( float( rng.uniform( 0.f, 1.f ) ) < prob && dist < inradsq && dist >= outradsq ) { samples[i] = img( Rect( c, r, w, h ) ); i++; } } samples.resize( min( i, maxnum ) ); return samples; } ; /** * TrackerSamplerCS */ TrackerSamplerCS::Params::Params() { overlap = 0.99f; searchFactor = 2; } TrackerSamplerCS::TrackerSamplerCS( const TrackerSamplerCS::Params ¶meters ) : params( parameters ) { className = "CS"; mode = MODE_POSITIVE; } void TrackerSamplerCS::setMode( int samplingMode ) { mode = samplingMode; } TrackerSamplerCS::~TrackerSamplerCS() { } bool TrackerSamplerCS::samplingImpl( const Mat& image, Rect boundingBox, std::vector<Mat>& sample ) { trackedPatch = boundingBox; Size imageSize( image.cols, image.rows ); validROI = Rect( 0, 0, imageSize.width, imageSize.height ); Size trackedPatchSize( trackedPatch.width, trackedPatch.height ); Rect trackingROI = getTrackingROI( params.searchFactor ); sample = patchesRegularScan( image, trackingROI, trackedPatchSize ); return true; } Rect TrackerSamplerCS::getTrackingROI( float searchFactor ) { Rect searchRegion; searchRegion = RectMultiply( trackedPatch, searchFactor ); //check if( searchRegion.y + searchRegion.height > validROI.height ) searchRegion.height = validROI.height - searchRegion.y; if( searchRegion.x + searchRegion.width > validROI.width ) searchRegion.width = validROI.width - searchRegion.x; return searchRegion; } Rect TrackerSamplerCS::RectMultiply( const Rect & rect, float f ) { cv::Rect r_tmp; r_tmp.y = (int) ( rect.y - ( (float) rect.height * f - rect.height ) / 2 ); if( r_tmp.y < 0 ) r_tmp.y = 0; r_tmp.x = (int) ( rect.x - ( (float) rect.width * f - rect.width ) / 2 ); if( r_tmp.x < 0 ) r_tmp.x = 0; r_tmp.height = (int) ( rect.height * f ); r_tmp.width = (int) ( rect.width * f ); return r_tmp; } Rect TrackerSamplerCS::getROI() const { return ROI; } void TrackerSamplerCS::setCheckedROI( Rect imageROI ) { int dCol, dRow; dCol = imageROI.x - validROI.x; dRow = imageROI.y - validROI.y; ROI.y = ( dRow < 0 ) ? validROI.y : imageROI.y; ROI.x = ( dCol < 0 ) ? validROI.x : imageROI.x; dCol = imageROI.x + imageROI.width - ( validROI.x + validROI.width ); dRow = imageROI.y + imageROI.height - ( validROI.y + validROI.height ); ROI.height = ( dRow > 0 ) ? validROI.height + validROI.y - ROI.y : imageROI.height + imageROI.y - ROI.y; ROI.width = ( dCol > 0 ) ? validROI.width + validROI.x - ROI.x : imageROI.width + imageROI.x - ROI.x; } std::vector<Mat> TrackerSamplerCS::patchesRegularScan( const Mat& image, Rect trackingROI, Size patchSize ) { std::vector<Mat> sample; if( ( validROI == trackingROI ) ) ROI = trackingROI; else setCheckedROI( trackingROI ); if( mode == MODE_POSITIVE ) { int num = 4; sample.resize( num ); Mat singleSample = image( trackedPatch ); for ( int i = 0; i < num; i++ ) sample[i] = singleSample; return sample; } int stepCol = (int) floor( ( 1.0f - params.overlap ) * (float) patchSize.width + 0.5f ); int stepRow = (int) floor( ( 1.0f - params.overlap ) * (float) patchSize.height + 0.5f ); if( stepCol <= 0 ) stepCol = 1; if( stepRow <= 0 ) stepRow = 1; Size m_patchGrid; Rect m_rectUpperLeft; Rect m_rectUpperRight; Rect m_rectLowerLeft; Rect m_rectLowerRight; int num; m_patchGrid.height = ( (int) ( (float) ( ROI.height - patchSize.height ) / stepRow ) + 1 ); m_patchGrid.width = ( (int) ( (float) ( ROI.width - patchSize.width ) / stepCol ) + 1 ); num = m_patchGrid.width * m_patchGrid.height; sample.resize( num ); int curPatch = 0; m_rectUpperLeft = m_rectUpperRight = m_rectLowerLeft = m_rectLowerRight = cv::Rect( 0, 0, patchSize.width, patchSize.height ); m_rectUpperLeft.y = ROI.y; m_rectUpperLeft.x = ROI.x; m_rectUpperRight.y = ROI.y; m_rectUpperRight.x = ROI.x + ROI.width - patchSize.width; m_rectLowerLeft.y = ROI.y + ROI.height - patchSize.height; m_rectLowerLeft.x = ROI.x; m_rectLowerRight.y = ROI.y + ROI.height - patchSize.height; m_rectLowerRight.x = ROI.x + ROI.width - patchSize.width; if( mode == MODE_NEGATIVE ) { int numSamples = 4; sample.resize( numSamples ); sample[0] = image( m_rectUpperLeft ); sample[1] = image( m_rectUpperRight ); sample[2] = image( m_rectLowerLeft ); sample[3] = image( m_rectLowerRight ); return sample; } int numPatchesX; int numPatchesY; numPatchesX = 0; numPatchesY = 0; for ( int curRow = 0; curRow < ROI.height - patchSize.height + 1; curRow += stepRow ) { numPatchesY++; for ( int curCol = 0; curCol < ROI.width - patchSize.width + 1; curCol += stepCol ) { if( curRow == 0 ) numPatchesX++; Mat singleSample = image( Rect( curCol + ROI.x, curRow + ROI.y, patchSize.width, patchSize.height ) ); sample[curPatch] = singleSample; curPatch++; } } CV_Assert( curPatch == num ); return sample; } TrackerSamplerPF::Params::Params(){ iterationNum=20; particlesNum=100; alpha=0.9; std=(Mat_<double>(1,4)<<15.0,15.0,15.0,15.0); } TrackerSamplerPF::TrackerSamplerPF(const Mat& chosenRect,const TrackerSamplerPF::Params ¶meters): params( parameters ),_function(new TrackingFunctionPF(chosenRect)){ className="PF"; _solver=createPFSolver(_function,parameters.std,TermCriteria(TermCriteria::MAX_ITER,parameters.iterationNum,0.0), parameters.particlesNum,parameters.alpha); } bool TrackerSamplerPF::samplingImpl( const Mat& image, Rect boundingBox, std::vector<Mat>& sample ){ Ptr<TrackerTargetState> ptr; Mat_<double> _last_guess=(Mat_<double>(1,4)<<(double)boundingBox.x,(double)boundingBox.y, (double)boundingBox.x+boundingBox.width,(double)boundingBox.y+boundingBox.height); PFSolver* promoted_solver=dynamic_cast<PFSolver*>(static_cast<MinProblemSolver*>(_solver)); promoted_solver->setParamsSTD(params.std); promoted_solver->minimize(_last_guess); dynamic_cast<TrackingFunctionPF*>(static_cast<MinProblemSolver::Function*>(promoted_solver->getFunction()))->update(image); while(promoted_solver->iteration() <= promoted_solver->getTermCriteria().maxCount); promoted_solver->getOptParam(_last_guess); Rect res=Rect(Point_<int>((int)_last_guess(0,0),(int)_last_guess(0,1)),Point_<int>((int)_last_guess(0,2),(int)_last_guess(0,3))); sample.clear(); sample.push_back(image(res)); return true; } } /* namespace cv */