OmniTrackingTable.hh

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) Massimo Cora' 2005 <maxcvs@email.it>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #ifndef __OMNITRACKING_TABLE_H__
00021 #define __OMNITRACKING_TABLE_H__
00022 
00023 #include "OmniConfig.hh"
00024 #include "OmniConversion.hh"
00025 #include "TrackingWindow.hh"
00026 
00027 // stl
00028 #include <list>
00029 
00030 using namespace std;
00031 
00032 
00041 template <class ConverterT, class AngleT, class ImageT, class PointT>
00042 class OmniTrackingTable {
00043 
00044 public:
00053         OmniTrackingTable( OmniConversion<ConverterT, AngleT, ImageT, PointT> *conv_table,
00054                 int freeze_frame_bound, double track_window_hitrate );
00055 
00056         virtual ~OmniTrackingTable();
00057 
00065         bool test_tracking_window_availability( int theta_start, int theta_end, 
00066                                 int window_length );
00067 
00068 protected:              // functions
00075         void add_tracking_window( int window_id, int theta_start, int theta_end );
00076         
00084         void add_wannabe_trackable_marks( int theta_start, int theta_end );
00085         
00094         bool update_tracking_window_bounds( int window_id, int new_theta_start, 
00095                                 int new_theta_end );
00096         
00101         void remove_tracking_window( int window_id );
00102 
00107         void update_begin();
00108 
00113         void update_end();
00114 
00119         OmniConversion<ConverterT, AngleT, ImageT, PointT> *m_conv_table;
00120 
00121 private:                // functions
00128         bool init_tracking_table( int degrees );
00129 
00130 
00131 private:                // data
00133         char *_degree_table;            // array of chars
00134         
00136         int _degree_table_length;
00137 
00139         int _active_tracks;
00140 
00141         const double _track_window_hitrate;
00142         const int _freeze_frame_bound;
00143         
00145         bool _update_is_possibile;
00146 
00148         list<TrackingWindow*> _track_list;
00149 };
00150 
00151 
00152 
00153 
00154 //-------------------------------------------------------------------------
00155 //
00156 
00157 template <class ConverterT, class AngleT, class ImageT, class PointT>
00158 OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::OmniTrackingTable( 
00159                                                                          OmniConversion<ConverterT, AngleT, ImageT, PointT> *conv_table, 
00160                                                                          int freeze_frame_bound, 
00161                                                                          double track_window_hitrate ) : 
00162                                                                          _freeze_frame_bound( freeze_frame_bound ),
00163                                                                          _track_window_hitrate( track_window_hitrate ),
00164                                                                          m_conv_table( conv_table )
00165 {
00166         _update_is_possibile = false;
00167         init_tracking_table( (int)ceil( 2 * CV_PI * m_conv_table->get_max_radius() ) );
00168 }
00169 
00170 
00171 
00172 //-------------------------------------------------------------------------
00173 //
00174 
00175 template <class ConverterT, class AngleT, class ImageT, class PointT>
00176 OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::~OmniTrackingTable() {
00177 
00178         free( _degree_table );
00179 
00180         if ( ! _track_list.empty () ) {
00181                 TrackingWindow* tmp_track;
00182 
00183                 while ( (tmp_track = _track_list.front ())) {
00184                         _track_list.pop_front ();
00185                         if ( tmp_track ) {
00186                                 delete tmp_track;
00187                         }
00188                 }
00189         }
00190 }
00191 
00192 
00193 //-------------------------------------------------------------------------
00194 // WARNING: with this call the entire degree_table will be cleaned from its
00195 // marks. 
00196 
00197 template <class ConverterT, class AngleT, class ImageT, class PointT>
00198 void OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::update_begin() {
00199         _update_is_possibile = true;
00200 
00201         memset( _degree_table, 0, _degree_table_length * sizeof(char));
00202 }
00203 
00204 
00205 //-------------------------------------------------------------------------
00206 //  perform a total rewrite of the degree table: every linked list element 
00207 // [a window] will write its own info to the table.
00208 
00209 template <class ConverterT, class AngleT, class ImageT, class PointT>
00210 void OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::update_end() {
00211         _update_is_possibile = false;
00212 
00213 
00214         list<TrackingWindow*>::iterator iter;
00215 
00216         // perform a scan till to find the right id element.
00217         for ( iter = _track_list.begin(); iter != _track_list.end(); iter++ ) {
00218                 (*iter)->write_window_to_table( _degree_table );
00219         }
00220 }
00221 
00222 
00223 //-------------------------------------------------------------------------
00224 // this will remove the object from the list, delete it and then upgrade the 
00225 // window_id of the remainings objects in the list. They will be decreased
00226 // by one. This to mantain a crescent array
00227 
00228 template <class ConverterT, class AngleT, class ImageT, class PointT>
00229 void OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::remove_tracking_window( int window_id ) 
00230 {
00231 
00232         list<TrackingWindow*>::iterator iter;
00233 
00234         TrackingWindow *win_to_remove = NULL;
00235         // flag
00236         bool win_deleted = false;
00237 
00238         // perform a scan till to find the right id element.
00239         for ( iter = _track_list.begin(); iter != _track_list.end(); iter++ ) {
00240                 // we wanna modify the object, not having its copy
00241                 TrackingWindow *win = (TrackingWindow*)(*iter);
00242 
00243                 // then update its status
00244                 if ( win->get_id() == window_id ) {
00245                         
00246                         win_to_remove = win;
00247                         win_deleted = true;
00248                 }
00249 
00250                 // go on decrementing the others window_id
00251                 if ( win_deleted ) {
00252                         win->change_id( win->get_id() - 1 );
00253                 }
00254         }
00255 
00256         if ( win_to_remove != NULL ) {
00257                 _track_list.remove( win_to_remove );
00258                 delete win_to_remove;
00259         }
00260 
00261         _active_tracks--;
00262 }
00263 
00264 
00265 //-------------------------------------------------------------------------
00266 // construct a TrackingWindow object and adds it to the linked list
00267 // It also performs a write to the table of the VALUE_TRACKED status.
00268 
00269 template <class ConverterT, class AngleT, class ImageT, class PointT>
00270 void OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::add_tracking_window( 
00271                         int window_id, int theta_start, int theta_end ) {
00272         
00273         TrackingWindow *t_win = new TrackingWindow( window_id, theta_start, theta_end, 
00274                 _degree_table_length, _freeze_frame_bound );
00275         _track_list.push_back( t_win );
00276 
00277         // write the status to the window
00278     t_win->write_window_to_table( _degree_table );
00279 
00280         _active_tracks++;
00281 }
00282 
00283 
00284 //-------------------------------------------------------------------------
00285 // I'll try to explain at best what this function does: it just writes to the degree
00286 // table a mark 'W' for a wannabe trackable window. It does not construct
00287 // a TrackingWindow object and does not add it to the list track_list.
00288 // This mark 'W' is written here only to permit a multiple tracking-window adding,
00289 // in case the motion detection detects more than one movement.
00290 // This happens because only with a complete loop of process_next_frame in OmniTracking
00291 // a window can be completely and cleanly added: so to avoid the loosing of 
00292 // many ( >1 ) motion windows at a time we must find a way to "update" the degree_table
00293 // so that the test_tracking_window_availability can return a "no, this space is already
00294 // tracked".
00295 // On next update_begin() and changes made here will be lost
00296 
00297 template <class ConverterT, class AngleT, class ImageT, class PointT>
00298 void OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::add_wannabe_trackable_marks( 
00299                         int theta_start, int theta_end ) 
00300 {
00301         int window_length_tmp;
00302 
00303         if ( theta_start < theta_end )  // 0 .. | | | |S| | | | | | |E| | | .. theta_max
00304                 window_length_tmp = theta_end - theta_start;
00305         else                                                    // 0 .. | | | |E| | | | | | |S| | | .. theta_max
00306                 window_length_tmp = theta_end + _degree_table_length - theta_start;
00307 
00308         for ( int i = 0 ; i < window_length_tmp; i++ ) {
00309                 _degree_table[(theta_start + i) % _degree_table_length] = VALUE_WANNABE_TRACKABLE;
00310         }
00311 }
00312 
00313 
00314 //-------------------------------------------------------------------------
00315 // test if the tracking window [i.e. the degree interval in which the 
00316 // motion is caught] is a face-detectable window [i.e. is not yet
00317 // tracked by LK algorithm].
00318 // 0 <= start_angle < end_angle <= 2pi in a circular fashion.
00319 //
00320 //   [ T T T T T T 0 0 0 0 0 0 0 0 0 0 W W W W 0 0 0 0 0 0 0 0 0 0 0]
00321 //      [M M M M M M M]   <-- testing motion window [*1]
00322 //   <-M M M]                                    [2*]          [ M M->
00323 //                                      [3*]      [M M M M M]
00324 //
00325 //  [*1]: new tracking window is not avaiable coz > 50% hits are yet tracked [T]
00326 //  [*2]: even here we have a failed new window
00327 //  [*3]: good new tracking window. Of course this must match the face-detect before
00328 //        become a real *new* tracking win.
00329 
00330 template <class ConverterT, class AngleT, class ImageT, class PointT>
00331 bool OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::test_tracking_window_availability( int theta_start, int theta_end, 
00332                                                                                                                   int window_length ) 
00333 {
00334         // main for loop: let's check in a circular fascion for an hitrate  > MOTION_HITRATE 
00335         // of avaiable tracking portions
00336         int hitrate = 0;
00337         
00338         for ( int step_count = 0; step_count < window_length; step_count++ ) {
00339                 int curr_value = _degree_table[(theta_start + step_count) % _degree_table_length];
00340                 if (  curr_value != VALUE_TRACKED && curr_value != VALUE_WANNABE_TRACKABLE )
00341                         hitrate++;
00342         }
00343 
00344         // check the rate obtained
00345         if ( hitrate > (window_length * TRACK_WINDOW_HITRATE) ) {
00346                 return true;
00347         }
00348         
00349         return false;
00350 }
00351 
00352 
00353 //-------------------------------------------------------------------------
00354 // be careful to call this function only between a update_begin() and a
00355 // update_end(). Will return false if this condition is not accomplished
00356 // or if a TrackingWindow remains in the same position too 
00357 // long [i.e. false positive tracking?!]
00358 
00359 template <class ConverterT, class AngleT, class ImageT, class PointT>
00360 bool OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::update_tracking_window_bounds( 
00361                         int window_id, int new_theta_start, int new_theta_end ) 
00362 {
00363         if ( !_update_is_possibile )
00364                 return false;
00365 
00366         list<TrackingWindow*>::iterator iter;
00367 
00368         // perform a scan till to find the right id element.
00369         for ( iter = _track_list.begin(); iter != _track_list.end(); iter++ ) {
00370                 // we wanna modify the object, not having its copy
00371                 TrackingWindow *win = (TrackingWindow*)(*iter);
00372 
00373                 // then update its status
00374                 if ( win->get_id() == window_id ) {
00375                         // we're done
00376                         return win->update_window_bounds( new_theta_start, new_theta_end );
00377                 }
00378         }
00379 
00380         return false;
00381 }
00382 
00383 //-------------------------------------------------------------------------
00384 //
00385 
00386 template <class ConverterT, class AngleT, class ImageT, class PointT>
00387 bool OmniTrackingTable<ConverterT, AngleT, ImageT, PointT>::init_tracking_table( int degrees ) 
00388 {
00389         if (degrees <= 0)
00390                 return false;
00391 
00392         // create the table which represents all the 360 degree
00393         _degree_table = (char*)calloc( degrees, sizeof(char) );
00394 
00395         _degree_table_length = degrees;
00396         _active_tracks = 0;
00397 
00398         return true;
00399 }
00400 
00401 
00402 #endif /* __OMNITRACKING_TABLE_H__ */
00403 

Generated on Tue Dec 26 10:32:38 2006 for Omnimeeting by  doxygen 1.4.7