This little example demonstrates the most simple case of usage of the Tracker class. It also demonstrates that it is neccessary to extract the tracking information and store them externally.
#include <bias_config.h>
#include <Base/Common/BIASpragma.hh>
#include <Matcher2D/Tracker.hh>
#include <Base/ImageUtils/ImageDraw.hh>
#include <Base/Image/ImageConvert.hh>
#include <Base/Image/ImageIO.hh>
#include <Image/PyramidImage.hh>
#include <FeatureDetector/CornerDetectorKLT.hh>
#include <Base/Math/Random.hh>
#define TIMING
#ifdef TIMING
#include <Base/Debug/TimeMeasure.hh>
#endif
#include <deque>
using namespace BIAS;
using namespace std;
#define StorageType float
#define CalculationType float
#define DEBUG 1
deque<vector<HomgPoint2D> > p;
deque<vector<KLT_TYPE> > residui;
deque<vector<int> > results;
deque<vector<Matrix<double> > > cov;
vector<HomgPoint2D> mp;
vector<QUAL> qual;
vector<HomgPoint2D> cp;
vector<KLT_TYPE> r;
vector<int> res;
vector<Matrix<double> > tmp_cov;
const int max_num_points = 150;
deque<vector<HomgPoint2D> >& p,
{
bool draw_tracks=true;
bool draw_cov=false;
double cov_scale=3e2;
} else {
}
unsigned char col[]={255, 0, 0};
unsigned char colgreen[]={0, 255, 0};
const int nump=p[0].size();
unsigned start[2], end[2];
const unsigned radius=1;
int maxhist=0;
double center[2], a[2], b[2], eva, evb;
if (imnum>0){
for (int l=0; l<nump; l++){
if (!p[imnum][l].IsAtInfinity() && !p[imnum-1][l].IsAtInfinity()){
if (draw_cov){
center[0]=p[imnum][l][0];
center[1]=p[imnum][l][1];
int covoffset = cov[imnum][l].GetRows()-2;
for (int row=0; row<2; row++)
for (int col=0; col<2; col++)
curcov[row][col] = cov[imnum][l][row+covoffset][col+covoffset];
eva=sqrt(eva);
evb=sqrt(evb);
a[0]=na[0]*eva*cov_scale;
a[1]=na[1]*eva*cov_scale;
b[0]=nb[0]*evb*cov_scale;
b[1]=nb[1]*evb*cov_scale;
}
start[0]=(unsigned)rint(p[imnum][l][0]);
start[1]=(unsigned)rint(p[imnum][l][1]);
radius, col);
if (draw_tracks){
for (int i=imnum; i>0; i--){
if (p[i-1][l].IsAtInfinity()) {
if ((imnum-i)>maxhist) maxhist=imnum-i;
break;
}
start[0]=(unsigned)rint(p[i][l][0]);
start[1]=(unsigned)rint(p[i][l][1]);
end[0]=(unsigned)rint(p[i-1][l][0]);
end[1]=(unsigned)rint(p[i-1][l][1]);
if (i-1==0) maxhist=imnum;
}
}
}
}
} else {
for (int l=0; l<nump; l++){
if (!p[imnum][l].IsAtInfinity()){
start[0]=(unsigned)rint(p[imnum][l][0]);
start[1]=(unsigned)rint(p[imnum][l][1]);
radius, colgreen);
}
}
}
}
void DumpTracks(deque<vector<HomgPoint2D> >& p)
{
int numim=0;
while (p[numim].size()>0 && numim<(int)p.size()) numim++;
for (unsigned l=0; l<p[0].size(); l++){
cout <<setw(3)<<l<<" : ";
for (int i=0; i<numim; i++){
cout.precision(4);
fprintf(stdout, "%i:(%5.1f, %5.1f) ", i, p[i][l][0], p[i][l][1]);
}
cout << endl;
}
}
void InsertZeroPoints(deque<vector<HomgPoint2D> >& p, int i)
{
if (i>0){
const int nump=p[i].size();
for (int k=0; k<nump; k++){
if (p[i][k].IsAtInfinity() && !p[i-1][k].IsAtInfinity()){
p[i-1][k].Set(0.0, 0.0, 0.0);
}
}
}
}
int main(int argc, char *argv[])
{
bool prefilter = true;
bool testBrightnessVariation = true;
hws.newsize(5);
hws[4] =hws[3] = hws[2] =hws[1] =hws[0] = 10;
tr.SetHalfWinSize(hws);
tr.SetRejectionType(-1);
tr.SetAffineBrightnessInvariance(testBrightnessVariation);
maxit.newsize(5);
maxit[4] =maxit[3] = maxit[2] =maxit[1] =maxit[0] = 50;
tr.SetMaxIterations(maxit);
for (int i=0; i<2; i++){
}
int argind = 1;
if (argc-argind<2 || argind<1){
cerr << argv[0] << " [parameter] <im1> <im2> [ <im3> ... ] \n";
return -2;
}
int act=0;
int num=0;
#ifdef TIMING
#endif
for (int i=argind; i<argc; i++){
act=!act;
BIASERR("error loading image "<<argv[i]);
return -1;
} else {
if (DEBUG) cerr << "read "<<argv[i]<<endl;
#ifdef TIMING
cerr << "---------------"<<argv[i]<<"---------------\n";
#endif
}
BIASERR("error converting image "<<argv[i]);
}
BIASERR("error converting image to grey"<<argv[i]);
}
}
if (testBrightnessVariation) {
cout<<"scaling with "<<scale<<" and shifting "<<shift<<endl;
if (*pimdata<0.0) *pimdata = 0.0;
if (*pimdata>255.0) *pimdata = 255.0;
pimdata++;
}
}
#ifdef TIMING
cerr <<
"loading and converting to float/grey took "<<timer.
GetRealTime()<<
" us\n";
#endif
if (prefilter)
{
tr.PreparePyramide(im, *pim[act], *gx[act], *gy[act]);
}
else
{
tr.PreparePyramide(im, *pim[act]);
}
#ifdef TIMING
cerr <<
"pyramid preparation took "<<timer.
GetRealTime()<<
" us\n";
#endif
if (prefilter)
{
num=tr.Track(*pim[act], *gx[act], *gy[act]);
}
else
{
num=tr.Track(*pim[act]);
}
#ifdef TIMING
cerr <<
"tracking took "<<timer.
GetRealTime()<<
" us for "<<num<<
" corners\n";
#endif
if (i==argind){
if (!prefilter)
{
tr.PreparePyramide(im, *pim[act], *gx[act], *gy[act]);
}
cd.
Detect(*(*gx[act])[0], *(*gy[act])[0], mp, qual);
cout << "initially found "<<mp.size()<<" points\n";
if ((int)mp.size() > (int)max_num_points)
{
mp.erase(mp.begin() + max_num_points, mp.end());
qual.erase(qual.begin() + max_num_points, qual.end());
}
tr.ReplaceAllPoints(mp, qual);
#ifdef TIMING
cerr <<
"corner detection took "<<timer.
GetRealTime()<<
" us\n";
#endif
}
tr.GetPoints(mp);
p.push_back(mp);
tr.GetResiduiMAD(r);
residui.push_back(r);
tr.GetResults(res);
results.push_back(res);
tr.GetCovariances(tmp_cov);
cov.push_back(tmp_cov);
#ifdef TIMING
cerr <<
"get results took "<<timer.
GetRealTime()<<
" us\n";
#endif
#ifdef TIMING
cerr <<
"corner detection took "<<timer.
GetRealTime()<<
" us\n";
#endif
Draw(*(*pim[act])[0], rgbim, p, cov, i-argind);
ostringstream name;
name << "track-"<<setw(4)<<setfill('0')<<i-argind<<".mip";
#ifdef TIMING
cerr <<
"drawing/writing took "<<timer.
GetRealTime()<<
" us\n";
#endif
}
return 0;
}