hough_tracking.hh

00001 #ifndef MMVL_HOUGH_TRACKING_HH_INCLUDED
00002 #define MMVL_HOUGH_TRACKING_HH_INCLUDED
00003 
00004 #include <iostream>
00005 #include <fstream>
00006 #include <iomanip>
00007 #include <vector>
00008 #include <set>
00009 #include <algorithm>
00010 #include <boost/multi_array.hpp>
00011 #include <boost/numeric/ublas/vector.hpp>
00012 #include <mimas/mm_linalg.h>
00013 
00014 #include <mimas/mm_image_fileinput.h>
00015 #include <mimas/mm_image_fileoutput.h>
00016 #include <mimas/mm_image_qtoutput.h>
00017 #include "tools.hh"
00018 #include <mimas/mm_image.h>
00019 
00020 #include <mimas/mm_xml_node_reference_list.h>
00021 #include <mimas/mm_xml_document.h>
00022 //why these 2 include are not documented in mimas
00023 #include <util/PlatformUtils.hpp>
00024 #include <XPath/XPathInit.hpp>
00025 #ifndef NDEBUG
00026 #include <mimas/mm_image_qtoutput.h>
00027 #include <qdatetime.h> 
00028 #endif
00029 
00030 #include <qthread.h> //for parallelization of the tracking
00031 #include <qthreadstorage.h> 
00032 #include <qmutex.h> 
00033 
00034 
00071 //interval_type can be continuous or discrete
00072 
00073 class Interval{
00074 public:
00075   enum interval_type {Continuous = 0, Discrete};
00076   enum interval_type type;
00077 
00078   //for Continous type
00079   float lower_bound;
00080   float upper_bound;
00081 
00082   //for Discrete type
00083   int value;
00084   
00085   Interval(float lowerBound, float uperBound)
00086     :type(Continuous), lower_bound(lowerBound), upper_bound(uperBound) 
00087   {};
00088 
00089   Interval(int value)
00090     :type(Discrete),value(value)
00091   {};
00092 };
00093 
00094 
00107 class Transformation{
00108 public:
00109   std::vector<Interval> intervals;
00110   int votes;
00111 
00112   Transformation():
00113     votes(0){}
00114 
00115 void debug(void)
00116   {
00117     std::cerr<<"transformation is:"<<std::endl
00118   <<"x: "<< (intervals[0].lower_bound + intervals[0].upper_bound)/2 <<std::endl
00119   <<"y: "<< (intervals[1].lower_bound + intervals[1].upper_bound)/2 <<std::endl
00120   <<"theta: "<< (intervals[2].lower_bound + intervals[2].upper_bound)/2 <<std::endl
00121   <<"z: "<< intervals[3].value <<std::endl
00122   <<"number of hit: "<< votes<<std::endl;
00123   }
00124 };
00125 
00126 struct lttransf : public std::binary_function<Transformation, Transformation, bool> {
00127     bool operator()(Transformation x, Transformation y) { return  x.votes < y.votes;}
00128   };
00129   
00139 typedef boost::numeric::ublas::vector<int> Feature;
00140 
00141 struct ltfeature
00142 {
00143   bool operator()(const Feature &f1, const Feature &f2) const
00144   {
00145     if (f1(0) == f2(0))
00146       {
00147   return f1(1) < f2(1);
00148       }
00149     return f1(0) < f2(0);
00150   }
00151 };
00152 
00153 //one way to generalize might be to pass the number of dimension of the transform space as a template argument and
00154 //use boost::shape to pass as argument of the constructor to specify the discretization of each
00155 //dimension.
00156 
00157 class hough_tracking {
00158 public:
00159  
00160   //put the frame of the model in the middle of the image.
00161   //K needs to be calculated to take into account the added translation of point due to roation
00162   //Features are given in a model centered coordinate system.
00163   // We assume that all model images are of
00164   //the same size and the object oriented the same way and centered in the middle of the image. 
00165 
00166 
00167   hough_tracking( const std::vector< std::vector<Feature> > &feature_images,
00168       int model_width, int model_height, int K ,
00169       int x_min, int x_max, int x_sub,
00170       int y_min, int y_max, int y_sub,
00171       float theta_min, float theta_max, int theta_sub,
00172       int nb_thread);
00173 
00174   //For each images we store the number of feature it contains.
00175   //This is used as an indication (when compared with the number of
00176   //hit find) of the success of the tracking
00177   std::vector<int> number_of_features;
00178  
00179 /*
00180   Pseudo-code 
00181 
00182   fill_image_space()
00183   {
00184   for each transformation
00185   for each feature of the image corresponding to the transformation(think of the stack)
00186     {
00187       calculate locus of point according to the sub-transformed space;      
00188       add transformation reference to this locus to the image_space array;
00189     }
00190   }
00191 */  
00192 
00193 //this is separated from the constructor as the data
00194 //structure it fills might be latter loaded
00195   void fill_image_space(void);
00196   
00197   //The feature should be expressed in a object centered coordinate system of
00198   //the previous tracked location.
00199   Transformation track(std::vector<Feature> &features);
00200 
00201   int get_model_width(void) const { return model_width; }
00202   int get_model_height(void) const { return model_height; }
00203 
00204   ~hough_tracking()
00205   {
00206     /*    mutex_1.unlock();
00207     mutex_2.unlock();
00208     mutex_1_b.unlock();    
00209     mutex_2_b.unlock();
00210     thread1.terminate();
00211     thread2.terminate();
00212     thread1.wait();
00213     thread2.wait();*/
00214   }
00215 
00216 private:
00217   int model_width;
00218   int model_height;
00219   int x_sub;
00220   int y_sub;
00221   int theta_sub;
00222   int z_max;
00223 
00224   class track_t:public QThread
00225   {
00226   public:
00227     boost::multi_array<std::vector<Transformation *>,2>& image_space;
00228     std::vector<Feature> &features;
00229     std::vector<Transformation *>::iterator transf_it;
00230     QMutex &mutex;
00231     QMutex &mutex_b;
00232 
00233     track_t(boost::multi_array<std::vector<Transformation *>,2>& image_space, /*std::vector<Transformation *>::iterator transf_it,*/ QMutex &mutex, QMutex &mutex_b)
00234       :image_space(image_space),features(*(new std::vector<Feature>) ),/*transf_it(transf_it),*/ mutex(mutex), mutex_b(mutex_b)
00235     {
00236       this->mutex.lock();
00237       this->mutex_b.lock();
00238     }//with memory leak
00239 
00240     
00241     void set_features(std::vector<Feature> &features_l)
00242     {
00243       features = features_l;
00244     }
00245     
00246   
00247     void run(void)
00248     {
00249       while(true)
00250   {
00251     mutex_b.lock();
00252     for( std::vector<Feature>::const_iterator feature_it = features.begin(); feature_it != features.end(); feature_it++)
00253       {
00254         Feature temp(2);
00255         temp(0) = (*feature_it)(0) + image_space.shape()[0]/2;
00256         temp(1) = image_space.shape()[1]/2 - (*feature_it)(1);
00257         
00258         for(transf_it = image_space[temp(0)][temp(1)].begin();
00259       transf_it != image_space[temp(0)][temp(1)].end();
00260       transf_it++)
00261     (*transf_it)->votes++;  
00262       }
00263     mutex.unlock();
00264   }
00265     }
00266 
00267   };
00268   
00269   //each image has its vector of Feature.
00270   std::vector< std::vector<Feature> > feature_images;
00271   
00272   boost::multi_array<Transformation,4> transformation_space;
00273   typedef boost::multi_array<Transformation,4>::index idx_ts;//for index transform space
00274   
00275   //for parallelisation 
00276 
00277   int nb_thread;
00278   std::vector<boost::multi_array<std::vector<Transformation *>,2> *> image_space_vec; //replace with  smart pointers ?
00279   std::vector<QMutex *> mutexes;    
00280   std::vector<QMutex *> mutexes_b;
00281   std::vector<track_t *> threads;
00282   
00283   //  std::vector<Transformation *>::iterator transf_it;
00284   typedef boost::multi_array<std::vector<Transformation *>,2>::index idx_is;//for index image space
00285 
00286 #ifndef NDEBUG
00287 
00288   mutable mimas::mm_image_qtoutput< mimas::mm_rgba< unsigned char > > display;
00289 #endif
00290   
00291 };
00292 
00293 typedef boost::shared_ptr< hough_tracking > hough_tracking_ptr;
00294 
00295 #endif

doxygen-1.4.5 documentation for micron-vision - Tue Jan 17 15:29:15 2006