00001 /*!@file Beobot/beobot-collectFrames-master.C 00002 Run beobot-collectFrames-master at A to collect frames 00003 Run beobot-collectFrames at B to remote control motion */ 00004 00005 // //////////////////////////////////////////////////////////////////// // 00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00007 // University of Southern California (USC) and the iLab at USC. // 00008 // See http://iLab.usc.edu for information about this project. // 00009 // //////////////////////////////////////////////////////////////////// // 00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00012 // in Visual Environments, and Applications'' by Christof Koch and // 00013 // Laurent Itti, California Institute of Technology, 2001 (patent // 00014 // pending; application number 09/912,225 filed July 23, 2001; see // 00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00016 // //////////////////////////////////////////////////////////////////// // 00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00018 // // 00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00020 // redistribute it and/or modify it under the terms of the GNU General // 00021 // Public License as published by the Free Software Foundation; either // 00022 // version 2 of the License, or (at your option) any later version. // 00023 // // 00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00027 // PURPOSE. See the GNU General Public License for more details. // 00028 // // 00029 // You should have received a copy of the GNU General Public License // 00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00032 // Boston, MA 02111-1307 USA. // 00033 // //////////////////////////////////////////////////////////////////// // 00034 // 00035 // Primary maintainer for this file: Christian Siagian <siagian@usc.edu> 00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/beobot-collectFrames-master.C $ 00037 // $Id: beobot-collectFrames-master.C 9412 2008-03-10 23:10:15Z farhan $ 00038 // 00039 00040 #include "Beowulf/Beowulf.H" 00041 #include "Component/ModelManager.H" 00042 #include "Util/Types.H" 00043 #include "Util/log.H" 00044 00045 #include <cstdio> 00046 #include <cstdlib> 00047 #include <signal.h> 00048 #include <unistd.h> 00049 00050 #include "Devices/FrameGrabberConfigurator.H" 00051 #include "Image/DrawOps.H" 00052 #include "Transport/FrameIstream.H" 00053 //#include "Image/Image.H" 00054 #include "Image/ImageCache.H" 00055 #include "Image/Pixels.H" 00056 #include "Raster/Raster.H" 00057 #include "Util/Timer.H" 00058 // #include <pthread.h> 00059 00060 #include "GUI/XWinManaged.H" 00061 #include "GUI/XWindow.H" 00062 00063 //! number of frames over which frame rate is computed 00064 #define NAVG 20 00065 00066 //! Maximum number of frames in queue 00067 #define MAXQLEN 1000 00068 00069 00070 pthread_mutex_t qmutex; 00071 pthread_mutex_t smutex; 00072 ImageCache< PixRGB<byte> > cache; 00073 std::string base; 00074 int sessionNum = 0; 00075 00076 static bool goforever = true; 00077 00078 // ###################################################################### 00079 void* saveframes(void *) 00080 { 00081 int fnb = 0; int sNum= -1; 00082 while(1) { 00083 Image< PixRGB<byte> > ima; bool havemore = false; 00084 00085 // do we have images ready to go? 00086 pthread_mutex_lock(&qmutex); 00087 if (cache.size()) ima = cache.pop_front(); 00088 if (cache.size()) havemore = true; 00089 pthread_mutex_unlock(&qmutex); 00090 00091 int tNum; 00092 pthread_mutex_lock(&smutex); 00093 tNum = sessionNum-1; 00094 pthread_mutex_unlock(&smutex); 00095 00096 if(sNum < tNum) 00097 { 00098 sNum = tNum; 00099 fnb = 0; 00100 } 00101 00102 // if we got an image, save it: 00103 if (ima.initialized()) 00104 { 00105 Raster::WriteRGB(ima, sformat("%s%03d_%06d.ppm", 00106 base.c_str(), sNum, fnb)); 00107 LINFO("saving %s%03d_%06d", base.c_str(), sNum, fnb); 00108 fnb++; 00109 } 00110 if (havemore == false) usleep(1000); 00111 } 00112 return NULL; 00113 } 00114 00115 // ###################################################################### 00116 void terminate(int s) 00117 { LERROR("*** INTERRUPT ***"); goforever = false; exit(1); } 00118 00119 // ###################################################################### 00120 /*! Displays and grabs video feeds to disk. Selection of grabber type 00121 is made via the --fg-type=XX command-line option. 00122 Frames are pushed into a queue and a second thread then 00123 tries to empty the queue as quickly as possible by writing the 00124 frames to disk. In testing, PPM format actually gave better frame 00125 rates than PNG, which is what is used. 00126 00127 The starting command is supplied from the beoChip keyboard 00128 */ 00129 int main(const int argc, const char **argv) 00130 { 00131 // instantiate a model manager: 00132 ModelManager manager("Beobot: collect frames - Master"); 00133 00134 // Instantiate our various ModelComponents: 00135 nub::soft_ref<Beowulf> 00136 beo(new Beowulf(manager, "Beowulf Master", "BeowulfMaster", true)); 00137 manager.addSubComponent(beo); 00138 00139 nub::soft_ref<FrameGrabberConfigurator> 00140 gbc(new FrameGrabberConfigurator(manager)); 00141 manager.addSubComponent(gbc); 00142 00143 // Parse command-line: 00144 if (manager.parseCommandLine(argc, argv, "<base>", 1, 1) == false) return(1); 00145 00146 // do post-command-line configs: 00147 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber(); 00148 if (gb.isInvalid()) 00149 LFATAL("You need to select a frame grabber type via the " 00150 "--fg-type=XX command-line option for this program " 00151 "to be useful -- ABORT"); 00152 //int w = gb->getWidth(), h = gb->getHeight(); 00153 00154 // display window 00155 XWindow win(gb->peekDims(), -1, -1, "grab window"); 00156 00157 TCPmessage rmsg; // buffer to receive messages from nodes 00158 TCPmessage smsg; // buffer to send messages to nodes 00159 00160 // get the basename: 00161 base = manager.getExtraArg(0);//"../data/beobotCF_"; 00162 00163 // let's get all our ModelComponent instances started: 00164 manager.start(); 00165 00166 // catch signals and redirect them to terminate for clean exit: 00167 signal(SIGHUP, terminate); signal(SIGINT, terminate); 00168 signal(SIGQUIT, terminate); signal(SIGTERM, terminate); 00169 signal(SIGALRM, terminate); 00170 00171 // get ready for main loop: 00172 int32 rframe = 0, raction = 0, rnode = 0; 00173 // this code is just for one slave for now 00174 //const int nbnode = beo->getNbSlaves(); // number of slave nodes 00175 00176 // activate the saving thread 00177 Timer tim; uint64 t[NAVG]; float frate = 0.0f; 00178 pthread_t saver; 00179 pthread_create(&saver, NULL, &saveframes, (void *)NULL); 00180 bool saving = false; 00181 00182 // get the frame grabber to start streaming: 00183 gb->startStream(); 00184 00185 // send image to slave node to initialize contact: 00186 smsg.reset(rframe, 1); 00187 smsg.addFloat(2.3434); 00188 beo->send(rnode, smsg); 00189 00190 // grab, display and save: 00191 int fNum = 0; 00192 while(goforever) 00193 { 00194 tim.reset(); 00195 00196 // grab a frame 00197 Image< PixRGB<byte> > ima = gb->readRGB(); 00198 00199 // to measure display time: 00200 uint64 t0 = tim.get(); 00201 00202 // check if we need to start(1) or stop(0) saving 00203 if(beo->receive(rnode, rmsg, rframe, raction, 5)) 00204 { 00205 LINFO("receiving"); 00206 const int32 val = rmsg.getElementInt32(); 00207 bool msg = bool(val); 00208 rmsg.reset(rframe, raction); 00209 if(msg) 00210 LINFO("start capturing"); 00211 else 00212 LINFO("stop capturing"); 00213 00214 // if we are start saving 00215 if(!saving & msg) 00216 { 00217 pthread_mutex_lock(&smutex); 00218 sessionNum++; 00219 pthread_mutex_unlock(&smutex); 00220 saving = true; 00221 } 00222 else if(saving & !msg) 00223 { 00224 saving = false; 00225 } 00226 } 00227 00228 // if saving, push image into queue: 00229 if (saving) 00230 { 00231 pthread_mutex_lock(&qmutex); 00232 cache.push_back(ima); 00233 pthread_mutex_unlock(&qmutex); 00234 char msg[30]; sprintf(msg, " %.1ffps [%04d] ", frate, cache.size()); 00235 writeText(ima,Point2D<int>(0, 0), msg, PixRGB<byte>(255), PixRGB<byte>(0)); 00236 } 00237 else // tell user we are ready to save 00238 { 00239 char msg[30]; sprintf(msg, " [SPC] to save [%04d] ", cache.size()); 00240 writeText(ima,Point2D<int>(0, 0), msg, PixRGB<byte>(255), PixRGB<byte>(0)); 00241 } 00242 00243 // show the frame: 00244 win.drawImage(ima); 00245 00246 t[fNum % NAVG] = tim.get(); 00247 t0 = t[fNum % NAVG] - t0; 00248 if (t0 > 20000ULL) LINFO("Display took %lluus", t0); 00249 00250 // compute and show framerate over the last NAVG frames: 00251 if (fNum % NAVG == 0 && fNum > 0) 00252 { 00253 uint64 avg = 0ULL; for (int i = 0; i < NAVG; i ++) avg += t[i]; 00254 frate = 1000.0F / float(avg) * float(NAVG); 00255 } 00256 00257 fNum++; 00258 } 00259 00260 // stop all our ModelComponents 00261 manager.stop(); 00262 00263 // all done! 00264 return 0; 00265 } 00266 00267 // ###################################################################### 00268 /* So things look consistent in everyone's emacs... */ 00269 /* Local Variables: */ 00270 /* indent-tabs-mode: nil */ 00271 /* End: */