pol_locator_gen.h

Go to the documentation of this file.
00001 /*
00002  *
00003  *  A new locator which does not use Hough "images"
00004  *  should in the future be able to deal with position and angle and scale
00005  *  gen is for generic
00006  *
00007  *  stumeikle Wed Dec 11 16:15:21 2002
00008  *
00009  */
00010 
00011 #ifndef POL_LOCATOR_GEN_H
00012 #define POL_LOCATOR_GEN_H
00013 
00014 #include <boost/numeric/ublas/vector.hpp>
00015 #include <cmath>
00016 #include <cstdarg>
00017 #include "pol_match.h"
00018 
00019 //not really true error values i think, but almost
00020 #define DISTANCE_ERROR  5
00021 #define ANGLE_ERROR 10.0 * 0.0174533
00022 namespace mimas {
00023 class poss_centroid
00024 {
00025     public:
00026    typedef boost::numeric::ublas::vector< double > Vector;
00027   Vector posn;
00028   double    posn_weight;
00029   angle ang;
00030   double    angle_weight;
00031             //and scale to come of course !!
00032   double    entry_weight;
00033 
00034   static  double* posn_gauss;
00035   static  double* angle_gauss;
00036   static  int     posn_gauss_size;
00037   static  int     angle_gauss_size;
00038 
00039   poss_centroid()
00040   {
00041       posn_weight = angle_weight = 1.0;
00042       entry_weight=0.0;
00043   }
00044 
00045   double    consistent( poss_centroid *other )
00046   {
00047       // is the provided mment consistent with this value
00048       // (ie does it fall within the error bounds of this point)
00049       // for now this will mean, is its posn close to ours and
00050       // is its angle close to ours. both conditions must be satisfied
00051       // we'll return a match value now...
00052       double  dist;
00053 
00054       dist = norm_2(other->posn - posn);
00055       if (dist>DISTANCE_ERROR)
00056         return 0;
00057 
00058       //else
00059       //check the angles, and if they match too
00060       //then calculate a weight based on Gausssssss
00061       angle adiff;
00062       adiff = other->ang - ang;
00063       if (adiff> ANGLE_ERROR | adiff< -ANGLE_ERROR)
00064         return 0;
00065 
00066       //ok, so calculate a fitness measure.
00067       //distance is easy --> we can calculate the gaussian weight
00068       double  weight=0,w1,w2;
00069 
00070       getWeights( other, &w1, &w2 );
00071       weight = w1*w2;
00072        std::cout << "weight=" << weight<< std::endl;
00073       return weight;
00074   }
00075 
00076   void    getWeights( poss_centroid *other, double *w1, double *w2 )
00077   {
00078       //this could be elipsesified too but its internal so not so important
00079       double  posn_diff;
00080       int   ipd;
00081 
00082       posn_diff = norm_2(posn - other->posn);
00083       ipd = (int)posn_diff;
00084       if (ipd< posn_gauss_size)
00085     *w1 = posn_gauss[ipd];
00086     //*w1=1.0;
00087       else
00088         *w1 = 0;
00089 
00090       double  angle_diff;
00091       int   iad;
00092 
00093       angle_diff = (double)(ang - other->ang);
00094       if (angle_diff<0) angle_diff=-angle_diff;
00095       iad = (int)angle_diff;
00096       if (iad< angle_gauss_size)
00097         *w2 = angle_gauss[iad];
00098     //*w2=1.0;
00099       else
00100         *w2 = 0;
00101 
00102        std::cout << "ipd=" << ipd << " and iad=" << iad << std::endl;
00103        std::cout << "angle_gauss=" << angle_gauss[iad] << std::endl;
00104        std::cout << "dist_gauss="  << posn_gauss[ipd]  << std::endl;
00105 
00106 
00107   }
00108 
00109   void    update( poss_centroid *other )
00110   {
00111       //function should be called after it hsa been found that 'this'
00112       //and other are consistent. update 'this' with the new 'other' entry
00113       //this function updates the weight and centroid and angle position
00114       //associated with this function.
00115       double  w1,w2;
00116        std::cout << "Update" << std::endl;
00117       getWeights( other, &w1, &w2 );
00118       w1*=other->entry_weight;
00119       w2*=other->entry_weight;
00120 
00121       //we use distance and angle weights separately here. actually i dont
00122       //this this algorithm is much good (!!FIX!!)
00123       posn = (posn * posn_weight) + (other->posn*w1);
00124       posn_weight+=w1;
00125       posn= posn/ posn_weight;
00126 
00127       ang= (ang * angle_weight) + (other->ang*w2);
00128       angle_weight+= w2;
00129       ang= ang / angle_weight;
00130 
00131       //update the entry weight. for models this value will be used for
00132       //later thresholding, but NOT during the update process
00133       entry_weight= posn_weight* angle_weight;
00134   }
00135 };
00136 
00137 typedef std::list< poss_centroid * > poss_centroid_list;
00138 
00139 class pol_locator_gen : public pol_locator
00140 {
00141  public:
00142    typedef boost::numeric::ublas::vector< double > Vector;
00143     private:
00144       double      threshold;
00145   // list of possible centroids
00146      poss_centroid_list list_poss_centroids;
00147   // list of possible matches/found instances of the model
00148      poss_centroid_list list_poss_matches;
00149 
00150   double      *posn_gauss,*angle_gauss;
00151   int     posn_gauss_size, angle_gauss_size;
00152 
00153   int calcGaussBoxSize( double sigma, double accuracy )
00154   {
00155       //code largely taken from tina src.
00156       double n;
00157 
00158       sigma = 2.0 * sigma * sigma;
00159 
00160       for(n=1.0; ;n+=1.0)
00161       {
00162     if (exp( -n*n/sigma )< accuracy) break;
00163       }
00164 
00165       return (int) n;
00166   }
00167 
00168     public:
00169   //same interface as with the last one. i guess i'll create an
00170   //abstract interface file later..
00171   pol_locator_gen()
00172   {
00173       posn_gauss=angle_gauss=0;
00174       posn_gauss_size=angle_gauss_size=0;
00175       threshold=0;
00176   }
00177   pol_locator_gen(double t)
00178   {
00179       posn_gauss=angle_gauss=0;
00180       posn_gauss_size=angle_gauss_size=0;
00181       threshold=t;
00182   }
00183   ~pol_locator_gen()
00184   {
00185       if (posn_gauss) delete[] posn_gauss;
00186       if (angle_gauss)  delete[] angle_gauss;
00187 //      list<poss_centroid*>::iterator  i;
00188 //      for(i=list_poss_centroids.begin();
00189 //          i!=list_poss_centroids.end(); ++i)
00190 //      {
00191 //        delete (*i);
00192 //      }
00193 //      list_poss_centroids.clear();
00194 
00195 //      for(i=list_poss_matches.begin();
00196 //          i!=list_poss_matches.end(); ++i)
00197 //      {
00198 //        delete (*i);
00199 //      }
00200 //      list_poss_matches.clear();
00201   }
00202 
00203   virtual void    init( int numdims, ...)
00204   {
00205       //set up the guassians. we'll need to use this for the position and angle
00206       //updates, so no harm in using this function again
00207       //i'll use a variable argument list here because the number of degrees of
00208       //freedom is likely to increase in the future
00209       va_list vlist;
00210 
00211       if (numdims!=2)
00212         return;
00213     //should throw an exception really
00214 
00215       //read the position and angle sigmas and precisions. create a gauss dist for each
00216       va_start(vlist, numdims);
00217 
00218       double  s,p;
00219       s=va_arg(vlist, double);
00220       p=va_arg(vlist, double);
00221 
00222       if (posn_gauss) delete posn_gauss;
00223 
00224       s = 2*s*s;
00225       int size = calcGaussBoxSize( s,p );
00226       int i;
00227 
00228       posn_gauss=new double[size];
00229       posn_gauss_size=size;
00230 
00231       //fill in the curve
00232       for(i=0;i<size;++i)
00233       {
00234     double d = (double)i*(double)i;
00235     double w = exp( -d/s );
00236 
00237         posn_gauss[i]=w;
00238       }
00239 
00240       //do the second ...
00241       s=va_arg(vlist, double);
00242       p=va_arg(vlist, double);
00243 
00244       if (angle_gauss)  delete angle_gauss;
00245 
00246       s = 2*s*s;
00247       size = calcGaussBoxSize( s,p );
00248 
00249       angle_gauss=new double[size];
00250       angle_gauss_size=size;
00251 
00252       //fill in the curve
00253       for(i=0;i<size;++i)
00254       {
00255     double d = (double)i*(double)i;
00256     double w = exp( -d/s );
00257 
00258         angle_gauss[i]=w;
00259       }
00260 
00261       //store the values in the poss_centroid so that all poss_centroids have access to them
00262       poss_centroid::posn_gauss= posn_gauss;
00263       poss_centroid::angle_gauss=angle_gauss;
00264       poss_centroid::angle_gauss_size=angle_gauss_size;
00265       poss_centroid::posn_gauss_size=posn_gauss_size;
00266 
00267       va_end(vlist);
00268   }
00269 
00270   virtual void    addEntry( double weight, ... )
00271   {
00272       //again we need ellipses to cover the n-dim case
00273       va_list vlist;
00274       va_start(vlist,weight);
00275 
00276        Vector posn( 2 );
00277        posn( 0 ) = va_arg( vlist, double );
00278        posn( 1 ) = va_arg( vlist, double );
00279       double  angle= va_arg( vlist, double );
00280 
00281       // just push the measurement onto the list. we'll analyse the results when
00282       // the user calls get matches
00283       poss_centroid *pc = new poss_centroid;
00284       pc->posn=posn;
00285       pc->ang=angle;
00286       pc->entry_weight=weight;
00287       list_poss_centroids.push_back(pc);
00288 
00289       va_end(vlist);
00290   }
00291 
00292   virtual pol_match_ptr_list getMatches()
00293   {
00294       // so now we have to look for consistencies in the measurements without
00295       // using a hough transform
00296 
00297       // maybe the first attempt will be to just try to replicate the results
00298       // that we get with the hough transform method.
00299       // Algo:
00300       // -- go through the list of poss centroids. compare each to the list of
00301       //    possible matches. if its consistent with one of them then update the
00302       //    match centroid and weight.
00303       // -- if not then , errr, in this simplist of cases, we will add it to thh
00304       //    list of possible matches anyway.
00305       //    [in future we can compare the centroid to all possible centroids and
00306       //     if it is consistent with at least one other, we can add it as a
00307       //     possible model.]
00308       // -- threshold the match list and return
00309        poss_centroid_list::iterator i_pc, i_pm;
00310        std::cout<<"hello1"<< std::endl;
00311 
00312       for(i_pc=list_poss_centroids.begin(); i_pc!=list_poss_centroids.end();++i_pc)
00313       {
00314     poss_centroid*  pc=(*i_pc);
00315 
00316     if  (!pc) continue;
00317 
00318     //we have a possible centroid position.
00319     //is it consistent with any of the matches found so far?
00320     //we'll take the best match to start with, though it may be too slow
00321     poss_centroid   *best_match=0;
00322     double      best_score=0;
00323     for(i_pm=list_poss_matches.begin(); i_pm!=list_poss_matches.end();++i_pm)
00324     {
00325         double    score;
00326         poss_centroid *match=(*i_pm);
00327         if (!match)   continue;
00328 
00329         score = pc->consistent( match );
00330           //std::cout << "score=" << score << std::endl;
00331 
00332           //if (score>best_score)
00333         if (score>0)
00334         {
00335           best_score=score;
00336       best_match=match;
00337       break;
00338         }
00339     }
00340 
00341     //if found a match
00342     if (best_match)
00343     {
00344         best_match->update( pc );
00345     }
00346     else
00347     {
00348         // if !found...
00349         // ... just add to the match list anyway
00350         list_poss_matches.push_back( pc );
00351     }
00352       }
00353        std::cout<<"hello2"<<std::endl;
00354 
00355       //threshold match list and return ...
00356       pol_match_ptr_list retval;
00357       double    max=0;
00358       for(i_pc=list_poss_matches.begin();
00359         i_pc!=list_poss_matches.end();  ++i_pc)
00360       {
00361     poss_centroid *match= (*i_pc);
00362 
00363       std::cout << "Found a possible entry, weight(" << threshold << ")= " << match->entry_weight<< std::endl;
00364     if (match->entry_weight> max)
00365       max = match->entry_weight;
00366     if (match->entry_weight > 5000) // threshold)
00367     {
00368         pol_match_ptr m( new pol_match );
00369 
00370       m->model_found = NULL;
00371       m->pos = match->posn;
00372       m->orient=match->ang;
00373       m->strength=match->entry_weight;
00374       retval.push_back(m);
00375     }
00376       }
00377        std::cout<<"hello3"<<std::endl;
00378       // delete the data structures which we're finished with now
00379 //        poss_centroid_list::iterator  i;
00380 //      for(i=list_poss_centroids.begin();
00381 //          i!=list_poss_centroids.end(); ++i)
00382 //      {
00383 //        delete (*i);
00384 //      }
00385 //      list_poss_centroids.clear();
00386 
00387 //      for(i=list_poss_matches.begin();
00388 //          i!=list_poss_matches.end(); ++i)
00389 //      {
00390 //        delete (*i);
00391 //      }
00392 //      list_poss_matches.clear();
00393        std::cout<<"hello4"<<std::endl;
00394        std::cout << "Max val = " << max << std::endl;
00395 
00396       return retval;
00397   }
00398 };
00399 
00400 
00401 //yukky yuk
00402 double* poss_centroid::angle_gauss = NULL;
00403 double* poss_centroid::posn_gauss = NULL;
00404 int     poss_centroid::angle_gauss_size = 0;
00405 int poss_centroid::posn_gauss_size = 0;
00406 }
00407 #endif
00408 

[GNU/Linux] [Qt] [Mesa] [STL] [Lapack] [Boost] [Magick++] [Xalan-C and Xerces-C] [doxygen] [graphviz] [FFTW] [popt] [xine] [Gnuplot] [gnu-arch] [gcc] [gstreamer] [autoconf/automake/make] [freshmeat.net] [opensource.org] [sourceforge.net] [MMVL]
mimas 2.1 - Copyright Mon Oct 30 11:31:17 2006, Bala Amavasai, Stuart Meikle, Arul Selvan, Fabio Caparrelli, Jan Wedekind, Manuel Boissenin, ...