00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Image/OpenCVUtil.H"
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>
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
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
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
00341 drawRectSquareCorners(zoomedsm, Rectangle(smstate.lowres_maxpos * m_dispzoom, Dims(m_dispzoom, m_dispzoom)),
00342 PixRGB<byte>(255, 0, 0), 3);
00343
00344
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
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
00494 const Rectangle foa = ese->getFoa(rgbin, smstate.fullres_maxpos, &foamask, &segmentdisp);
00495
00496
00497
00498
00499
00500
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
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
00530 textLog(uidata.text_log_file, "FOAbox", convertToString(foa));
00531
00532 const FrameState os = ofs->updateNext();
00533
00534
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
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
00551 if (esv->optExtendedDisplay.getVal() == 10) {
00552
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
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
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
00578 ofs->writeRGB(markup, esv->optMainwinTitle.getVal(), FrameInfo("copy of input", SRC_POS));
00579
00580
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
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
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
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
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
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, 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
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
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
00899 manager.setOptionValString(&OPT_OutputFrameSink, "display");
00900
00901
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
00949
00950 rutz::shared_ptr<WorkThreadServer> tsrv(new WorkThreadServer("neovision2-ui", 1));
00951
00952
00953
00954 tsrv->setMaxQueueSize(esv->optAsyncUiQueueSize.getVal());
00955 tsrv->setDropPolicy(WorkThreadServer::DROP_OLDEST);
00956 tsrv->setFlushBeforeStopping(esv->optFlushUiQueue.getVal());
00957 uiq = tsrv;
00958 } else {
00959
00960
00961 uiq.reset(new SyncJobServer);
00962 }
00963
00964 ASSERT(uiq.get() != 0);
00965
00966 ifs->startStream();
00967
00968
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
01002
01003
01004 pwin.update();
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);
01020 } else {
01021 if (previous_objrec_mode) objrecParams.restoreValues(&manager);
01022 }
01023
01024 previous_objrec_mode = prefInObjRecMode.get();
01025
01026
01027
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
01046
01047 uidata.accepted_training_label = prefTrainingLabel.get();
01048 }
01049 }
01050 } else {
01051
01052 prefDoGrabFrame.set(true);
01053 prefCommitTrainingImage.set(false);
01054 prefCommitTrainingImageConfirm.set(false);
01055 prefTrainingLabel.set("");
01056
01057
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
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
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
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
01099
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
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
01142
01143
01144
01145