00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __OMNIMOTION_DETECTING__
00021 #define __OMNIMOTION_DETECTING__
00022
00023 #include <cv.h>
00024 #include <highgui.h>
00025
00026 #include <time.h>
00027
00028 #include "OmniConfig.hh"
00029 #include "OmniConversion.hh"
00030
00031
00033
00034 const double MHI_DURATION = 1;
00035
00037 const double MAX_TIME_DELTA = 1;
00038
00040 const double MIN_TIME_DELTA = 0.05;
00041
00046 typedef void (on_window_trackable_wannabe_cb)( IplImage* omni_frame,
00047 int theta_start,
00048 int theta_end,
00049 int win_length,
00050 void* callback_data );
00051
00058 template <class ConverterT, class AngleT>
00059 class OmniMotionDetecting {
00060 public:
00070 OmniMotionDetecting( on_window_trackable_wannabe_cb *f_cb,
00071 void* callback_data,
00072 OmniConversion<ConverterT, AngleT, IplImage, CvPoint> *conv_table,
00073 int ring_buf_length = 4 );
00074 virtual ~OmniMotionDetecting();
00075
00080 void process_next_frame( IplImage *next_frame );
00081
00091 void register_image_callbacks( on_create_image_context_cb* create_image_context,
00092 on_image_do_action_cb* image_show,
00093 on_destroy_image_context_cb* destroy_image_context,
00094 void* callback_data_on_image_cb );
00095
00096
00097 private:
00103 void fast_update_mhi( IplImage* img, int diff_threshold = 10 );
00104
00108 on_window_trackable_wannabe_cb* f_on_window_trackable_wannabe_cb;
00109
00111 on_create_image_context_cb* create_image_context;
00112
00114 on_image_do_action_cb* image_show;
00115
00117 on_destroy_image_context_cb* destroy_image_context;
00118
00119 private:
00120
00121 void* _callback_data_on_window_trackable_wannabe_cb;
00122 void* _callback_data_on_image_cb;
00123
00128 OmniConversion<ConverterT, AngleT, IplImage, CvPoint> *_conv_table;
00129
00131 IplImage **_ring_buf;
00132
00134 int _ring_buf_length;
00135 int _ring_last_indx;
00136
00138
00139 IplImage *_mhi;
00140
00142 IplImage *_orient;
00143
00145 IplImage *_mask;
00146
00148 IplImage *_segmask;
00149
00151 CvMemStorage *_storage;
00152 };
00153
00154
00155
00159
00160
00161 template <class ConverterT, class AngleT>
00162 OmniMotionDetecting<ConverterT, AngleT>::OmniMotionDetecting( on_window_trackable_wannabe_cb *f_cb,
00163 void* callback_data,
00164 OmniConversion<ConverterT, AngleT, IplImage, CvPoint> *conv_table,
00165 int ring_buf_length ) : _conv_table( conv_table ),
00166 f_on_window_trackable_wannabe_cb( f_cb ),
00167 _callback_data_on_window_trackable_wannabe_cb ( callback_data ),
00168 _ring_buf_length( ring_buf_length ),
00169 _ring_last_indx( 0 ),
00170 _mhi( 0 ),
00171 _orient( 0 ),
00172 _mask( 0 ),
00173 _segmask( 0 ),
00174 _storage( 0 )
00175 {
00176
00177 _ring_buf = (IplImage**)malloc( _ring_buf_length * sizeof(_ring_buf[0]) );
00178 memset( _ring_buf, 0, _ring_buf_length * sizeof(_ring_buf[0]) );
00179
00180
00181
00182 register_image_callbacks( omnistuff_create_image_context, omnistuff_image_do_action,
00183 omnistuff_destroy_image_context, NULL );
00184 }
00185
00186
00187
00188
00189
00190 template <class ConverterT, class AngleT>
00191 OmniMotionDetecting<ConverterT, AngleT>::~OmniMotionDetecting()
00192 {
00193 free( _ring_buf );
00194 }
00195
00196
00197
00198 template <class ConverterT, class AngleT>
00199 void OmniMotionDetecting<ConverterT, AngleT>::process_next_frame( IplImage *next_frame )
00200 {
00201 fast_update_mhi( next_frame );
00202 }
00203
00204
00205
00206
00207 template <class ConverterT, class AngleT>
00208 void OmniMotionDetecting<ConverterT, AngleT>::fast_update_mhi( IplImage* img, int diff_threshold )
00209 {
00210
00211 double timestamp = clock()/1000.;
00212
00213
00214 CvSize size = cvSize(img->width,img->height);
00215 int i, idx1 = _ring_last_indx, idx2;
00216 IplImage* silh;
00217 CvSeq* seq;
00218 CvRect comp_rect;
00219
00220
00221
00222 if( (!_mhi || _mhi->width != size.width) || (_mhi->height != size.height) ) {
00223
00224 for( i = 0; i < _ring_buf_length; i++ ) {
00225 cvReleaseImage( &_ring_buf[i] );
00226 _ring_buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
00227 cvZero( _ring_buf[i] );
00228 }
00229 cvReleaseImage( &_mhi );
00230 cvReleaseImage( &_orient );
00231 cvReleaseImage( &_segmask );
00232 cvReleaseImage( &_mask );
00233
00234 _mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
00235
00236
00237 cvZero( _mhi );
00238 _orient = cvCreateImage( size, IPL_DEPTH_32F, 1 );
00239 _segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 );
00240 _mask = cvCreateImage( size, IPL_DEPTH_8U, 1 );
00241 }
00242
00243
00244 cvCvtColor( img, _ring_buf[_ring_last_indx], CV_BGR2GRAY );
00245
00246
00247 idx2 = (_ring_last_indx + 1) % _ring_buf_length;
00248 _ring_last_indx = idx2;
00249
00250 silh = _ring_buf[idx2];
00251
00252 cvAbsDiff( _ring_buf[idx1], _ring_buf[idx2], silh );
00253
00254
00255 cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY );
00256
00257
00258 cvUpdateMotionHistory( silh, _mhi, timestamp, MHI_DURATION );
00259
00260 if( !_storage )
00261 _storage = cvCreateMemStorage( 0 );
00262 else
00263 cvClearMemStorage( _storage );
00264
00265
00266
00267 seq = cvSegmentMotion( _mhi, _segmask, _storage, timestamp, MAX_TIME_DELTA );
00268
00269
00270
00271
00272 for( i = -1; i < seq->total; i++ ) {
00273
00274 if( i < 0 ) {
00275 comp_rect = cvRect( 0, 0, size.width, size.width );
00276 }
00277 else {
00278 comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;
00279
00280
00281 if( comp_rect.width + comp_rect.height < 150 )
00282 continue;
00283 }
00284
00285 CvPoint left_bottom = { comp_rect.x, comp_rect.y };
00286
00287
00288 float rad_angle = atan2f( left_bottom.y - ((float)_conv_table->get_omni_center_y()),
00289 left_bottom.x - ((float)_conv_table->get_omni_center_x()));
00290
00291
00292 OmniAngle<int> angle_int;
00293 OmniAngle<double> angle_double(rad_angle - FACE_TRACK_ANGLE_WINDOW,
00294 rad_angle + FACE_TRACK_ANGLE_WINDOW,
00295 2 * FACE_TRACK_ANGLE_WINDOW);
00296
00297 _conv_table->angle_type_conversion( angle_double, angle_int );
00298
00299 f_on_window_trackable_wannabe_cb( img, angle_int.angle_start,
00300 angle_int.angle_end, angle_int.range, _callback_data_on_window_trackable_wannabe_cb );
00301 }
00302
00303 if ( seq != NULL )
00304 cvClearSeq( seq );
00305 }
00306
00307
00308
00309
00310 template <class ConverterT, class AngleT>
00311 void OmniMotionDetecting<ConverterT, AngleT>::register_image_callbacks(
00312 on_create_image_context_cb* create_image_context,
00313 on_image_do_action_cb* image_show,
00314 on_destroy_image_context_cb* destroy_image_context,
00315 void* callback_data_on_image_cb
00316 )
00317 {
00318 this->create_image_context = create_image_context;
00319 this->image_show = image_show;
00320 this->destroy_image_context = destroy_image_context;
00321 this->_callback_data_on_image_cb = callback_data_on_image_cb;
00322 }
00323
00324
00325 #endif
00326