neovision2-hd.C

Go to the documentation of this file.
00001 /*!@file INVT/neovision2-hd.C Neovision demo for HD streams and 1080p display*/
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/INVT/neovision2-hd.C $
00035 // $Id: neovision2-hd.C 12782 2010-02-05 22:14:30Z irock $
00036 //
00037 
00038 #include "Image/OpenCVUtil.H"  // must be first to avoid conflicting defs of int64, uint64
00039 
00040 #include "Component/GlobalOpts.H"
00041 #include "Component/ModelManager.H"
00042 #include "Component/ModelOptionDef.H"
00043 #include "Component/ModelParam.H"
00044 #include "Component/ModelParamBatch.H"
00045 #include "Devices/DeviceOpts.H"
00046 #include "Devices/IEEE1394grabber.H"
00047 #include "GUI/ImageDisplayStream.H"
00048 #include "GUI/PrefsWindow.H"
00049 #include "GUI/XWinManaged.H"
00050 #include "Image/ColorOps.H"
00051 #include "Image/CutPaste.H"
00052 #include "Image/DrawOps.H"
00053 #include "Image/FilterOps.H"
00054 #include "Image/Image.H"
00055 #include "Image/ImageSet.H"
00056 #include "Image/Layout.H"
00057 #include "Image/MathOps.H"
00058 #include "Image/Pixels.H"
00059 #include "Image/PyramidOps.H"
00060 #include "Image/ShapeOps.H"
00061 #include "Image/Transforms.H"
00062 #include "Media/BufferedInputFrameSeries.H"
00063 #include "Media/FrameSeries.H"
00064 #include "Media/MediaOpts.H"
00065 #include "NeovisionII/Nv2LabelReader.H"
00066 #include "NeovisionII/nv2_common.h"
00067 #include "Neuro/NeoBrain.H"
00068 #include "Neuro/EnvInferoTemporal.H"
00069 #include "Neuro/EnvSaliencyMap.H"
00070 #include "Neuro/EnvSegmenterConfigurator.H"
00071 #include "Neuro/EnvVisualCortex.H"
00072 #include "Raster/GenericFrame.H"
00073 #include "Raster/Raster.H"
00074 #include "Transport/FrameInfo.H"
00075 #include "Transport/TransportOpts.H"
00076 #include "Util/FpsTimer.H"
00077 #include "Util/Pause.H"
00078 #include "Util/StringConversions.H"
00079 #include "Util/StringUtil.H"
00080 #include "Util/SyncJobServer.H"
00081 #include "Util/SysInfo.H"
00082 #include "Util/TextLog.H"
00083 #include "Util/WorkThreadServer.H"
00084 #include "Util/csignals.H"
00085 #include "rutz/shared_ptr.h"
00086 #include "rutz/trace.h"
00087 
00088 #include <ctype.h>
00089 #include <deque>
00090 #include <iterator>
00091 #include <limits>
00092 #include <stdlib.h> // for atoi(), malloc(), free()
00093 #include <string.h>
00094 #include <sys/resource.h>
00095 #include <signal.h>
00096 #include <time.h>
00097 #include <vector>
00098 
00099 #define PREFERRED_TEXT_LENGTH 42
00100 
00101 struct Nv2UiData
00102 {
00103   Nv2UiData(const int map_zoom_) :
00104     map_zoom(map_zoom_), ncpu(numCpus())
00105   {}
00106 
00107   FpsTimer::State time_state;
00108   const int map_zoom;
00109   const int ncpu;
00110 };
00111 
00112 std::string time2str(const rutz::time& t)
00113 {
00114   const double s = t.sec();
00115 
00116   const int hpart = int(s/(60.0*60.0));
00117   const int mpart = int((s-hpart*60*60)/60.0);
00118   const double spart = s - hpart*60*60 - mpart*60;
00119 
00120   return sformat("%02d:%02d:%06.3f", hpart, mpart, spart);
00121 }
00122 
00123 class Nv2UiJob : public JobServer::Job
00124 {
00125 public:
00126   Nv2UiJob(OutputFrameSeries* ofs_, const Nv2UiData& uidata_,
00127            Image<PixRGB<byte> > rgbin_, Image<byte> vcxmap_,
00128            Image<byte> Imap_, Image<byte> Cmap_, Image<byte> Omap_
00129 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00130            , Image<byte> Fmap_, Image<byte> Mmap_
00131 #endif
00132                 ) :
00133     ofs(ofs_), uidata(uidata_), rgbin(rgbin_), vcxmap(vcxmap_),
00134     Imap(Imap_), Cmap(Cmap_), Omap(Omap_)
00135 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00136     , Fmap(Fmap_), Mmap(Mmap_)
00137 #endif
00138   { }
00139 
00140   virtual void run()
00141   {
00142     ofs->updateNext();
00143 
00144     Point2D<int> win; byte winval;
00145     findMax(vcxmap, win, winval);
00146     win = win * uidata.map_zoom;
00147 
00148     // do a markup on the input images:
00149     Image<PixRGB<byte> > markup = rgbin;
00150     drawCircle(markup, win, 3, PixRGB<byte>(60, 220, 255), 3);
00151 
00152     // do the saliency map:
00153     Image<byte> sm = vcxmap; // for now
00154     Image<PixRGB<byte> > smc =
00155       zoomXY(sm, uidata.map_zoom / 2, uidata.map_zoom / 2);
00156     drawCircle(smc, win/2, 3, PixRGB<byte>(60, 220, 255), 3);
00157 
00158     const std::string lines[2] =
00159       {
00160         sformat("peak %3d @ (%3d,%3d)",
00161                 winval, win.i, win.j),
00162         sformat("%s [%5.2ffps, %5.1f%%CPU]",
00163                 time2str(uidata.time_state.elapsed_time).c_str(),
00164                 uidata.time_state.recent_fps,
00165                 uidata.time_state.recent_cpu_usage*100.0)
00166       };
00167 
00168     const Image<PixRGB<byte> > textarea =
00169       makeMultilineTextBox(smc.getWidth(), &lines[0], 2,
00170                            PixRGB<byte>(255, 255, 0), PixRGB<byte>(0,0,0),
00171                            PREFERRED_TEXT_LENGTH);
00172 
00173     Layout<PixRGB<byte> > disp = vcat(smc, textarea);
00174 
00175     //   ofs->writeRgbLayout(disp, "neovision2-HD Control",
00176     //                   FrameInfo("copy of input", SRC_POS));
00177     ofs->writeRGB(markup, "neovision2-HD",
00178                   FrameInfo("copy of input", SRC_POS));
00179   }
00180 
00181   virtual const char* jobType() const { return "Nv2UiJob"; }
00182 
00183 private:
00184   OutputFrameSeries* const ofs;
00185   const Nv2UiData uidata;
00186   Image<PixRGB<byte> > rgbin;
00187   const Image<byte> vcxmap;
00188   const Image<byte> Imap;
00189   const Image<byte> Cmap;
00190   const Image<byte> Omap;
00191 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00192   const Image<byte> Fmap;
00193   const Image<byte> Mmap;
00194 #endif
00195 };
00196 
00197 // ######################################################################
00198 int submain(int argc, const char** argv)
00199 {
00200   volatile int signum = 0;
00201   signal(SIGPIPE, SIG_IGN);
00202   catchsignals(&signum);
00203 
00204   // Instantiate our various ModelComponents:
00205 
00206   ModelManager manager("Nv2hd");
00207 
00208   nub::ref<BufferedInputFrameSeries>
00209     ifs(new BufferedInputFrameSeries(manager, 50, true));
00210   manager.addSubComponent(ifs);
00211 
00212   nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00213   manager.addSubComponent(ofs);
00214 
00215   nub::ref<EnvVisualCortex> evc(new EnvVisualCortex(manager));
00216   manager.addSubComponent(evc);
00217 
00218   manager.exportOptions(MC_RECURSE);
00219 
00220 #if defined(HAVE_IEEE1394)
00221   // input comes from firewire camera 640x480/rgb/30fps by default
00222   manager.setOptionValString(&OPT_InputFrameSource, "ieee1394");
00223   manager.setOptionValString(&OPT_FrameGrabberMode, "RGB24");
00224   manager.setOptionValString(&OPT_FrameGrabberDims, "640x480");
00225   manager.setOptionValString(&OPT_FrameGrabberFPS, "30");
00226 #elif defined(HAVE_QUICKTIME_QUICKTIME_H)
00227   manager.setOptionValString(&OPT_InputFrameSource, "qtgrab");
00228   manager.setOptionValString(&OPT_FrameGrabberDims, "640x480");
00229 #endif
00230 
00231   // output goes to the screen by default
00232   manager.setOptionValString(&OPT_OutputFrameSink, "display");
00233 
00234   // change some default values
00235   manager.setOptionValString(&OPT_EvcColorSmoothing, "true");
00236 
00237   if (manager.parseCommandLine(argc, argv,
00238                                "<ip1:port1,ip2:port2,...>",
00239                                0, 1) == false)
00240     return(1);
00241 
00242   manager.start();
00243 
00244   Nv2UiData uidata(1 << evc->getMapLevel());
00245 
00246   // set up a background job server with one worker thread to
00247   // handle the ui jobs:
00248   rutz::shared_ptr<WorkThreadServer> tsrv
00249     (new WorkThreadServer("neovision2-ui", 1));
00250 
00251   // keep max latency low, and if we get bogged down, then drop
00252   // old frames rather than new ones
00253   tsrv->setMaxQueueSize(3);
00254   tsrv->setDropPolicy(WorkThreadServer::DROP_OLDEST);
00255   tsrv->setFlushBeforeStopping(true);
00256   rutz::shared_ptr<JobServer> uiq = tsrv;
00257 
00258   /////////////  ifs->startStream();
00259 
00260   const GenericFrameSpec fspec = ifs->peekFrameSpec();
00261   Image<PixRGB<byte> > rgbin_last(fspec.dims, ZEROS);
00262   FpsTimer fps_timer;
00263 
00264   int retval = 0; bool toggle = true; Image<byte> vcxmap;
00265   while (true)
00266     {
00267       if (signum != 0)
00268         {
00269           LINFO("quitting because %s was caught", signame(signum));
00270           retval = -1;
00271           break;
00272         }
00273 
00274       if (ofs->becameVoid())
00275         {
00276           LINFO("quitting because output stream was closed or became void");
00277           break;
00278         }
00279 
00280       //
00281       // get the next frame from our input source
00282       //
00283       bool underflowed;
00284       Image<PixRGB<byte> > rgbin;
00285       GenericFrame input = ifs->get(&underflowed);
00286       if (!input.initialized())
00287         {
00288           if (underflowed) { LINFO("Input underflow!"); rgbin = rgbin_last; }
00289           else break; // end of stream or error
00290         }
00291       else
00292         rgbin = input.asRgb();
00293 
00294       rgbin_last = rgbin;
00295 
00296       //
00297       // send the frame to the EnvVisualCortex and get the vcx output
00298       //
00299       if (toggle)
00300         {
00301           evc->input(rgbin);
00302           vcxmap = evc->getVCXmap();
00303         }
00304 
00305       toggle = !toggle;
00306 
00307       fps_timer.nextFrame();
00308       uidata.time_state = fps_timer.getState();
00309 
00310       if (uidata.time_state.frame_number % 50 == 0)
00311         LINFO("frame %u: %.2f fps",
00312               uidata.time_state.frame_number,
00313               uidata.time_state.recent_fps);
00314 
00315       //
00316       // build a ui job to run in the background to display update the
00317       // saliency map the input frame, the vcx maps,
00318       //
00319       uiq->enqueueJob(rutz::make_shared
00320                       (new Nv2UiJob
00321                        (ofs.get(), uidata, rgbin, vcxmap, evc->getImap(),
00322                         evc->getCmap(), evc->getOmap()
00323 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00324                         , evc->getFmap(), evc->getMmap()
00325 #endif
00326                         )));
00327     }
00328 
00329   // destroy the ui queue so that we force it to shut down now
00330   uiq.reset(0);
00331 
00332   manager.stop();
00333 
00334   return retval;
00335 }
00336 
00337 // ######################################################################
00338 int main(int argc, const char** argv)
00339 {
00340   try
00341     {
00342       return submain(argc, argv);
00343     }
00344   catch (...)
00345     {
00346       REPORT_CURRENT_EXCEPTION;
00347     }
00348 }
00349 
00350 // ######################################################################
00351 /* So things look consistent in everyone's emacs... */
00352 /* Local Variables: */
00353 /* mode: c++ */
00354 /* indent-tabs-mode: nil */
00355 /* End: */
Generated on Sun May 8 08:40:58 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3