34 #include <bias_config.h>
36 #include <Base/Common/BIASpragma.hh>
38 #include <Matcher2D/Tracker.hh>
39 #include <Base/ImageUtils/ImageDraw.hh>
40 #include <Base/Image/ImageConvert.hh>
41 #include <Base/Image/ImageIO.hh>
42 #include <Image/PyramidImage.hh>
43 #include <FeatureDetector/CornerDetectorKLT.hh>
44 #include <Base/Math/Random.hh>
48 #include <Base/Debug/TimeMeasure.hh>
57 #define StorageType float
58 #define CalculationType float
64 deque<vector<HomgPoint2D> > p;
65 deque<vector<KLT_TYPE> > residui;
68 deque<vector<int> > results;
70 deque<vector<Matrix<double> > > cov;
73 vector<HomgPoint2D> mp;
75 vector<HomgPoint2D> cp;
78 vector<Matrix<double> > tmp_cov;
82 const int max_num_points = 150;
87 deque<vector<HomgPoint2D> >& p,
91 bool draw_tracks=
true;
108 unsigned char col[]={255, 0, 0};
109 unsigned char colgreen[]={0, 255, 0};
110 const int nump=p[0].size();
111 unsigned start[2], end[2];
112 const unsigned radius=1;
114 double center[2], a[2], b[2], eva, evb;
118 for (
int l=0; l<nump; l++){
119 if (!p[imnum][l].IsAtInfinity() && !p[imnum-1][l].IsAtInfinity()){
121 center[0]=p[imnum][l][0];
122 center[1]=p[imnum][l][1];
128 int covoffset = cov[imnum][l].GetRows()-2;
129 for (
int row=0; row<2; row++)
130 for (
int col=0; col<2; col++)
131 curcov[row][col] = cov[imnum][l][row+covoffset][col+covoffset];
138 a[0]=na[0]*eva*cov_scale;
139 a[1]=na[1]*eva*cov_scale;
140 b[0]=nb[0]*evb*cov_scale;
141 b[1]=nb[1]*evb*cov_scale;
145 Ellipse(im, center, a, b, col);
148 start[0]=(unsigned)rint(p[imnum][l][0]);
149 start[1]=(unsigned)rint(p[imnum][l][1]);
155 for (
int i=imnum; i>0; i--){
156 if (p[i-1][l].IsAtInfinity()) {
157 if ((imnum-i)>maxhist) maxhist=imnum-i;
160 start[0]=(unsigned)rint(p[i][l][0]);
161 start[1]=(unsigned)rint(p[i][l][1]);
162 end[0]=(unsigned)rint(p[i-1][l][0]);
163 end[1]=(unsigned)rint(p[i-1][l][1]);
164 if (i-1==0) maxhist=imnum;
173 for (
int l=0; l<nump; l++){
174 if (!p[imnum][l].IsAtInfinity()){
176 start[0]=(unsigned)rint(p[imnum][l][0]);
177 start[1]=(unsigned)rint(p[imnum][l][1]);
187 void DumpTracks(deque<vector<HomgPoint2D> >& p)
190 while (p[numim].size()>0 && numim<(
int)p.size()) numim++;
191 for (
unsigned l=0; l<p[0].size(); l++){
192 cout <<setw(3)<<l<<
" : ";
193 for (
int i=0; i<numim; i++){
195 fprintf(stdout,
"%i:(%5.1f, %5.1f) ", i, p[i][l][0], p[i][l][1]);
203 void InsertZeroPoints(deque<vector<HomgPoint2D> >& p,
int i)
206 const int nump=p[i].size();
208 for (
int k=0; k<nump; k++){
209 if (p[i][k].IsAtInfinity() && !p[i-1][k].IsAtInfinity()){
210 p[i-1][k].Set(0.0, 0.0, 0.0);
217 int main(
int argc,
char *argv[])
219 bool prefilter =
true;
220 bool testBrightnessVariation =
true;
235 hws[4] =hws[3] = hws[2] =hws[1] =hws[0] = 10;
236 tr.SetHalfWinSize(hws);
237 tr.SetRejectionType(-1);
238 tr.SetAffineBrightnessInvariance(testBrightnessVariation);
242 maxit[4] =maxit[3] = maxit[2] =maxit[1] =maxit[0] = 50;
243 tr.SetMaxIterations(maxit);
252 for (
int i=0; i<2; i++){
266 if (argc-argind<2 || argind<1){
267 cerr << argv[0] <<
" [parameter] <im1> <im2> [ <im3> ... ] \n";
284 for (
int i=argind; i<argc; i++){
290 BIASERR(
"error loading image "<<argv[i]);
293 if (DEBUG) cerr <<
"read "<<argv[i]<<endl;
295 cerr <<
"---------------"<<argv[i]<<
"---------------\n";
302 BIASERR(
"error converting image "<<argv[i]);
308 BIASERR(
"error converting image to grey"<<argv[i]);
311 if (testBrightnessVariation) {
314 cout<<
"scaling with "<<scale<<
" and shifting "<<shift<<endl;
318 if (*pimdata<0.0) *pimdata = 0.0;
319 if (*pimdata>255.0) *pimdata = 255.0;
328 cerr <<
"loading and converting to float/grey took "<<timer.
GetRealTime()<<
" us\n";
337 tr.PreparePyramide(im, *pim[act], *gx[act], *gy[act]);
341 tr.PreparePyramide(im, *pim[act]);
346 cerr <<
"pyramid preparation took "<<timer.
GetRealTime()<<
" us\n";
354 num=tr.Track(*pim[act], *gx[act], *gy[act]);
358 num=tr.Track(*pim[act]);
363 cerr <<
"tracking took "<<timer.
GetRealTime()<<
" us for "<<num<<
" corners\n";
364 cerr <<
" = "<<timer.
GetCycleCount()/num<<
" fps/corner/frame\n";
373 tr.PreparePyramide(im, *pim[act], *gx[act], *gy[act]);
375 cd.
Detect(*(*gx[act])[0], *(*gy[act])[0], mp, qual);
376 cout <<
"initially found "<<mp.size()<<
" points\n";
381 if ((
int)mp.size() > (int)max_num_points)
383 mp.erase(mp.begin() + max_num_points, mp.end());
384 qual.erase(qual.begin() + max_num_points, qual.end());
386 tr.ReplaceAllPoints(mp, qual);
390 cerr <<
"corner detection took "<<timer.
GetRealTime()<<
" us\n";
402 residui.push_back(r);
405 results.push_back(res);
407 tr.GetCovariances(tmp_cov);
408 cov.push_back(tmp_cov);
412 cerr <<
"get results took "<<timer.
GetRealTime()<<
" us\n";
451 cerr <<
"corner detection took "<<timer.
GetRealTime()<<
" us\n";
458 Draw(*(*pim[act])[0], rgbim, p, cov, i-argind);
461 name <<
"track-"<<setw(4)<<setfill(
'0')<<i-argind<<
".mip";
468 cerr <<
"drawing/writing took "<<timer.
GetRealTime()<<
" us\n";
(16bit) unsigned integer image storage type
static int CircleCenterFilled(Image< StorageType > &im, unsigned int CenterX, unsigned int CenterY, unsigned int Radius, const StorageType Value[])
draws a filled circle using Value
int ScaleShift(double Scale, double Shift)
scales and shifts image (all channels simultanously)
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
invalid not set image storage type
static int Line(Image< StorageType > &im, const unsigned int start[2], const unsigned int end[2], const StorageType value[])
lines
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
static int Ellipse(Image< StorageType > &im, double center[2], double a[2], double b[2], const StorageType Value[])
draws an ellipse at center with half axes a and b
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
color values, 3 channels, order: red,green,blue
Computes the cornerness as the smaller eigenvalue of the structure tensor matrix. ...
The image template class for specific storage types.
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
double GetCycleCount() const
return number of cycles between all subsequent calls to Start() and Stop() since last call to Reset()...
double GetRealTime() const
return real time (=wall time clock) in usec JW For Win32: real-time is measured differently from user...
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
int EigenvalueDecomposition(T &value1, Vector2< T > &vector1, T &value2, Vector2< T > &vector2) const
Eigenvalue decomposition.
Class for holding multiple downsampled images.
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
static int Convert(BIAS::ImageBase &source, BIAS::ImageBase &dest, enum BIAS::ImageBase::EColorModel targetColorModel, bool bPlanar=false)
main general conversion function, calls desired specialized functions, always initializes the destIma...
enum EStorageType GetStorageType() const
(8bit) unsigned char image storage type
unsigned long int GetPixelCount() const
returns number of pixels in image
This is the base class for images in BIAS.
class for producing random numbers from different distributions
class TimeMeasure contains functions for timing real time and cpu time.
High level tracking class.
virtual int Detect(const Image< StorageType > &image, std::vector< HomgPoint2D > &p, std::vector< QUAL > &quality, std::vector< Matrix2x2< double > > *cov=NULL)
detect corners in a grey image
static int ToGrey(const ImageBase &source, ImageBase &dest)
wrapper for the templated function ToGrey