You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
12 KiB
414 lines
12 KiB
/*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" ); |
|
return Ptr<TrackerSamplerAlgorithm>(); |
|
} |
|
|
|
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<optim::Solver*>(_solver)); |
|
|
|
promoted_solver->setParamsSTD(params.std); |
|
promoted_solver->minimize(_last_guess); |
|
dynamic_cast<TrackingFunctionPF*>(static_cast<optim::Solver::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 */
|
|
|