GSoC2011SfM
0.1
Google Summer of Code 2011: Structure from motion
|
00001 00002 #include "macro.h" //SFM_EXPORTS 00003 00004 #include <opencv2/core/core.hpp> 00005 #include <opencv2/imgproc/imgproc.hpp> 00006 #ifdef HAVE_BOOST 00007 #include <boost/filesystem.hpp> // includes all needed Boost.Filesystem declarations 00008 #endif 00009 #include <sstream> 00010 00011 #include "MotionProcessor.h" 00012 00013 using cv::Mat; 00014 using cv::Size; 00015 using cv::Vec; 00016 using cv::Ptr; 00017 using cv::VideoCapture; 00018 using std::string; 00019 using cv::imread; 00020 using std::ostringstream; 00021 using std::vector; 00022 #ifdef HAVE_BOOST 00023 using boost::filesystem::path; 00024 #endif 00025 00026 namespace cv{ 00027 CVAPI( int ) cvHaveImageReader( const char* filename ); 00028 } 00029 00030 namespace OpencvSfM{ 00031 00032 MotionProcessor::MotionProcessor( void ) 00033 { 00034 numFrame_=0; 00035 pos_in_loading_process_ = 0; 00036 wantedWidth_=-1; 00037 wantedHeight_=-1; 00038 convertToRGB_=-1; 00039 } 00040 00041 MotionProcessor::~MotionProcessor( void ) 00042 { 00043 switch( type_of_input_ ) 00044 { 00045 case IS_WEBCAM: 00046 case IS_VIDEO: 00047 capture_.release( ); 00048 break; 00049 case IS_DIRECTORY: 00050 case IS_LIST_FILES: 00051 case IS_SINGLE_FILE: 00052 nameOfFiles_.clear( ); 00053 break; 00054 } 00055 } 00056 00057 bool MotionProcessor::setInputSource( int idWebCam ) 00058 { 00059 if( this->capture_.open( idWebCam )) 00060 { 00061 this->type_of_input_=IS_WEBCAM; 00062 //if we have some properties, set them to the webcam: 00063 this->capture_.set( CV_CAP_PROP_CONVERT_RGB,this->convertToRGB_>0 ); 00064 if( wantedHeight_>0 ) 00065 this->capture_.set( CV_CAP_PROP_FRAME_HEIGHT,this->wantedHeight_ ); 00066 if( wantedWidth_>0 ) 00067 this->capture_.set( CV_CAP_PROP_FRAME_WIDTH,this->wantedWidth_ ); 00068 return true; 00069 }; 00070 return false; 00071 }; 00072 00073 bool MotionProcessor::setInputSource( std::vector< std::string > list_images ) 00074 { 00075 this->type_of_input_=IS_LIST_FILES; 00076 nameOfFiles_ = list_images; 00077 suffix_ = "Not a dynamic list"; 00078 return true; 00079 }; 00080 00081 bool MotionProcessor::setInputSource( std::string nameOfFile, 00082 TypeOfMotionProcessor inputType/*=IS_VIDEO*/ ) 00083 {//IS_DIRECTORY, IS_VIDEO or IS_SINGLE_FILE 00084 this->sourceName_=nameOfFile; 00085 this->type_of_input_=inputType; 00086 00087 if( inputType == IS_VIDEO ) 00088 return this->capture_.open( nameOfFile ); 00089 00090 if( inputType == IS_DIRECTORY ) 00091 { 00092 #ifdef HAVE_BOOST 00093 path dirTmp( nameOfFile.c_str( ) ); 00094 if ( !boost::filesystem::exists( dirTmp ) || !boost::filesystem::is_directory( dirTmp ) ) { 00095 return false; 00096 } 00097 00098 boost::filesystem::directory_iterator iter= boost::filesystem::directory_iterator( dirTmp ); 00099 while( iter != boost::filesystem::directory_iterator( ) ) 00100 { 00101 string name_of_file = iter->path( ).string( ); 00102 if( cv::cvHaveImageReader( (const char* )name_of_file.c_str( ) ) ) 00103 nameOfFiles_.push_back( name_of_file ); 00104 iter++; 00105 } 00106 //if we don't have loaded files, return an error! 00107 if( nameOfFiles_.empty( ) ) 00108 return false; 00109 00110 // sort, since directory iteration 00111 // is not ordered on some file systems 00112 std::sort( nameOfFiles_.begin( ), nameOfFiles_.end( ) ); 00113 #else 00114 return false; 00115 #endif 00116 } 00117 return true; 00118 }; 00119 00120 bool MotionProcessor::setInputSource( std::string prefix, std::string suffix, 00121 int startNumber/*=0*/ ) 00122 { 00123 this->sourceName_ = prefix; 00124 this->suffix_ = suffix; 00125 pos_in_loading_process_ = startNumber; 00126 this->type_of_input_ = IS_LIST_FILES; 00127 return true; 00128 //always true because the error will occur when user will try to get the frame, not now... 00129 }; 00130 00131 cv::Mat MotionProcessor::getFrame( ) 00132 { 00133 Mat imgTmp; 00134 00135 //Is the current cursor in the middle of the video? 00136 if( type_of_input_==IS_LIST_FILES && numFrame_<nameOfFiles_.size( ) ) 00137 { 00138 //Someone as changed the position of cursor... 00139 //Reload the wanted file: 00140 imgTmp=imread( nameOfFiles_[ numFrame_ ],convertToRGB_ ); 00141 this->numFrame_++;//and move to the next frame 00142 } 00143 else 00144 { 00145 switch( type_of_input_ ) 00146 { 00147 case IS_WEBCAM: 00148 case IS_VIDEO: 00149 { 00150 //Get the current image from file: 00151 bool aNewFrameIsAvailable=capture_.grab( ); 00152 if( aNewFrameIsAvailable ) 00153 { 00154 capture_.retrieve( imgTmp ); 00155 } 00156 } 00157 break; 00158 case IS_LIST_FILES: 00159 { 00160 ostringstream oss; 00161 oss<<this->sourceName_<<this->numFrame_<<this->suffix_; 00162 00163 imgTmp=imread( oss.str( ).c_str( ),convertToRGB_ ); 00164 this->numFrame_++; 00165 00166 unsigned int stop=this->numFrame_+10; 00167 while( imgTmp.empty( )&&stop>this->numFrame_ ){ 00168 oss.str( "" ); 00169 oss<<this->sourceName_<<this->numFrame_<<this->suffix_; 00170 imgTmp=imread( oss.str( ).c_str( ),convertToRGB_ ); 00171 this->numFrame_++; 00172 } 00173 if( ! imgTmp.empty( ) ) 00174 nameOfFiles_.push_back( oss.str( ) );//add the new file 00175 } 00176 break; 00177 case IS_DIRECTORY: 00178 { 00179 if( numFrame_<nameOfFiles_.size( ) ) 00180 { 00181 imgTmp=imread( nameOfFiles_[ numFrame_ ],convertToRGB_ ); 00182 this->numFrame_++;//and move to the next frame 00183 } 00184 } 00185 break; 00186 case IS_SINGLE_FILE: 00187 { 00188 imgTmp=imread( this->sourceName_.c_str( ),convertToRGB_ ); 00189 } 00190 break; 00191 } 00192 } 00193 00194 if( !imgTmp.empty( ) ) 00195 { 00196 //now we ensure the file as the good properties: 00197 //First the colors: 00198 if( (( (convertToRGB_>0) && imgTmp.channels( )<=1 ) || 00199 ( (convertToRGB_==0) && imgTmp.channels( )!=1 )) ) 00200 { 00201 Mat correctImg; 00202 if( convertToRGB_==0 ) 00203 cvtColor( imgTmp,correctImg,CV_RGB2GRAY ); 00204 else 00205 cvtColor( imgTmp,correctImg,CV_GRAY2RGB ); 00206 imgTmp=correctImg; 00207 } 00208 //then the width and height: 00209 if( (( wantedHeight_>0 )&&( wantedHeight_!=imgTmp.rows ))|| 00210 ( (wantedWidth_>0 )&&( wantedWidth_!=imgTmp.cols )) ) 00211 { 00212 Mat correctImg; 00213 int widthTmp=wantedWidth_; 00214 if( wantedWidth_<=0 ) 00215 widthTmp=imgTmp.cols; 00216 int heightTmp=wantedHeight_; 00217 if( wantedHeight_<=0 ) 00218 heightTmp=imgTmp.cols; 00219 cv::resize( imgTmp,correctImg,Size( widthTmp,heightTmp )); 00220 imgTmp=correctImg; 00221 } 00222 } 00223 00224 return imgTmp; 00225 } 00226 00227 bool MotionProcessor::setProperty( int _idProp,double _value ) 00228 { 00229 bool videoCaptureLikeThisProperty=true; 00230 if( type_of_input_==IS_WEBCAM||type_of_input_==IS_VIDEO ) 00231 videoCaptureLikeThisProperty = capture_.set( _idProp,_value ); 00232 if( ! videoCaptureLikeThisProperty ) 00233 return false;//as the VideoCapture object don't want this property, don't do anything else. 00234 00235 //First store the property using attributs: 00236 switch ( _idProp ) 00237 { 00238 case CV_CAP_PROP_CONVERT_RGB://Boolean flags indicating whether images should be converted to RGB 00239 convertToRGB_ = ( int )_value; 00240 break; 00241 case CV_CAP_PROP_FRAME_HEIGHT://Height of the frames in the video stream 00242 wantedHeight_= ( int )_value; 00243 break; 00244 case CV_CAP_PROP_FRAME_WIDTH://Width of the frames in the video stream 00245 wantedWidth_= ( int )_value; 00246 break; 00247 case CV_CAP_PROP_POS_FRAMES:// 0-based index of the frame to be decoded/captured next 00248 { 00249 if( type_of_input_==IS_LIST_FILES||type_of_input_==IS_SINGLE_FILE ) 00250 { 00251 if( _value>=0&&_value<=nameOfFiles_.size( ) ) 00252 numFrame_=( unsigned int )_value; 00253 else 00254 CV_Error( CV_StsBadArg, "CV_CAP_PROP_POS_FRAMES: _value out of range!" ); 00255 } 00256 }; 00257 break; 00258 case CV_CAP_PROP_FORMAT://The format of the Mat objects returned by retrieve( ) 00259 case CV_CAP_PROP_POS_MSEC://Film current position in milliseconds or video capture timestamp 00260 case CV_CAP_PROP_FPS://Frame rate 00261 case CV_CAP_PROP_FOURCC://4-character code of codec 00262 case CV_CAP_PROP_MODE:// A backend-specific value indicating the current capture mode 00263 case CV_CAP_PROP_BRIGHTNESS:// Brightness of the image ( only for cameras ) 00264 case CV_CAP_PROP_CONTRAST:// Contrast of the image ( only for cameras ) 00265 case CV_CAP_PROP_SATURATION:// Saturation of the image ( only for cameras ) 00266 case CV_CAP_PROP_HUE:// Hue of the image ( only for cameras ) 00267 case CV_CAP_PROP_GAIN:// Gain of the image ( only for cameras ) 00268 case CV_CAP_PROP_EXPOSURE:// Exposure ( only for cameras ) 00269 case CV_CAP_PROP_FRAME_COUNT://Number of frames in the video file 00270 //case CV_CAP_PROP_WHITE_BALANCE://Currently unsupported 00271 case CV_CAP_PROP_RECTIFICATION://TOWRITE ( note: only supported by DC1394 v 2.x backend currently ) 00272 { 00273 if( type_of_input_==IS_LIST_FILES||type_of_input_==IS_SINGLE_FILE||type_of_input_==IS_DIRECTORY ) 00274 return false; 00275 //else, do nothing as the property is already assigned 00276 } 00277 break; 00278 case CV_CAP_PROP_POS_AVI_RATIO: 00279 //Relative position of the video file ( 0 - start of the film, 1 - end of the film ) 00280 { 00281 if( (type_of_input_==IS_LIST_FILES && suffix_ != "Not a dynamic list" )|| 00282 type_of_input_== IS_SINGLE_FILE ) 00283 return false; 00284 else 00285 { 00286 if( type_of_input_==IS_DIRECTORY ) 00287 { 00288 numFrame_=( unsigned int ) ( _value*nameOfFiles_.size( ) ); 00289 } 00290 } 00291 } 00292 break; 00293 default: 00294 return false; 00295 break; 00296 } 00297 00298 //if the motion stream come from capture_, update the structure too: 00299 return true; 00300 }; 00301 00302 double MotionProcessor::getProperty( int idProp ) 00303 { 00304 double valOut=0; 00305 switch( type_of_input_ ) 00306 { 00307 case IS_WEBCAM: 00308 case IS_VIDEO: 00309 valOut = capture_.get( idProp ); 00310 break; 00311 case IS_LIST_FILES: 00312 case IS_SINGLE_FILE: 00313 { 00314 switch ( idProp ) 00315 { 00316 case CV_CAP_PROP_CONVERT_RGB://Boolean flags indicating whether images should be converted to RGB 00317 { 00318 valOut=convertToRGB_; 00319 }; 00320 break; 00321 case CV_CAP_PROP_FRAME_HEIGHT://Height of the frames in the video stream 00322 { 00323 valOut=wantedHeight_; 00324 }; 00325 break; 00326 case CV_CAP_PROP_FRAME_WIDTH://Width of the frames in the video stream 00327 { 00328 valOut=wantedWidth_; 00329 }; 00330 break; 00331 case CV_CAP_PROP_POS_FRAMES:// 0-based index of the frame to be decoded/captured next 00332 { 00333 valOut=numFrame_; 00334 }; 00335 break; 00336 case CV_CAP_PROP_POS_AVI_RATIO://Relative position of the video file ( 0 - start of the film, 1 - end of the film ) 00337 { 00338 if( type_of_input_==IS_LIST_FILES||type_of_input_==IS_SINGLE_FILE ) 00339 CV_Error( CV_StsBadArg, "MotionProcessor unknow property !" ); 00340 else 00341 { 00342 if( type_of_input_==IS_DIRECTORY ) 00343 { 00344 valOut=( (double )numFrame_/nameOfFiles_.size( ) ); 00345 } 00346 } 00347 } 00348 break; 00349 case CV_CAP_PROP_FRAME_COUNT://Number of frames in the video file 00350 { 00351 if( type_of_input_==IS_LIST_FILES||type_of_input_==IS_SINGLE_FILE ) 00352 CV_Error( CV_StsBadArg, "MotionProcessor unknow property !" ); 00353 else 00354 { 00355 if( type_of_input_==IS_DIRECTORY ) 00356 { 00357 numFrame_=( unsigned int )idProp; 00358 } 00359 } 00360 } 00361 break; 00362 case CV_CAP_PROP_FORMAT://The format of the Mat objects returned by retrieve( ) 00363 case CV_CAP_PROP_POS_MSEC://Film current position in milliseconds or video capture timestamp 00364 case CV_CAP_PROP_FPS://Frame rate 00365 case CV_CAP_PROP_FOURCC://4-character code of codec 00366 case CV_CAP_PROP_MODE:// A backend-specific value indicating the current capture mode 00367 case CV_CAP_PROP_BRIGHTNESS:// Brightness of the image ( only for cameras ) 00368 case CV_CAP_PROP_CONTRAST:// Contrast of the image ( only for cameras ) 00369 case CV_CAP_PROP_SATURATION:// Saturation of the image ( only for cameras ) 00370 case CV_CAP_PROP_HUE:// Hue of the image ( only for cameras ) 00371 case CV_CAP_PROP_GAIN:// Gain of the image ( only for cameras ) 00372 case CV_CAP_PROP_EXPOSURE:// Exposure ( only for cameras ) 00373 //case CV_CAP_PROP_WHITE_BALANCE://Currently unsupported 00374 case CV_CAP_PROP_RECTIFICATION://TOWRITE ( note: only supported by DC1394 v 2.x backend currently ) 00375 default: 00376 CV_Error( CV_StsBadArg, "MotionProcessor unknow property !" ); 00377 break; 00378 } 00379 } 00380 break; 00381 } 00382 00383 return valOut; 00384 } 00385 00386 }