neovision2.C

Go to the documentation of this file.
00001 /*!@file INVT/neovision2.C Neovision2 integrated demo */
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.C $
00035 // $Id: neovision2.C 14376 2011-01-11 02:44:34Z pez $
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/FrameSeries.H"
00063 #include "Media/MediaOpts.H"
00064 #include "NeovisionII/Nv2LabelReader.H"
00065 #include "NeovisionII/nv2_common.h"
00066 #include "Neuro/NeoBrain.H"
00067 #include "Neuro/EnvInferoTemporal.H"
00068 #include "Neuro/EnvSaliencyMap.H"
00069 #include "Neuro/EnvSegmenterConfigurator.H"
00070 #include "Neuro/EnvVisualCortex.H"
00071 #include "Raster/GenericFrame.H"
00072 #include "Raster/Raster.H"
00073 #include "Transport/FrameInfo.H"
00074 #include "Transport/TransportOpts.H"
00075 #include "Util/FpsTimer.H"
00076 #include "Util/Pause.H"
00077 #include "Util/StringConversions.H"
00078 #include "Util/StringUtil.H"
00079 #include "Util/SyncJobServer.H"
00080 #include "Util/SysInfo.H"
00081 #include "Util/TextLog.H"
00082 #include "Util/WorkThreadServer.H"
00083 #include "Util/csignals.H"
00084 #include "rutz/shared_ptr.h"
00085 #include "rutz/trace.h"
00086 
00087 #include <ctype.h>
00088 #include <deque>
00089 #include <iterator>
00090 #include <limits>
00091 #include <stdlib.h> // for atoi(), malloc(), free()
00092 #include <string.h>
00093 #include <sys/resource.h>
00094 #include <signal.h>
00095 #include <time.h>
00096 #include <vector>
00097 
00098 const size_t PREFERRED_TEXT_LENGTH = 42;
00099 
00100 // ######################################################################
00101 class EnvSimulationViewer : public ModelComponent
00102 {
00103 public:
00104   EnvSimulationViewer(OptionManager& mgr);
00105 
00106   virtual ~EnvSimulationViewer();
00107 
00108   virtual void paramChanged(ModelParamBase* const param, const bool valueChanged, ParamClient::ChangeStatus* status);
00109 
00110   bool shouldQuit() const { return itsDoQuit; }
00111 
00112   OModelParam<Dims> itsInputDims;
00113   OModelParam<bool> optAsyncUi;
00114   OModelParam<uint> optAsyncUiQueueSize;
00115   OModelParam<bool> optFlushUiQueue;
00116   OModelParam<bool> itsNeovision2Gui;
00117   OModelParam<bool> optCompactDisplay;
00118   OModelParam<byte> optExtendedDisplay;
00119   OModelParam<size_t> optDispZoom;
00120   OModelParam<size_t> optInputReduce;
00121   OModelParam<std::string> optMainwinTitle;
00122   OModelParam<bool> itsSaveVcx;
00123   OModelParam<bool> itsSaveSm;
00124 
00125   bool itsDoQuit;
00126 };
00127 
00128 
00129 // ######################################################################
00130 static const ModelOptionDef OPT_AsyncUi =
00131   { MODOPT_FLAG, "AsyncUi", &MOC_OUTPUT, OPTEXP_CORE,
00132     "Whether to run the UI asynchronously in a background thread. "
00133     "This will give lower latencies and better framerates on a multi-core "
00134     "system, but will also allow frames to be dropped in order to maintain "
00135     "real-time responsiveness. Use --noasync-ui when it is critical that "
00136     "all frames be processed through the ui queue even if it cannot be done "
00137     "in real time.",
00138     "async-ui", '\0', "", "true" };
00139 
00140 static const ModelOptionDef OPT_AsyncUiQueueSize =
00141   { MODOPT_ARG(uint), "AsyncUiQueueSize", &MOC_OUTPUT, OPTEXP_CORE,
00142     "How many frames to hold in the asynchronous UI queue before "
00143     "we start dropping old frames",
00144     "async-ui-qsize", '\0', "<uint>", "2" };
00145 
00146 static const ModelOptionDef OPT_FlushUiQueue =
00147   { MODOPT_FLAG, "FlushUiQueue", &MOC_OUTPUT, OPTEXP_CORE,
00148     "Whether to flush UI frames that are left in the queue "
00149     "when the main loop exits",
00150     "flush-ui-queue", '\0', "", "false" };
00151 
00152 static const ModelOptionDef OPT_Neovision2Gui =
00153   { MODOPT_FLAG, "Neovision2Gui", &MOC_OUTPUT, OPTEXP_CORE,
00154     "Whether to show/save the neovision2 GUI",
00155     "neovision2-gui", '\0', "", "true" };
00156 
00157 static const ModelOptionDef OPT_CompactDisplay =
00158   { MODOPT_FLAG, "EsvCompactDisplay", &MOC_OUTPUT, OPTEXP_CORE,
00159     "Whether to start the GUI in compact display mode",
00160     "compact-display", '\0', "", "true" };
00161 
00162 static const ModelOptionDef OPT_ExtendedDisplay =
00163   { MODOPT_ARG(byte), "EsvExtendedDisplay", &MOC_OUTPUT, OPTEXP_CORE,
00164     "Amount of extra info to display in the GUI:\n"
00165     "    level 0: just input + saliency map\n"
00166     "    level 1: add meters underneath input+salmap\n"
00167     "    level 2: add single row of small internal maps\n"
00168     "    level 3: add double row of medium-sized internal maps",
00169     "extended-display", '\0', "<int>", "2" };
00170 
00171 static const ModelOptionDef OPT_DispZoom =
00172   { MODOPT_ARG(size_t), "EsvDispZoom", &MOC_OUTPUT, OPTEXP_CORE,
00173     "Number of octaves to zoom in on the small maps",
00174     "disp-zoom", '\0', "size_t", "4" };
00175 
00176 static const ModelOptionDef OPT_InputReduce =
00177   { MODOPT_ARG(size_t), "EsvInputReduce", &MOC_OUTPUT, OPTEXP_CORE,
00178     "Number of octaves to reduce the input by, for display purposes only",
00179     "input-reduce", '\0', "size_t", "0" };
00180 
00181 static const ModelOptionDef OPT_MainwinTitle =
00182   { MODOPT_ARG_STRING, "MainwinTitle", &MOC_OUTPUT, OPTEXP_CORE,
00183     "Title to use for main output window",
00184     "mainwin-title", '\0', "<string>", "neovision2" };
00185 
00186 static const ModelOptionDef OPT_SaveVcx =
00187   { MODOPT_FLAG, "SaveVcx", &MOC_OUTPUT, OPTEXP_CORE,
00188     "Whether to save the VisualCortex (VCX) output",
00189     "save-vcx", '\0', "", "false" };
00190 
00191 static const ModelOptionDef OPT_SaveSm =
00192   { MODOPT_FLAG, "SaveSm", &MOC_OUTPUT, OPTEXP_CORE,
00193     "Whether to save the SaliencyMap (Sm) output",
00194     "save-sm", '\0', "", "false" };
00195 
00196 // ######################################################################
00197 EnvSimulationViewer::EnvSimulationViewer(OptionManager& mgr) :
00198   ModelComponent(mgr, "Embeddable Simulation Viewer", "EnvSimulationViewer"),
00199   itsInputDims(&OPT_InputFrameDims, this),
00200   optAsyncUi(&OPT_AsyncUi, this),
00201   optAsyncUiQueueSize(&OPT_AsyncUiQueueSize, this),
00202   optFlushUiQueue(&OPT_FlushUiQueue, this),
00203   itsNeovision2Gui(&OPT_Neovision2Gui, this),
00204   optCompactDisplay(&OPT_CompactDisplay, this, ALLOW_ONLINE_CHANGES),
00205   optExtendedDisplay(&OPT_ExtendedDisplay, this, ALLOW_ONLINE_CHANGES),
00206   optDispZoom(&OPT_DispZoom, this, ALLOW_ONLINE_CHANGES),
00207   optInputReduce(&OPT_InputReduce, this, ALLOW_ONLINE_CHANGES),
00208   optMainwinTitle(&OPT_MainwinTitle, this),
00209   itsSaveVcx(&OPT_SaveVcx, this),
00210   itsSaveSm(&OPT_SaveSm, this),
00211   itsDoQuit(false)
00212 { }
00213 
00214 EnvSimulationViewer::~EnvSimulationViewer()
00215 { }
00216 
00217 void EnvSimulationViewer::paramChanged(ModelParamBase* const param, const bool valueChanged,
00218                                        ParamClient::ChangeStatus* status)
00219 {
00220   if (param == &itsInputDims) {
00221     const size_t excess_size = size_t(0.5 * log2(itsInputDims.getVal().sz() / 1000000.0));
00222     if (excess_size > optInputReduce.getVal()) optInputReduce.setVal(excess_size);
00223   } else if (param == &optInputReduce) {
00224     const size_t val = optInputReduce.getVal();
00225     const Dims d = itsInputDims.getVal();
00226 
00227     if (val > 16) *status = ParamClient::CHANGE_REJECTED;
00228     else if (d.isNonEmpty() && val > 0 && ((d.w() / (1 << val)) < 32 || (d.h() / (1 << val)) < 32))
00229       *status = ParamClient::CHANGE_REJECTED;
00230   }
00231 }
00232 
00233 // ######################################################################
00234 struct Nv2UiData
00235 {
00236   Nv2UiData(const int map_zoom_) :
00237     accepted_training_label(),
00238     remote_command(),
00239     map_zoom(map_zoom_),
00240     targetLoc(-1,-1),
00241     ncpu(numCpus()),
00242     text_log_file("")
00243   { }
00244 
00245   FpsTimer::State time_state;
00246   std::string accepted_training_label;
00247   std::string remote_command;
00248   const int map_zoom;
00249   Point2D<int> targetLoc;
00250   const int ncpu;
00251   std::string text_log_file;
00252 };
00253 
00254 // ######################################################################
00255 class Nv2UiJob : public JobServer::Job
00256 {
00257 public:
00258   Nv2UiJob(OutputFrameSeries* ofs_,
00259            EnvSimulationViewer* esv_,
00260            EnvInferoTemporal* eit_,
00261            const Nv2UiData& uidata_,
00262            EnvSaliencyMap* sm_,
00263            EnvSegmenter* ese_,
00264            NeoBrain* nb_,
00265            Image<PixRGB<byte> > rgbin_,
00266            Image<byte> vcxmap_
00267            , Image<byte> Imap_
00268            , Image<byte> Cmap_
00269            , Image<byte> Omap_
00270 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00271            , Image<byte> Fmap_
00272            , Image<byte> Mmap_
00273 #endif
00274            ) :
00275     ofs(ofs_), esv(esv_), eit(eit_), uidata(uidata_), sm(sm_), ese(ese_), neoBrain(nb_), rgbin(rgbin_),
00276     vcxmap(vcxmap_), Imap(Imap_), Cmap(Cmap_), Omap(Omap_),
00277 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00278     Fmap(Fmap_), Mmap(Mmap_),
00279 #endif
00280     m_dispzoom(1 << esv->optDispZoom.getVal()), m_inputreduce(esv->optInputReduce.getVal())
00281   { }
00282 
00283   // ####################
00284   unsigned int getHalfZoom() const
00285   {
00286     const int div = (esv->optExtendedDisplay.getVal() >= 4 && esv->optExtendedDisplay.getVal() < 10) ? 2 : 4;
00287     return std::max(size_t(1), m_dispzoom/div);
00288   }
00289 
00290   // ####################
00291   Layout<PixRGB<byte> > makeInputMarkup(const Rectangle& foa, const Image<byte>& foamask,
00292                                         const EnvSaliencyMap::State& smstate, const uint32_t patch_id) const
00293   {
00294     Image<PixRGB<byte> > markup = rgbin;
00295 
00296     if (foa.isValid()) drawRectSquareCorners(markup, foa, PixRGB<byte>(255, 255, 0), 3 << m_inputreduce);
00297 
00298     if (uidata.targetLoc.isValid())
00299       drawCircle(markup, uidata.targetLoc, 3, PixRGB<byte>(60, 220, 255), 3 << m_inputreduce);
00300 
00301     // draw the first most salient loc:
00302     drawRectSquareCorners(markup,
00303                           Rectangle(smstate.fullres_maxpos - uidata.map_zoom/2, Dims(uidata.map_zoom, uidata.map_zoom)),
00304                           PixRGB<byte>(255, 0, 0), 3 << m_inputreduce);
00305 
00306     // draw the next n most salient loc:
00307     for (uint i = 1; i < smstate.nMostSalientLoc.size(); ++i)
00308       {
00309         const EnvSaliencyMap::LocInfo locInfo = smstate.nMostSalientLoc[i];
00310         drawRectSquareCorners(markup, Rectangle(locInfo.fullres_maxpos - uidata.map_zoom/2,
00311                                                 Dims(uidata.map_zoom, uidata.map_zoom)),
00312                               PixRGB<byte>(150, 0, 0), 3 << m_inputreduce);
00313       }
00314 
00315     for (size_t i = 0; i < m_inputreduce; ++i) markup = decXY(markup);
00316 
00317     if (foamask.initialized()) drawContour2D(rescaleNI(foamask, markup.getDims()), markup, PixRGB<byte>(0,255,0), 2);
00318 
00319     const std::string lines[2] = {
00320       sformat("peak %3d in %3dx%3d foa @ (%3d,%3d)", int(smstate.maxval),
00321               foa.isValid() ? foa.width() : -1, foa.isValid() ? foa.height() : -1,
00322               smstate.fullres_maxpos.i, smstate.fullres_maxpos.j),
00323         sformat("%s #%06u [%5.2ffps, %5.1f%%CPU]", convertToString(uidata.time_state.elapsed_time).c_str(),
00324                 (unsigned int) patch_id, uidata.time_state.recent_fps, uidata.time_state.recent_cpu_usage*100.0)
00325     };
00326 
00327     const Image<PixRGB<byte> > textarea =
00328       makeMultilineTextBox(markup.getWidth(), &lines[0], 2,
00329                            PixRGB<byte>(255, 255, 0), PixRGB<byte>(0,0,0), PREFERRED_TEXT_LENGTH);
00330 
00331     return vcat(markup, textarea);
00332   }
00333 
00334   // ####################
00335   Layout<PixRGB<byte> >
00336   makeSalmapMarkup(const EnvSaliencyMap::State& smstate) const
00337   {
00338     Image<PixRGB<byte> > zoomedsm = zoomXY(smstate.salmap, m_dispzoom, m_dispzoom);
00339 
00340     // draw the first most salient loc:
00341     drawRectSquareCorners(zoomedsm, Rectangle(smstate.lowres_maxpos * m_dispzoom, Dims(m_dispzoom, m_dispzoom)),
00342                           PixRGB<byte>(255, 0, 0), 3);
00343 
00344     // draw the next n most salient locs:
00345     for (uint i = 1; i < smstate.nMostSalientLoc.size(); ++i)
00346       {
00347         const EnvSaliencyMap::LocInfo locInfo = smstate.nMostSalientLoc[i];
00348         drawRectSquareCorners(zoomedsm, Rectangle(locInfo.lowres_maxpos * m_dispzoom, Dims(m_dispzoom, m_dispzoom)),
00349                               PixRGB<byte>(150, 0, 0), 3);
00350       }
00351 
00352     const std::string valstring = sformat("%d", int(smstate.maxval));
00353 
00354     const SimpleFont font = SimpleFont::fixedMaxWidth(zoomedsm.getWidth() / 30);
00355 
00356     Point2D<int> textpos = smstate.lowres_maxpos * m_dispzoom;
00357     textpos.j -= font.h() + 2; if (textpos.j < 0) textpos.j += m_dispzoom + 2;
00358 
00359     writeText(zoomedsm, textpos, valstring.c_str(),
00360               PixRGB<byte>(255, 0, 0), PixRGB<byte>(0, 0, 0), font, true);
00361 
00362 #ifdef VSS_DEMO
00363     Image<PixRGB<byte> > histo =
00364       neoBrain->getSaliencyHisto(Dims(zoomedsm.getWidth(), 62), PixRGB<byte>(0,0,0), PixRGB<byte>(180,180,180));
00365     return vcat(zoomedsm, histo);
00366 #else
00367     return zoomedsm;
00368 #endif
00369   }
00370 
00371   // ####################
00372   Layout<PixRGB<byte> > makeCmapsMarkup() const
00373   {
00374     unsigned int halfzoom = this->getHalfZoom();
00375     if (esv->optExtendedDisplay.getVal() == 10) halfzoom /= 2;
00376 
00377     Image<PixRGB<byte> > cmaps[] = {
00378       zoomXY(Imap, halfzoom, halfzoom),
00379       zoomXY(Cmap, halfzoom, halfzoom),
00380       zoomXY(Omap, halfzoom, halfzoom),
00381 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00382       zoomXY(Fmap, halfzoom, halfzoom),
00383       zoomXY(Mmap, halfzoom, halfzoom),
00384 #endif
00385       zoomXY(vcxmap, halfzoom, halfzoom)
00386     };
00387 
00388     const char* labels[] = {
00389       "I", "C", "O",
00390 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00391       "F", "M",
00392 #endif
00393       "VC"
00394     };
00395 
00396     for (size_t i = 0; i < sizeof(labels) / sizeof(labels[0]); ++i) {
00397       const SimpleFont font = SimpleFont::fixedMaxWidth(cmaps[i].getWidth() / 20);
00398       writeText(cmaps[i], Point2D<int>(1,1), labels[i], PixRGB<byte>(0), PixRGB<byte>(255), font);
00399       drawLine(cmaps[i], Point2D<int>(0,0), Point2D<int>(cmaps[i].getWidth()-1,0), PixRGB<byte>(255), 1);
00400       drawLine(cmaps[i], Point2D<int>(0,0), Point2D<int>(0,cmaps[i].getHeight()-1), PixRGB<byte>(255), 1);
00401     }
00402 
00403     const size_t nrows = esv->optExtendedDisplay.getVal() >= 4 ? 2 : 1;
00404 
00405     return arrcat(&cmaps[0], sizeof(cmaps) / sizeof(cmaps[0]), (sizeof(cmaps) / sizeof(cmaps[0]) + (nrows-1)) / nrows);
00406   }
00407 
00408   // ####################
00409   Image<PixRGB<byte> > makeInhibitionMarkup() const
00410   {
00411     Image<byte> inh = sm->getInhibmap();
00412     if (!inh.initialized()) inh = Image<byte>(vcxmap.getDims(), ZEROS);
00413 
00414     Image<byte> inr = Image<byte>(sm->getInertiaMap());
00415     if (!inr.initialized()) inr = Image<byte>(vcxmap.getDims(), ZEROS);
00416 
00417     Image<PixRGB<byte> > rgb(vcxmap.getDims(), NO_INIT);
00418     Image<PixRGB<byte> >::iterator aptr = rgb.beginw();
00419     Image<PixRGB<byte> >::iterator stop = rgb.endw();
00420 
00421     Image<byte>::const_iterator rptr = inh.begin();
00422     Image<byte>::const_iterator gptr = inr.begin();
00423 
00424     while (aptr != stop) *aptr++ = PixRGB<byte>(*rptr++, *gptr++, 0);
00425 
00426     return zoomXY(rgb, esv->optExtendedDisplay.getVal() == 10 ? getHalfZoom() / 2 : getHalfZoom());
00427   }
00428 
00429   // ####################
00430   Image<PixRGB<byte> > makeMeters(const size_t nx, const Dims& meterdims) const
00431   {
00432     const double maxcpu = uidata.ncpu <= 0 ? 100.0 : uidata.ncpu * 100.0;
00433 
00434     const double nothresh = std::numeric_limits<double>::max();
00435 
00436     const MeterInfo infos[] = {
00437       { "dvcx/dt", sm->getVcxFlicker(), 1.0, nothresh, PixRGB<byte>(0, 255, 0) },
00438       { "dfactor", sm->getDynamicFactor(), 1.0, nothresh, PixRGB<byte>(128, 0, 255) },
00439 #ifdef VSS_DEMO
00440       { "boringness", neoBrain->getBoringness(), 128.0, nothresh, PixRGB<byte>(192, 255, 0) },
00441       { "excitement", neoBrain->getExcitementLevel(), 256.0, nothresh, PixRGB<byte>(255, 0, 32) },
00442       { "sleepiness", neoBrain->getSleepLevel(), 1000.0, nothresh, PixRGB<byte>(255, 0, 32) },
00443 #endif
00444       { "confidence", eit->getMaxConfidence(), 1.0, eit->getConfidenceThresh(), PixRGB<byte>(0, 255, 128) },
00445       { "cpu%", uidata.time_state.recent_cpu_usage*100.0, maxcpu, nothresh, PixRGB<byte>(255, 165, 0) },
00446       { "fps", uidata.time_state.recent_fps, 60.0, nothresh, PixRGB<byte>(0, 128, 255) }
00447     };
00448 
00449     return drawMeters(&infos[0], sizeof(infos) / sizeof(infos[0]), nx, meterdims);
00450   }
00451 
00452   // ####################
00453   virtual void run()
00454   {
00455     Point2D<int> scaled_maxpos(-1,-1);
00456 
00457     const nub::soft_ref<ImageDisplayStream> ids = ofs->findFrameDestType<ImageDisplayStream>();
00458 
00459     const rutz::shared_ptr<XWinManaged> uiwin = ids.is_valid() ?
00460       ids->getWindow(esv->optCompactDisplay.getVal() ? esv->optMainwinTitle.getVal() : "input")
00461       : rutz::shared_ptr<XWinManaged>();
00462 
00463     Point2D<int> forceTrackLocation(-1,-1);
00464 
00465     if (uiwin.is_valid()) {
00466       XButtonEvent ev;
00467       if (uiwin->getLastButtonEvent(&ev) && ev.button == 1) forceTrackLocation = Point2D<int>(ev.x, ev.y);
00468      }
00469 
00470     if (forceTrackLocation.isValid()) {
00471       const Point2D<int> candidate = forceTrackLocation * (1 << m_inputreduce) + (1 << m_inputreduce) / 2;
00472 
00473       if (rgbin.coordsOk(candidate)) {
00474         scaled_maxpos = candidate;
00475         neoBrain->setTarget(scaled_maxpos, rgbin, -1, false, true);
00476         //neoBrain->setKeepTracking(true);
00477       }
00478     } else if (uidata.targetLoc.isValid()) {
00479       scaled_maxpos = uidata.targetLoc;
00480       ASSERT(rgbin.coordsOk(scaled_maxpos));
00481     }
00482 
00483     const EnvSaliencyMap::State smstate = sm->getSalmap(vcxmap, scaled_maxpos);
00484 
00485 #ifdef VSS_DEMO
00486     neoBrain->updateBoringness(smstate.salmap, smstate.maxval);
00487     neoBrain->updateExcitement(sm->getVcxFlicker());
00488 #endif
00489 
00490     Image<byte> foamask;
00491     Image<PixRGB<byte> > segmentdisp;
00492 
00493     // Send the first most salient locations to be identified
00494     const Rectangle foa = ese->getFoa(rgbin, smstate.fullres_maxpos, &foamask, &segmentdisp);
00495 
00496     //if (foa.isValid()) {
00497     //  const Point2D<int> objCenter = Point2D<int>(foa.topLeft().i + foa.width()/2, foa.topLeft().j + foa.height()/2);
00498     //  neoBrain->setTarget(objCenter, rgbin, smstate.maxval);
00499     //} else if (!uidata.targetLoc.isValid())
00500     //  neoBrain->setTarget(smstate.fullres_maxpos, rgbin, smstate.maxval);
00501     if (!uidata.targetLoc.isValid())
00502             neoBrain->setTarget(smstate.fullres_maxpos, rgbin, smstate.maxval);
00503 
00504     const uint32_t patch_id = uidata.time_state.frame_number;
00505 
00506     eit->sendPatch(patch_id, rgbin, foa,
00507                    uidata.time_state.elapsed_time,
00508                    uidata.accepted_training_label.length() > 0,
00509                    uidata.accepted_training_label,
00510                    uidata.remote_command,
00511                    smstate.fullres_maxpos);
00512 
00513     // Send the next N most salient locations to be identified:
00514     for (uint i = 1; i < smstate.nMostSalientLoc.size(); ++i) {
00515       Image<byte> nextFoamask;
00516       Image<PixRGB<byte> > nextSegmentdisp;
00517 
00518       const EnvSaliencyMap::LocInfo locInfo = smstate.nMostSalientLoc[i];
00519       const Rectangle nextFoa = ese->getFoa(rgbin, locInfo.fullres_maxpos, &nextFoamask, &nextSegmentdisp);
00520 
00521       eit->sendPatch(patch_id, rgbin, nextFoa,
00522                      uidata.time_state.elapsed_time,
00523                      uidata.accepted_training_label.length() > 0,
00524                      uidata.accepted_training_label,
00525                      uidata.remote_command,
00526                      locInfo.fullres_maxpos);
00527     }
00528 
00529     // log various bits of info (these calls will do nothing if the log filename is empty):
00530     textLog(uidata.text_log_file, "FOAbox", convertToString(foa));
00531 
00532     const FrameState os = ofs->updateNext();
00533 
00534     // save maps if requested:
00535     if (esv->itsSaveVcx.getVal()) ofs->writeGray(vcxmap, "VCO", FrameInfo("VisualCortex output map", SRC_POS));
00536 
00537     if (esv->itsSaveSm.getVal()) ofs->writeGray(smstate.salmap, "SM", FrameInfo("SaliencyMap output map", SRC_POS));
00538 
00539     // ##### compact displays
00540     if (esv->itsNeovision2Gui.getVal() && esv->optCompactDisplay.getVal()) {
00541       ofs->closeStream("input");
00542       ofs->closeStream("salmap");
00543       ofs->closeStream("cmaps");
00544       ofs->closeStream("inhibition,inertia");
00545       ofs->closeStream("segmentation");
00546       ofs->closeStream("meters");
00547 
00548       Layout<PixRGB<byte> > img;
00549 
00550       // ##### mode 10 displays (for display on HD monitor)
00551       if (esv->optExtendedDisplay.getVal() == 10) {
00552         // let's start with an HD display of the input + markups:
00553         Image<PixRGB<byte> > markup = rgbin;
00554         if (foa.isValid()) drawRectSquareCorners(markup, foa, PixRGB<byte>(255, 255, 0), 3 << m_inputreduce);
00555 
00556         if (uidata.targetLoc.isValid())
00557           drawCircle(markup, uidata.targetLoc, 3, PixRGB<byte>(60, 220, 255), 3 << m_inputreduce);
00558 
00559         // draw the first most salient loc
00560         drawRectSquareCorners(markup,
00561                               Rectangle(smstate.fullres_maxpos - uidata.map_zoom/2,
00562                                         Dims(uidata.map_zoom, uidata.map_zoom)),
00563                               PixRGB<byte>(255, 0, 0), 3 << m_inputreduce);
00564 
00565         // draw the next n most salient locs:
00566         for (uint i = 1; i < smstate.nMostSalientLoc.size(); ++i) {
00567           const EnvSaliencyMap::LocInfo locInfo = smstate.nMostSalientLoc[i];
00568           drawRectSquareCorners(markup,
00569                                 Rectangle(locInfo.fullres_maxpos - uidata.map_zoom/2,
00570                                  Dims(uidata.map_zoom, uidata.map_zoom)), PixRGB<byte>(150, 0, 0), 3 << m_inputreduce);
00571         }
00572 
00573         for (size_t i = 0; i < m_inputreduce; ++i) markup = decXY(markup);
00574 
00575         if (foamask.initialized()) drawContour2D(rescaleNI(foamask,markup.getDims()), markup, PixRGB<byte>(0,255,0), 2);
00576 
00577         // that's it for this window, let's send it out to display:
00578         ofs->writeRGB(markup, esv->optMainwinTitle.getVal(), FrameInfo("copy of input", SRC_POS));
00579 
00580         // the salmap:
00581         const unsigned int halfzoom = 8;
00582         Image<PixRGB<byte> > zoomedsm = zoomXY(smstate.salmap, halfzoom, halfzoom);
00583 
00584         drawRectSquareCorners(zoomedsm, Rectangle(smstate.lowres_maxpos * halfzoom, Dims(halfzoom, halfzoom)),
00585                               PixRGB<byte>(255, 0, 0), 3);
00586 
00587         const std::string valstring = sformat("%d", int(smstate.maxval));
00588         const SimpleFont font = SimpleFont::fixedMaxWidth(zoomedsm.getWidth() / 30);
00589         Point2D<int> textpos = smstate.lowres_maxpos * halfzoom;
00590         textpos.j -= font.h() + 2; if (textpos.j < 0) textpos.j += halfzoom + 2;
00591         writeText(zoomedsm, textpos, valstring.c_str(), PixRGB<byte>(255, 0, 0), PixRGB<byte>(0, 0, 0), font, true);
00592 
00593         Image<PixRGB<byte> > inh = this->makeInhibitionMarkup();
00594         drawLine(inh, Point2D<int>(0,0), Point2D<int>(inh.getWidth()-1,0), PixRGB<byte>(255, 255, 255), 1);
00595         drawLine(inh, Point2D<int>(0,0), Point2D<int>(0,inh.getHeight()-1), PixRGB<byte>(255, 255, 255), 1);
00596 
00597         if (!segmentdisp.initialized())
00598           segmentdisp = Image<PixRGB<byte> >(inh.getDims(), ZEROS);
00599         else {
00600           segmentdisp = rescaleNI(segmentdisp, inh.getDims());
00601           drawContour2D(rescaleNI(foamask, inh.getDims()), segmentdisp, PixRGB<byte>(0,255,0), 2);
00602         }
00603         drawLine(segmentdisp, Point2D<int>(0,0), Point2D<int>(inh.getWidth()-1,0),
00604                  PixRGB<byte>(255, 255, 255), 1);
00605         drawLine(segmentdisp, Point2D<int>(0,0), Point2D<int>(0,inh.getHeight()-1),
00606                  PixRGB<byte>(255, 255, 255), 1);
00607         Layout<PixRGB<byte> > inl = vcat(inh, segmentdisp);
00608 
00609         img = vcat(zoomedsm, this->makeMeters(2, Dims(zoomedsm.getDims().w() / 2, 13)));
00610 
00611         // now some info:
00612         const std::string lines[1] =
00613           {
00614             sformat("peak %3d in %3dx%3d foa @ (%4d,%4d) %04dx%04d %s #%06u [%3.2ffps, %4.1f%%CPU]",
00615                     int(smstate.maxval),
00616                     foa.isValid() ? foa.width() : -1,
00617                     foa.isValid() ? foa.height() : -1,
00618                     smstate.fullres_maxpos.i,
00619                     smstate.fullres_maxpos.j,
00620                     rgbin.getWidth(), rgbin.getHeight(),
00621                     convertToString(uidata.time_state.elapsed_time).c_str(),
00622                     (unsigned int) patch_id,
00623                     uidata.time_state.recent_fps,
00624                     uidata.time_state.recent_cpu_usage*100.0)
00625           };
00626 
00627         const Image<PixRGB<byte> > textarea =
00628           makeMultilineTextBox(img.getWidth(), &lines[0], 1, PixRGB<byte>(255, 255, 0), PixRGB<byte>(0,0,0),
00629                                PREFERRED_TEXT_LENGTH, 10);
00630         img = vcat(img, textarea);
00631 
00632         // now the cmaps and friends:
00633         const Layout<PixRGB<byte> > cmaps = this->makeCmapsMarkup();
00634         inl = hcat(cmaps, inl);
00635         img = vcat(img, inl);
00636 
00637         ofs->writeRgbLayout(img, "control-panel", FrameInfo("copy of input", SRC_POS));
00638         ////////////////////////////////
00639       } else {
00640         img = hcat(this->makeInputMarkup(foa, foamask, smstate, patch_id), this->makeSalmapMarkup(smstate));
00641 
00642         if (esv->optExtendedDisplay.getVal() > 0) {
00643           // ##### mode 2+ displays
00644           if (esv->optExtendedDisplay.getVal() >= 2)
00645             {
00646               const Layout<PixRGB<byte> > cmaps = this->makeCmapsMarkup();
00647               Image<PixRGB<byte> > inh = this->makeInhibitionMarkup();
00648               drawLine(inh, Point2D<int>(0,0), Point2D<int>(inh.getWidth()-1,0), PixRGB<byte>(255, 255, 255), 1);
00649               drawLine(inh, Point2D<int>(0,0), Point2D<int>(0,inh.getHeight()-1), PixRGB<byte>(255, 255, 255), 1);
00650 
00651               const SimpleFont font = SimpleFont::fixedMaxWidth(inh.getWidth() / 20);
00652               writeText(inh, Point2D<int>(1,1), "INH", PixRGB<byte>(0), PixRGB<byte>(255), font);
00653 
00654               if (!segmentdisp.initialized())
00655                 segmentdisp = Image<PixRGB<byte> >(inh.getDims(), ZEROS);
00656               else {
00657                 segmentdisp = rescaleNI(segmentdisp, inh.getDims());
00658 
00659                 drawContour2D(rescaleNI(foamask, inh.getDims()), segmentdisp, PixRGB<byte>(0,255,0), 2);
00660                 writeText(segmentdisp, Point2D<int>(1,1), "SEG", PixRGB<byte>(0), PixRGB<byte>(255), font);
00661               }
00662               drawLine(segmentdisp, Point2D<int>(0,0), Point2D<int>(inh.getWidth()-1,0),
00663                        PixRGB<byte>(255, 255, 255), 1);
00664               drawLine(segmentdisp, Point2D<int>(0,0), Point2D<int>(0,inh.getHeight()-1),
00665                        PixRGB<byte>(255, 255, 255), 1);
00666 
00667               if (esv->optExtendedDisplay.getVal() >= 4)
00668                 img = vcat(img, hcat(cmaps, vcat(inh,segmentdisp)));
00669               else
00670                 img = vcat(img, hcat(cmaps, hcat(inh,segmentdisp)));
00671             }
00672 
00673           img = vcat(img, this->makeMeters(2, Dims(img.getDims().w() / 2, 13)));
00674 
00675           // ##### mode 3+ displays
00676           if (esv->optExtendedDisplay.getVal() >= 3)
00677             {
00678               NeoBrain::Stats stats = neoBrain->getStats();
00679 
00680               const std::string lines[5] = {
00681                 sformat(" track error #frames %04lu (%04lu) | target track #frames %04lu (%04lu)",
00682                         stats.bigerrframes, stats.bigerrframes_thresh, stats.targetframes, stats.targetframes_thresh),
00683                 sformat("  non-motion #frames %04lu (%04lu) |   stop track #frames %04lu (%04lu)",
00684                         stats.nomoveframes, stats.nomoveframes_thresh, stats.stopframes, stats.stopframes_thresh),
00685                 "",
00686                 sformat("    track err = %.3f = %.3f+%.3f (%.3f, %.3f)",
00687                         stats.last_err, stats.last_xerr, stats.last_yerr, stats.err_tol, stats.dist_tol),
00688                 sformat("    leftEyeTilt = %.3f leftEyePan = %.3f headPan = %.3f",
00689                         stats.leftEyeTiltPos, stats.leftEyePanPos, stats.headPanPos)
00690               };
00691 
00692               const Image<PixRGB<byte> > textarea =
00693                 makeMultilineTextBox(img.getDims().w(), &lines[0], 5,
00694                                      PixRGB<byte>(128, 180, 255), PixRGB<byte>(0,0,0), 150);
00695               img = vcat(img, textarea);
00696             }
00697         }
00698         ofs->writeRgbLayout(img, esv->optMainwinTitle.getVal(), FrameInfo("copy of input", SRC_POS));
00699       }
00700     } else if (esv->itsNeovision2Gui.getVal()) {
00701       // ##### multiwindow displays
00702       ofs->closeStream(esv->optMainwinTitle.getVal());
00703 
00704       ofs->writeRgbLayout(this->makeInputMarkup(foa, foamask, smstate, patch_id),
00705                           "input", FrameInfo("copy of input", SRC_POS));
00706 
00707       ofs->writeRgbLayout(this->makeSalmapMarkup(smstate), "salmap", FrameInfo("saliency map", SRC_POS));
00708 
00709       if (esv->optExtendedDisplay.getVal()) {
00710         ofs->writeRgbLayout(this->makeCmapsMarkup(), "cmaps", FrameInfo("channel conspicuity maps", SRC_POS));
00711 
00712         ofs->writeRGB(this->makeInhibitionMarkup(), "inhibition,inertia",
00713                       FrameInfo("inertia and inhibition of return", SRC_POS));
00714 
00715         ofs->writeRGB(this->makeMeters(1, Dims(400, 13)), "meters");
00716       } else {
00717         ofs->closeStream("cmaps");
00718         ofs->closeStream("inhibition,inertia");
00719         ofs->closeStream("meters");
00720       }
00721 
00722       if (segmentdisp.initialized()) {
00723         segmentdisp = zoomXY(segmentdisp, m_dispzoom);
00724         drawContour2D(zoomXY(foamask, m_dispzoom), segmentdisp, PixRGB<byte>(0,255,0), 2);
00725         ofs->writeRGB(segmentdisp, "segmentation");
00726       } else ofs->closeStream("segmentation");
00727     }
00728 
00729     std::vector<Nv2LabelReader::LabeledImage> images = eit->getLabeledImages(PREFERRED_TEXT_LENGTH);
00730 
00731     for (size_t i = 0; i < images.size(); ++i)
00732       {
00733         ofs->writeRGB(images[i].img, images[i].ident, FrameInfo("object-labeled image", SRC_POS));
00734 #ifdef VSS_DEMO
00735         neoBrain->sayObjectLabel(images[i].label, /*confidence = */ 0, true);
00736 #endif
00737       }
00738 
00739     if (os == FRAME_FINAL) esv->itsDoQuit = true;
00740   }
00741 
00742   // ####################
00743   virtual const char* jobType() const { return "Nv2UiJob"; }
00744 
00745 private:
00746   OutputFrameSeries* const ofs;
00747   EnvSimulationViewer* const esv;
00748   EnvInferoTemporal* const eit;
00749   const Nv2UiData uidata;
00750   EnvSaliencyMap* const sm;
00751   EnvSegmenter* const ese;
00752   NeoBrain* const neoBrain;
00753   Image<PixRGB<byte> > rgbin;
00754   const Image<byte> vcxmap;
00755   const Image<byte> Imap;
00756   const Image<byte> Cmap;
00757   const Image<byte> Omap;
00758 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00759   const Image<byte> Fmap;
00760   const Image<byte> Mmap;
00761 #endif
00762   const size_t m_dispzoom;
00763   const size_t m_inputreduce;
00764 };
00765 
00766 // ######################################################################
00767 static const ModelOptionDef OPT_WithObjrecMode =
00768   { MODOPT_FLAG, "WithObjrecMode", &MOC_OUTPUT, OPTEXP_CORE,
00769     "Whether to include an 'objrec' mode which toggles parameters "
00770     "to values suitable for object recognition training.",
00771     "with-objrec-mode", '\0', "", "false" };
00772 
00773 static const ModelOptionDef OPT_ALIASheadDemo =
00774   { MODOPT_ALIAS, "ALIASheadDemo", &MOC_ALIAS, OPTEXP_CORE,
00775     "Set parameters for the head demo",
00776     "head-demo", '\0', "",
00777     "--in=V4L2 "
00778     "--framegrabber-dims=320x240 "
00779     "--framegrabber-mode=RGB24 "
00780     "--framegrabber-chan=0 "
00781     "--framegrabber-dev=/dev/video1 "
00782     "--evc-type=I:0.75C:0.75O:0.75F:0.75M:1.0 "
00783     "--mainwin-title=Sal "
00784     "--neobrain-speak-saliency "
00785     "--neobrain-speak-objects "
00786     "--with-objrec-mode "
00787   };
00788 
00789 static const ModelOptionDef OPT_ALIASheadDemo21 =
00790   { MODOPT_ALIAS, "ALIASheadDemo21", &MOC_ALIAS, OPTEXP_CORE,
00791     "Set parameters for the head demo on ilab21",
00792     "head-demo21", '\0', "",
00793     "--in=v4l2 "
00794     "--framegrabber-dims=720x480 "
00795     "--framegrabber-mode=HM12 "
00796     "--framegrabber-chan=2 "
00797     "--framegrabber-dev=/dev/video32 "
00798     "--evc-type=I:0.75C:0.75O:0.75F:0.75M:1.0 "
00799     "--mainwin-title=Sal "
00800     "--with-objrec-mode "
00801     "--neobrain-speak-saliency "
00802     "--evc-multithreaded "
00803   };
00804 
00805 static const ModelOptionDef OPT_ALIASheadDemo3 =
00806   { MODOPT_ALIAS, "ALIASheadDemo3", &MOC_ALIAS, OPTEXP_CORE,
00807     "Set parameters for the head demo on ilab3",
00808     "head-demo3", '\0', "",
00809     "--in=v4l2 "
00810     "--evc-type=I:0.75C:0.75O:0.75F:0.75M:1.0 "
00811     "--mainwin-title=Sal "
00812     "--with-objrec-mode "
00813     "--neobrain-speak-saliency "
00814     "--evc-multithreaded "
00815   };
00816 
00817 static const ModelOptionDef OPT_ALIASflea2Demo =
00818   { MODOPT_ALIAS, "ALIASflea2Demo", &MOC_ALIAS, OPTEXP_CORE,
00819     "Set parameters for the Flea2 demo",
00820     "flea2-demo", '\0', "",
00821     "--in=dc1394v2 "
00822     "--framegrabber-dims=1024x768 "
00823     "--framegrabber-mode=RGB24 "
00824     "--framegrabber-fps=15 "
00825     "--evc-multithreaded "
00826     "--noneobrain-speech "
00827     "--disp-zoom=4 "
00828   };
00829 
00830 static const ModelOptionDef OPT_ALIASHDDemo =
00831   { MODOPT_ALIAS, "ALIASHDDemo", &MOC_ALIAS, OPTEXP_CORE,
00832     "Set parameters for the hd camera on ilab24",
00833     "hd-demo", '\0', "",
00834     "--in=XC "
00835     "--framegrabber-dims=1024x768 "
00836     "--patch-reader=192.168.0.229:9930 "
00837     "--disp-zoom=3 "
00838     "--evc-multithreaded "
00839   };
00840 
00841 // ######################################################################
00842 int submain(int argc, const char** argv)
00843 {
00844   volatile int signum = 0;
00845   signal(SIGPIPE, SIG_IGN);
00846   catchsignals(&signum);
00847 
00848   // Instantiate our various ModelComponents:
00849 
00850   ModelManager manager("Nv2");
00851 
00852   OModelParam<bool> optWithObjrecMode(&OPT_WithObjrecMode, &manager);
00853   OModelParam<std::string> optTextLogFile(&OPT_TextLogFile, &manager);
00854 
00855   nub::ref<EnvSimulationViewer> esv(new EnvSimulationViewer(manager));
00856   manager.addSubComponent(esv);
00857 
00858   nub::ref<InputFrameSeries> ifs(new InputFrameSeries(manager));
00859   manager.addSubComponent(ifs);
00860 
00861   nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00862   manager.addSubComponent(ofs);
00863 
00864   nub::ref<EnvVisualCortex> evc(new EnvVisualCortex(manager));
00865   manager.addSubComponent(evc);
00866 
00867   nub::ref<EnvSaliencyMap> esm(new EnvSaliencyMap(manager));
00868   manager.addSubComponent(esm);
00869 
00870   nub::ref<EnvSegmenterConfigurator> esec(new EnvSegmenterConfigurator(manager));
00871   manager.addSubComponent(esec);
00872 
00873   nub::ref<EnvInferoTemporal> eit(new EnvInferoTemporal(manager));
00874   manager.addSubComponent(eit);
00875 
00876   nub::ref<NeoBrain> neoBrain(new NeoBrain(manager));
00877   manager.addSubComponent(neoBrain);
00878 
00879   manager.requestOptionAlias(&OPT_ALIASheadDemo);
00880   manager.requestOptionAlias(&OPT_ALIASheadDemo3);
00881   manager.requestOptionAlias(&OPT_ALIASheadDemo21);
00882   manager.requestOptionAlias(&OPT_ALIASflea2Demo);
00883   manager.requestOptionAlias(&OPT_ALIASHDDemo);
00884 
00885   manager.exportOptions(MC_RECURSE);
00886 
00887 #if defined(HAVE_IEEE1394)
00888   // input comes from firewire camera 640x480/rgb/15fps by default
00889   manager.setOptionValString(&OPT_InputFrameSource, "ieee1394");
00890   manager.setOptionValString(&OPT_FrameGrabberMode, "RGB24");
00891   manager.setOptionValString(&OPT_FrameGrabberDims, "640x480");
00892   manager.setOptionValString(&OPT_FrameGrabberFPS, "15");
00893 #elif defined(HAVE_QUICKTIME_QUICKTIME_H)
00894   manager.setOptionValString(&OPT_InputFrameSource, "qtgrab");
00895   manager.setOptionValString(&OPT_FrameGrabberDims, "640x480");
00896 #endif
00897 
00898   // output goes to the screen by default
00899   manager.setOptionValString(&OPT_OutputFrameSink, "display");
00900 
00901   // change some default values
00902   manager.setOptionValString(&OPT_EvcColorSmoothing, "true");
00903   manager.setOptionValString(&OPT_EsmInertiaHalfLife, "60");
00904   manager.setOptionValString(&OPT_EsmIorStrength, "8.0");
00905 
00906   if (manager.parseCommandLine(argc, argv, "<ip1:port1,ip2:port2,...>", 0, 1) == false) return(1);
00907 
00908   eit->initReaders(manager.numExtraArgs() > 0 ? manager.getExtraArg(0) : "");
00909 
00910   manager.start();
00911 
00912   neoBrain->init(ifs->peekDims());
00913 
00914   Nv2UiData uidata(1 << evc->getMapLevel());
00915   uidata.text_log_file = optTextLogFile.getVal();
00916 
00917   PrefsWindow pwin("control panel", SimpleFont::FIXED(8));
00918   pwin.setValueNumChars(16);
00919 
00920   pwin.addPrefsForComponent(esv.get());
00921   pwin.addPrefsForComponent(esm.get());
00922   pwin.addPrefsForComponent(esec->getSeg().get());
00923   pwin.addPrefsForComponent(eit.get());
00924   pwin.addPrefsForComponent(neoBrain.get(), true);
00925   pwin.addPrefsForComponent(evc.get());
00926 
00927   PrefItemBln prefPause(&pwin, "pause", false);
00928   PrefItemStr prefRemoteCommand(&pwin, "remote command", uidata.remote_command);
00929   PrefItemBln prefInTrainingMode(&pwin, "in training mode", false);
00930   PrefItemBln prefInObjRecMode(optWithObjrecMode.getVal() ? &pwin : 0, "in ObjRec mode", false);
00931   PrefItemBln prefDoGrabFrame(&pwin, "grab frame", true);
00932   PrefItemBln prefCommitTrainingImage(&pwin, "commit training image", false);
00933   PrefItemBln prefCommitTrainingImageConfirm(&pwin, "confirm commit ??", false);
00934   PrefItemStr prefTrainingLabel(&pwin, "training label", "");
00935   PrefItemByt prefFontSize(&pwin, "font size", 6);
00936 
00937   PrefsWindow inputprefs;
00938   inputprefs.addPrefsForComponent(ifs->getFrameSource().get());
00939   pwin.setFont(SimpleFont::fixedMaxWidth(prefFontSize.get()));
00940   inputprefs.setFont(SimpleFont::fixedMaxWidth(prefFontSize.get()));
00941 
00942   PauseWaiter p;
00943 
00944   int retval = 0;
00945 
00946   rutz::shared_ptr<JobServer> uiq;
00947   if (esv->optAsyncUi.getVal()) {
00948     // set up a background job server with one worker thread to
00949     // handle the ui jobs:
00950     rutz::shared_ptr<WorkThreadServer> tsrv(new WorkThreadServer("neovision2-ui", 1));
00951 
00952     // keep max latency low, and if we get bogged down, then drop
00953     // old frames rather than new ones
00954     tsrv->setMaxQueueSize(esv->optAsyncUiQueueSize.getVal());
00955     tsrv->setDropPolicy(WorkThreadServer::DROP_OLDEST);
00956     tsrv->setFlushBeforeStopping(esv->optFlushUiQueue.getVal());
00957     uiq = tsrv;
00958   } else {
00959     // set up a synchronous job server that will run all ui jobs in
00960     // the foreground
00961     uiq.reset(new SyncJobServer);
00962   }
00963 
00964   ASSERT(uiq.get() != 0);
00965 
00966   ifs->startStream();
00967 
00968   // const GenericFrameSpec fspec = ifs->peekFrameSpec();
00969 
00970   FpsTimer fps_timer;
00971 
00972   bool previous_training_mode = prefInTrainingMode.get();
00973   bool previous_do_fixed = esm->getUseFixed();
00974   Image<PixRGB<byte> > rgbin_last;
00975 
00976   ModelParamBatch objrecParams;
00977   objrecParams.addParamValue("EseDynamicFoa", false);
00978   objrecParams.addParamValue("EseFoaSize", 80);
00979   objrecParams.addParamValue("NeobrainBoringnessThresh", 2000);
00980   objrecParams.addParamValue("NeobrainTargetFramesThresh", (unsigned long) 2000);
00981   objrecParams.addParamValue("NeobrainNoMoveFramesThresh", (unsigned long) 2000);
00982 
00983   bool previous_objrec_mode = prefInObjRecMode.get();
00984 
00985   while (true)
00986     {
00987       if (signum != 0) {
00988           LINFO("quitting because %s was caught", signame(signum));
00989           retval = -1;
00990           break;
00991       }
00992 
00993       if (ofs->becameVoid()) {
00994         LINFO("quitting because output stream was closed or became void");
00995         break;
00996       }
00997 
00998       if (esv->shouldQuit()) break;
00999 
01000       //
01001       // update preferences window and uidata
01002       //
01003 
01004       pwin.update(); // handle pending preference window events
01005 
01006       setPause(prefPause.get());
01007       uidata.remote_command = prefRemoteCommand.get();
01008 
01009       prefCommitTrainingImage.setDisabled(!prefInTrainingMode.get());
01010       prefCommitTrainingImageConfirm.setDisabled(!prefInTrainingMode.get());
01011       prefTrainingLabel.setDisabled(!prefInTrainingMode.get());
01012 
01013       pwin.setFont(SimpleFont::fixedMaxWidth(prefFontSize.get()));
01014 
01015       inputprefs.setFont(SimpleFont::fixedMaxWidth(prefFontSize.get()));
01016       inputprefs.update();
01017 
01018       if (prefInObjRecMode.get()) {
01019         if (!previous_objrec_mode) objrecParams.installValues(&manager); // save previous values
01020       } else {
01021         if (previous_objrec_mode) objrecParams.restoreValues(&manager); //restore values
01022       }
01023 
01024       previous_objrec_mode = prefInObjRecMode.get();
01025 
01026       // This code enforces the "training mode" logic
01027       //  .. i.e., certain combinations of preferences are not possible.
01028       uidata.accepted_training_label = "";
01029 
01030       if (prefInTrainingMode.get()) {
01031         if (!previous_training_mode) previous_do_fixed = esm->getUseFixed();
01032 
01033           esm->setUseFixed(true);
01034 
01035           if (prefCommitTrainingImageConfirm.get()) {
01036             if (!prefCommitTrainingImage.get())
01037               prefCommitTrainingImageConfirm.set(false);
01038             else if (prefTrainingLabel.get().length() <= 3) {
01039               prefCommitTrainingImage.set(false);
01040               prefCommitTrainingImageConfirm.set(false);
01041               prefTrainingLabel.set("");
01042 
01043               LERROR("invalid training label %s (too short)", prefTrainingLabel.get().c_str());
01044             } else {
01045               // OK, we accept the training label as a valid one
01046               // and send it off to the labelers:
01047               uidata.accepted_training_label = prefTrainingLabel.get();
01048             }
01049           }
01050       } else {
01051         // training mode is off, certain settings not possible
01052         prefDoGrabFrame.set(true);
01053         prefCommitTrainingImage.set(false);
01054         prefCommitTrainingImageConfirm.set(false);
01055         prefTrainingLabel.set("");
01056 
01057         // this just handles unfixing window when training is first toggled off
01058         if (previous_training_mode) esm->setUseFixed(previous_do_fixed);
01059       }
01060 
01061       previous_training_mode = prefInTrainingMode.get();
01062 
01063       if (p.checkPause()) continue;
01064 
01065       //
01066       // get the next frame from our input source
01067       //
01068 
01069       const FrameState is = ifs->updateNext();
01070       if (is == FRAME_COMPLETE) break;
01071 
01072       GenericFrame input = ifs->readFrame();
01073       if (!input.initialized()) break;
01074 
01075       // only read in from camera if do_grab_frame
01076       const Image<PixRGB<byte> > rgbin = prefDoGrabFrame.get() ? input.asRgb() : rgbin_last;
01077 
01078       rgbin_last = rgbin;
01079 
01080       if (eit->belowConfidenceThresh()) uidata.targetLoc = neoBrain->trackObject(rgbin);
01081       else uidata.targetLoc = Point2D<int>(-1,-1);
01082 
01083       //
01084       // send the frame to the EnvVisualCortex and get the vcx output
01085       //
01086 
01087       evc->input(rgbin);
01088 
01089       fps_timer.nextFrame();
01090       uidata.time_state = fps_timer.getState();
01091 
01092       if (uidata.time_state.frame_number % 50 == 0)
01093         LINFO("frame %u: %.2f fps", uidata.time_state.frame_number, uidata.time_state.recent_fps);
01094 
01095       const Image<byte> vcxmap = evc->getVCXmap();
01096 
01097       //
01098       // build a ui job to run in the background to display update the
01099       // saliency map the input frame, the vcx maps,
01100       //
01101 
01102       uiq->enqueueJob(rutz::make_shared
01103                       (new Nv2UiJob
01104                        (ofs.get(),
01105                         esv.get(),
01106                         eit.get(),
01107                         uidata,
01108                         esm.get(),
01109                         esec->getSeg().get(),
01110                         neoBrain.get(),
01111                         rgbin, vcxmap
01112                         , evc->getImap()
01113                         , evc->getCmap()
01114                         , evc->getOmap()
01115 #ifdef ENV_WITH_DYNAMIC_CHANNELS
01116                         , evc->getFmap()
01117                         , evc->getMmap()
01118 #endif
01119                         )));
01120     }
01121 
01122   // destroy the ui queue so that we force it to shut down now
01123   uiq.reset(0);
01124 
01125   manager.stop();
01126 
01127   return retval;
01128 }
01129 
01130 // ######################################################################
01131 int main(int argc, const char** argv)
01132 {
01133   try {
01134     return submain(argc, argv);
01135   } catch (...) {
01136     REPORT_CURRENT_EXCEPTION;
01137   }
01138 }
01139 
01140 // ######################################################################
01141 /* So things look consistent in everyone's emacs... */
01142 /* Local Variables: */
01143 /* mode: c++ */
01144 /* indent-tabs-mode: nil */
01145 /* End: */
Generated on Sun May 8 08:40:58 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3