mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-21 23:01:45 +08:00
Updated the support for color-names features and fixing some typos
This commit is contained in:
@@ -1189,8 +1189,8 @@ class CV_EXPORTS_W TrackerTLD : public Tracker
|
|||||||
BOILERPLATE_CODE("TLD",TrackerTLD);
|
BOILERPLATE_CODE("TLD",TrackerTLD);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief KCF is a novel tracking framework that utilize properties of circulant matrix to enhance the processing speed.
|
/** @brief KCF is a novel tracking framework that utilizes properties of circulant matrix to enhance the processing speed.
|
||||||
* This tracking method is implementation of @cite KCF_ECCV which is extended to KFC with color-names features (@cite KCF_CN).
|
* This tracking method is an implementation of @cite KCF_ECCV which is extended to KFC with color-names features (@cite KCF_CN).
|
||||||
* The original paper of KCF is available at <http://home.isr.uc.pt/~henriques/circulant/index.html>
|
* The original paper of KCF is available at <http://home.isr.uc.pt/~henriques/circulant/index.html>
|
||||||
* as well as the matlab implementation. For more information about KCF with color-names features, please refer to
|
* as well as the matlab implementation. For more information about KCF with color-names features, please refer to
|
||||||
* <http://www.cvl.isy.liu.se/research/objrec/visualtracking/colvistrack/index.html>.
|
* <http://www.cvl.isy.liu.se/research/objrec/visualtracking/colvistrack/index.html>.
|
||||||
|
@@ -88,8 +88,11 @@ namespace cv{
|
|||||||
* KCF functions and vars
|
* KCF functions and vars
|
||||||
*/
|
*/
|
||||||
void createHanningWindow(OutputArray _dst, const cv::Size winSize, const int type) const;
|
void createHanningWindow(OutputArray _dst, const cv::Size winSize, const int type) const;
|
||||||
|
void inline fft2(const Mat src, std::vector<Mat> & dest) const;
|
||||||
void inline fft2(const Mat src, Mat & dest) const;
|
void inline fft2(const Mat src, Mat & dest) const;
|
||||||
void inline ifft2(const Mat src, Mat & dest) const ;
|
void inline ifft2(const Mat src, Mat & dest) const ;
|
||||||
|
void inline pixelWiseMult(const std::vector<Mat> src1, const std::vector<Mat> src2, std::vector<Mat> & dest, const int flags, const bool conjB=false) const;
|
||||||
|
void inline sumChannels(std::vector<Mat> src, Mat & dest) const;
|
||||||
bool getSubWindow(const Mat img, const Rect roi, Mat& patch) const;
|
bool getSubWindow(const Mat img, const Rect roi, Mat& patch) const;
|
||||||
void extractCN(Mat _patch, Mat & cnFeatures) const;
|
void extractCN(Mat _patch, Mat & cnFeatures) const;
|
||||||
void denseGaussKernel(const double sigma, const Mat _x, const Mat _y, Mat & _k) const;
|
void denseGaussKernel(const double sigma, const Mat _x, const Mat _y, Mat & _k) const;
|
||||||
@@ -127,6 +130,8 @@ namespace cv{
|
|||||||
{
|
{
|
||||||
isInit = false;
|
isInit = false;
|
||||||
resizeImage = false;
|
resizeImage = false;
|
||||||
|
|
||||||
|
CV_Assert(params.descriptor == GRAY || params.descriptor == CN /*|| params.descriptor == CN2*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackerKCFImpl::read( const cv::FileNode& fn ){
|
void TrackerKCFImpl::read( const cv::FileNode& fn ){
|
||||||
@@ -163,7 +168,7 @@ namespace cv{
|
|||||||
|
|
||||||
// add padding to the roi
|
// add padding to the roi
|
||||||
roi.x-=roi.width/2;
|
roi.x-=roi.width/2;
|
||||||
roi.y-=roi.height/2+1;
|
roi.y-=roi.height/2;
|
||||||
roi.width*=2;
|
roi.width*=2;
|
||||||
roi.height*=2;
|
roi.height*=2;
|
||||||
|
|
||||||
@@ -173,7 +178,6 @@ namespace cv{
|
|||||||
Mat layers[] = {hann, hann, hann, hann, hann, hann, hann, hann, hann, hann};
|
Mat layers[] = {hann, hann, hann, hann, hann, hann, hann, hann, hann, hann};
|
||||||
merge(layers, 10, hann);
|
merge(layers, 10, hann);
|
||||||
}
|
}
|
||||||
if(params.descriptor != GRAY){printf("The choosen descriptor mode is not available! Please use GRAY descriptor, other descriptors will be avaiable soon.\n");return false;}//temporary, will be updated soon
|
|
||||||
|
|
||||||
// create gaussian response
|
// create gaussian response
|
||||||
y=Mat::zeros((int)roi.height,(int)roi.width,CV_64F);
|
y=Mat::zeros((int)roi.height,(int)roi.width,CV_64F);
|
||||||
@@ -229,18 +233,19 @@ namespace cv{
|
|||||||
|
|
||||||
// Kernel Regularized Least-Squares, calculate alphas
|
// Kernel Regularized Least-Squares, calculate alphas
|
||||||
denseGaussKernel(params.sigma,x,x,k);
|
denseGaussKernel(params.sigma,x,x,k);
|
||||||
|
|
||||||
fft2(k,kf);
|
fft2(k,kf);
|
||||||
kf=kf+params.lambda;
|
kf=kf+params.lambda;
|
||||||
|
|
||||||
/* TODO: optimize this element-wise division
|
/* TODO: optimize this element-wise division
|
||||||
* new_alphaf=yf./kf
|
* new_alphaf=yf./kf
|
||||||
* z=[(ax+bd)+i(bc-ad)]/(c^2+d^2)
|
* z=(a+bi)/(c+di)[(ac+bd)+i(bc-ad)]/(c^2+d^2)
|
||||||
*/
|
*/
|
||||||
new_alphaf=Mat_<Vec2d >(yf.rows, yf.cols);
|
new_alphaf=Mat_<Vec2d >(yf.rows, yf.cols);
|
||||||
std::complex<double> temp;
|
std::complex<double> temp;
|
||||||
for(int i=0;i<yf.rows;i++){
|
for(int i=0;i<yf.rows;i++){
|
||||||
for(int j=0;j<yf.cols;j++){
|
for(int j=0;j<yf.cols;j++){
|
||||||
temp=std::complex<double>(yf.at<Vec2d>(i,j)[0],yf.at<Vec2d>(i,j)[1])/(std::complex<double>(kf.at<Vec2d>(i,j)[0],kf.at<Vec2d>(i,j)[1])/*+complex<float>(0.0000000001,0.0000000001)*/);
|
temp=std::complex<double>(yf.at<Vec2d>(i,j)[0],yf.at<Vec2d>(i,j)[1])/(std::complex<double>(kf.at<Vec2d>(i,j)[0],kf.at<Vec2d>(i,j)[1])/*+std::complex<double>(0.0000000001,0.0000000001)*/);
|
||||||
new_alphaf.at<Vec2d >(i,j)[0]=temp.real();
|
new_alphaf.at<Vec2d >(i,j)[0]=temp.real();
|
||||||
new_alphaf.at<Vec2d >(i,j)[1]=temp.imag();
|
new_alphaf.at<Vec2d >(i,j)[1]=temp.imag();
|
||||||
}
|
}
|
||||||
@@ -250,7 +255,7 @@ namespace cv{
|
|||||||
new_z=x.clone();
|
new_z=x.clone();
|
||||||
if(frame==0){
|
if(frame==0){
|
||||||
alphaf=new_alphaf.clone();
|
alphaf=new_alphaf.clone();
|
||||||
z=x;
|
z=x.clone();
|
||||||
}else{
|
}else{
|
||||||
alphaf=(1.0-params.interp_factor)*alphaf+params.interp_factor*new_alphaf;
|
alphaf=(1.0-params.interp_factor)*alphaf+params.interp_factor*new_alphaf;
|
||||||
z=(1.0-params.interp_factor)*z+params.interp_factor*new_z;
|
z=(1.0-params.interp_factor)*z+params.interp_factor*new_z;
|
||||||
@@ -309,21 +314,62 @@ namespace cv{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* simplification of fourier transoform function in opencv
|
* simplification of fourier transform function in opencv
|
||||||
*/
|
*/
|
||||||
void inline TrackerKCFImpl::fft2(const Mat src, Mat & dest)const {
|
void inline TrackerKCFImpl::fft2(const Mat src, Mat & dest)const {
|
||||||
Mat planes[] = {Mat_<double>(src), Mat::zeros(src.size(), CV_64F)};
|
std::vector<Mat> layers(src.channels());
|
||||||
merge(planes, 2, dest);
|
std::vector<Mat> outputs(src.channels());
|
||||||
dft(dest,dest,DFT_COMPLEX_OUTPUT);
|
|
||||||
|
split(src, layers);
|
||||||
|
|
||||||
|
for(int i=0;i<src.channels();i++){
|
||||||
|
dft(layers[i],outputs[i],DFT_COMPLEX_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
merge(outputs,dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inline TrackerKCFImpl::fft2(const Mat src, std::vector<Mat> & dest) const{
|
||||||
|
std::vector<Mat> layers(src.channels());
|
||||||
|
dest.clear();
|
||||||
|
dest.resize(src.channels());
|
||||||
|
|
||||||
|
split(src, layers);
|
||||||
|
|
||||||
|
for(int i=0;i<src.channels();i++){
|
||||||
|
dft(layers[i],dest[i],DFT_COMPLEX_OUTPUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* simplification of inverse fourier transoform function in opencv
|
* simplification of inverse fourier transform function in opencv
|
||||||
*/
|
*/
|
||||||
void inline TrackerKCFImpl::ifft2(const Mat src, Mat & dest)const {
|
void inline TrackerKCFImpl::ifft2(const Mat src, Mat & dest)const {
|
||||||
idft(src,dest,DFT_SCALE+DFT_REAL_OUTPUT);
|
idft(src,dest,DFT_SCALE+DFT_REAL_OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-wise multiplication of two Multichannel Mat data
|
||||||
|
*/
|
||||||
|
void inline TrackerKCFImpl::pixelWiseMult(const std::vector<Mat> src1, const std::vector<Mat> src2, std::vector<Mat> & dest, const int flags, const bool conjB) const{
|
||||||
|
dest.clear();
|
||||||
|
dest.resize(src1.size());
|
||||||
|
|
||||||
|
for(unsigned i=0;i<src1.size();i++){
|
||||||
|
mulSpectrums(src1[i], src2[i], dest[i],flags,conjB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Combines all channels in a multi-channels Mat data into a single channel
|
||||||
|
*/
|
||||||
|
void inline TrackerKCFImpl::sumChannels(std::vector<Mat> src, Mat & dest) const{
|
||||||
|
dest=src[0].clone();
|
||||||
|
for(unsigned i=1;i<src.size();i++){
|
||||||
|
dest+=src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* obtain the patch and apply hann window filter to it
|
* obtain the patch and apply hann window filter to it
|
||||||
*/
|
*/
|
||||||
@@ -356,24 +402,24 @@ namespace cv{
|
|||||||
addRight=(_roi.width+_roi.x>img.cols?_roi.width+_roi.x-img.cols:0);
|
addRight=(_roi.width+_roi.x>img.cols?_roi.width+_roi.x-img.cols:0);
|
||||||
|
|
||||||
copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE);
|
copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE);
|
||||||
|
if(patch.rows==0 || patch.cols==0)return false;
|
||||||
|
|
||||||
// extract the desired descriptors
|
// extract the desired descriptors
|
||||||
switch(params.descriptor){
|
switch(params.descriptor){
|
||||||
case GRAY:
|
case GRAY:
|
||||||
if(img.channels()>1)cvtColor(patch,patch, CV_BGR2GRAY);
|
if(img.channels()>1)cvtColor(patch,patch, CV_BGR2GRAY);
|
||||||
|
patch.convertTo(patch,CV_64F);
|
||||||
|
patch=patch/255.0-0.5; // normalize to range -0.5 .. 0.5
|
||||||
break;
|
break;
|
||||||
case CN:
|
case CN:
|
||||||
CV_Assert(img.channels() == 3);
|
CV_Assert(img.channels() == 3);
|
||||||
extractCN(patch,patch);
|
extractCN(patch,patch);
|
||||||
break;
|
break;
|
||||||
default:
|
case CN2:
|
||||||
if(patch.channels()>1)cvtColor(patch,patch, CV_BGR2GRAY);
|
if(patch.channels()>1)cvtColor(patch,patch, CV_BGR2GRAY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
patch.convertTo(patch,CV_64F);
|
|
||||||
|
|
||||||
patch=patch/255.0-0.5; // normalize to range -0.5 .. 0.5
|
|
||||||
patch=patch.mul(hann); // hann window filter
|
patch=patch.mul(hann); // hann window filter
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -407,25 +453,26 @@ namespace cv{
|
|||||||
* dense gauss kernel function
|
* dense gauss kernel function
|
||||||
*/
|
*/
|
||||||
void TrackerKCFImpl::denseGaussKernel(const double sigma, const Mat _x, const Mat _y, Mat & _k)const{
|
void TrackerKCFImpl::denseGaussKernel(const double sigma, const Mat _x, const Mat _y, Mat & _k)const{
|
||||||
Mat _xf, _yf, xyf,xy;
|
std::vector<Mat> _xf,_yf,xyf_v;
|
||||||
|
Mat xy,xyf;
|
||||||
double normX, normY;
|
double normX, normY;
|
||||||
|
|
||||||
fft2(_x,_xf);
|
fft2(_x,_xf);
|
||||||
fft2(_y,_yf);
|
fft2(_y,_yf);
|
||||||
|
|
||||||
normX=norm(_x);
|
normX=norm(_x);
|
||||||
normX*=normX;
|
normX*=normX;
|
||||||
normY=norm(_y);
|
normY=norm(_y);
|
||||||
normY*=normY;
|
normY*=normY;
|
||||||
|
|
||||||
mulSpectrums(_xf,_yf,xyf,0,true);
|
pixelWiseMult(_xf,_yf,xyf_v,0,true);
|
||||||
|
sumChannels(xyf_v,xyf);
|
||||||
ifft2(xyf,xyf);
|
ifft2(xyf,xyf);
|
||||||
shiftRows(xyf, _x.rows/2);
|
// shiftRows(xyf, _x.rows/2);
|
||||||
shiftCols(xyf,_x.cols/2);
|
// shiftCols(xyf, _x.cols/2);
|
||||||
|
|
||||||
//(xx + yy - 2 * xy) / numel(x)
|
//(xx + yy - 2 * xy) / numel(x)
|
||||||
xy=(normX+normY-2*xyf)/(_x.rows*_x.cols);
|
xy=(normX+normY-2*xyf)/(_x.rows*_x.cols*_x.channels());
|
||||||
|
|
||||||
|
|
||||||
// TODO: check wether we really need thresholding or not
|
// TODO: check wether we really need thresholding or not
|
||||||
//threshold(xy,xy,0.0,0.0,THRESH_TOZERO);//max(0, (xx + yy - 2 * xy) / numel(x))
|
//threshold(xy,xy,0.0,0.0,THRESH_TOZERO);//max(0, (xx + yy - 2 * xy) / numel(x))
|
||||||
@@ -441,7 +488,7 @@ namespace cv{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CIRCULAR SHIT Function
|
/* CIRCULAR SHIFT Function
|
||||||
* http://stackoverflow.com/questions/10420454/shift-like-matlab-function-rows-or-columns-of-a-matrix-in-opencv
|
* http://stackoverflow.com/questions/10420454/shift-like-matlab-function-rows-or-columns-of-a-matrix-in-opencv
|
||||||
*/
|
*/
|
||||||
// circular shift one row from up to down
|
// circular shift one row from up to down
|
||||||
@@ -523,16 +570,12 @@ namespace cv{
|
|||||||
interp_factor=0.075;
|
interp_factor=0.075;
|
||||||
output_sigma_factor=1.0/16.0;
|
output_sigma_factor=1.0/16.0;
|
||||||
resize=true;
|
resize=true;
|
||||||
max_patch_size=80*80;
|
max_patch_size=100*100;
|
||||||
descriptor=GRAY;
|
descriptor=CN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackerKCF::Params::read( const cv::FileNode& /*fn*/ ){
|
void TrackerKCF::Params::read( const cv::FileNode& /*fn*/ ){}
|
||||||
|
|
||||||
}
|
void TrackerKCF::Params::write( cv::FileStorage& /*fs*/ ) const{}
|
||||||
|
|
||||||
void TrackerKCF::Params::write( cv::FileStorage& /*fs*/ ) const{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace cv */
|
} /* namespace cv */
|
||||||
|
Reference in New Issue
Block a user