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/BufferedInputFrameSeries.H"
00063 #include "Media/FrameSeries.H"
00064 #include "Media/MediaOpts.H"
00065 #include "NeovisionII/Nv2LabelReader.H"
00066 #include "NeovisionII/nv2_common.h"
00067 #include "Neuro/NeoBrain.H"
00068 #include "Neuro/EnvInferoTemporal.H"
00069 #include "Neuro/EnvSaliencyMap.H"
00070 #include "Neuro/EnvSegmenterConfigurator.H"
00071 #include "Neuro/EnvVisualCortex.H"
00072 #include "Raster/GenericFrame.H"
00073 #include "Raster/Raster.H"
00074 #include "Transport/FrameInfo.H"
00075 #include "Transport/TransportOpts.H"
00076 #include "Util/FpsTimer.H"
00077 #include "Util/Pause.H"
00078 #include "Util/StringConversions.H"
00079 #include "Util/StringUtil.H"
00080 #include "Util/SyncJobServer.H"
00081 #include "Util/SysInfo.H"
00082 #include "Util/TextLog.H"
00083 #include "Util/WorkThreadServer.H"
00084 #include "Util/csignals.H"
00085 #include "rutz/shared_ptr.h"
00086 #include "rutz/trace.h"
00087
00088 #include <ctype.h>
00089 #include <deque>
00090 #include <iterator>
00091 #include <limits>
00092 #include <stdlib.h>
00093 #include <string.h>
00094 #include <sys/resource.h>
00095 #include <signal.h>
00096 #include <time.h>
00097 #include <vector>
00098
00099 #define PREFERRED_TEXT_LENGTH 42
00100
00101 struct Nv2UiData
00102 {
00103 Nv2UiData(const int map_zoom_) :
00104 map_zoom(map_zoom_), ncpu(numCpus())
00105 {}
00106
00107 FpsTimer::State time_state;
00108 const int map_zoom;
00109 const int ncpu;
00110 };
00111
00112 std::string time2str(const rutz::time& t)
00113 {
00114 const double s = t.sec();
00115
00116 const int hpart = int(s/(60.0*60.0));
00117 const int mpart = int((s-hpart*60*60)/60.0);
00118 const double spart = s - hpart*60*60 - mpart*60;
00119
00120 return sformat("%02d:%02d:%06.3f", hpart, mpart, spart);
00121 }
00122
00123 class Nv2UiJob : public JobServer::Job
00124 {
00125 public:
00126 Nv2UiJob(OutputFrameSeries* ofs_, const Nv2UiData& uidata_,
00127 Image<PixRGB<byte> > rgbin_, Image<byte> vcxmap_,
00128 Image<byte> Imap_, Image<byte> Cmap_, Image<byte> Omap_
00129 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00130 , Image<byte> Fmap_, Image<byte> Mmap_
00131 #endif
00132 ) :
00133 ofs(ofs_), uidata(uidata_), rgbin(rgbin_), vcxmap(vcxmap_),
00134 Imap(Imap_), Cmap(Cmap_), Omap(Omap_)
00135 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00136 , Fmap(Fmap_), Mmap(Mmap_)
00137 #endif
00138 { }
00139
00140 virtual void run()
00141 {
00142 ofs->updateNext();
00143
00144 Point2D<int> win; byte winval;
00145 findMax(vcxmap, win, winval);
00146 win = win * uidata.map_zoom;
00147
00148
00149 Image<PixRGB<byte> > markup = rgbin;
00150 drawCircle(markup, win, 3, PixRGB<byte>(60, 220, 255), 3);
00151
00152
00153 Image<byte> sm = vcxmap;
00154 Image<PixRGB<byte> > smc =
00155 zoomXY(sm, uidata.map_zoom / 2, uidata.map_zoom / 2);
00156 drawCircle(smc, win/2, 3, PixRGB<byte>(60, 220, 255), 3);
00157
00158 const std::string lines[2] =
00159 {
00160 sformat("peak %3d @ (%3d,%3d)",
00161 winval, win.i, win.j),
00162 sformat("%s [%5.2ffps, %5.1f%%CPU]",
00163 time2str(uidata.time_state.elapsed_time).c_str(),
00164 uidata.time_state.recent_fps,
00165 uidata.time_state.recent_cpu_usage*100.0)
00166 };
00167
00168 const Image<PixRGB<byte> > textarea =
00169 makeMultilineTextBox(smc.getWidth(), &lines[0], 2,
00170 PixRGB<byte>(255, 255, 0), PixRGB<byte>(0,0,0),
00171 PREFERRED_TEXT_LENGTH);
00172
00173 Layout<PixRGB<byte> > disp = vcat(smc, textarea);
00174
00175
00176
00177 ofs->writeRGB(markup, "neovision2-HD",
00178 FrameInfo("copy of input", SRC_POS));
00179 }
00180
00181 virtual const char* jobType() const { return "Nv2UiJob"; }
00182
00183 private:
00184 OutputFrameSeries* const ofs;
00185 const Nv2UiData uidata;
00186 Image<PixRGB<byte> > rgbin;
00187 const Image<byte> vcxmap;
00188 const Image<byte> Imap;
00189 const Image<byte> Cmap;
00190 const Image<byte> Omap;
00191 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00192 const Image<byte> Fmap;
00193 const Image<byte> Mmap;
00194 #endif
00195 };
00196
00197
00198 int submain(int argc, const char** argv)
00199 {
00200 volatile int signum = 0;
00201 signal(SIGPIPE, SIG_IGN);
00202 catchsignals(&signum);
00203
00204
00205
00206 ModelManager manager("Nv2hd");
00207
00208 nub::ref<BufferedInputFrameSeries>
00209 ifs(new BufferedInputFrameSeries(manager, 50, true));
00210 manager.addSubComponent(ifs);
00211
00212 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00213 manager.addSubComponent(ofs);
00214
00215 nub::ref<EnvVisualCortex> evc(new EnvVisualCortex(manager));
00216 manager.addSubComponent(evc);
00217
00218 manager.exportOptions(MC_RECURSE);
00219
00220 #if defined(HAVE_IEEE1394)
00221
00222 manager.setOptionValString(&OPT_InputFrameSource, "ieee1394");
00223 manager.setOptionValString(&OPT_FrameGrabberMode, "RGB24");
00224 manager.setOptionValString(&OPT_FrameGrabberDims, "640x480");
00225 manager.setOptionValString(&OPT_FrameGrabberFPS, "30");
00226 #elif defined(HAVE_QUICKTIME_QUICKTIME_H)
00227 manager.setOptionValString(&OPT_InputFrameSource, "qtgrab");
00228 manager.setOptionValString(&OPT_FrameGrabberDims, "640x480");
00229 #endif
00230
00231
00232 manager.setOptionValString(&OPT_OutputFrameSink, "display");
00233
00234
00235 manager.setOptionValString(&OPT_EvcColorSmoothing, "true");
00236
00237 if (manager.parseCommandLine(argc, argv,
00238 "<ip1:port1,ip2:port2,...>",
00239 0, 1) == false)
00240 return(1);
00241
00242 manager.start();
00243
00244 Nv2UiData uidata(1 << evc->getMapLevel());
00245
00246
00247
00248 rutz::shared_ptr<WorkThreadServer> tsrv
00249 (new WorkThreadServer("neovision2-ui", 1));
00250
00251
00252
00253 tsrv->setMaxQueueSize(3);
00254 tsrv->setDropPolicy(WorkThreadServer::DROP_OLDEST);
00255 tsrv->setFlushBeforeStopping(true);
00256 rutz::shared_ptr<JobServer> uiq = tsrv;
00257
00258
00259
00260 const GenericFrameSpec fspec = ifs->peekFrameSpec();
00261 Image<PixRGB<byte> > rgbin_last(fspec.dims, ZEROS);
00262 FpsTimer fps_timer;
00263
00264 int retval = 0; bool toggle = true; Image<byte> vcxmap;
00265 while (true)
00266 {
00267 if (signum != 0)
00268 {
00269 LINFO("quitting because %s was caught", signame(signum));
00270 retval = -1;
00271 break;
00272 }
00273
00274 if (ofs->becameVoid())
00275 {
00276 LINFO("quitting because output stream was closed or became void");
00277 break;
00278 }
00279
00280
00281
00282
00283 bool underflowed;
00284 Image<PixRGB<byte> > rgbin;
00285 GenericFrame input = ifs->get(&underflowed);
00286 if (!input.initialized())
00287 {
00288 if (underflowed) { LINFO("Input underflow!"); rgbin = rgbin_last; }
00289 else break;
00290 }
00291 else
00292 rgbin = input.asRgb();
00293
00294 rgbin_last = rgbin;
00295
00296
00297
00298
00299 if (toggle)
00300 {
00301 evc->input(rgbin);
00302 vcxmap = evc->getVCXmap();
00303 }
00304
00305 toggle = !toggle;
00306
00307 fps_timer.nextFrame();
00308 uidata.time_state = fps_timer.getState();
00309
00310 if (uidata.time_state.frame_number % 50 == 0)
00311 LINFO("frame %u: %.2f fps",
00312 uidata.time_state.frame_number,
00313 uidata.time_state.recent_fps);
00314
00315
00316
00317
00318
00319 uiq->enqueueJob(rutz::make_shared
00320 (new Nv2UiJob
00321 (ofs.get(), uidata, rgbin, vcxmap, evc->getImap(),
00322 evc->getCmap(), evc->getOmap()
00323 #ifdef ENV_WITH_DYNAMIC_CHANNELS
00324 , evc->getFmap(), evc->getMmap()
00325 #endif
00326 )));
00327 }
00328
00329
00330 uiq.reset(0);
00331
00332 manager.stop();
00333
00334 return retval;
00335 }
00336
00337
00338 int main(int argc, const char** argv)
00339 {
00340 try
00341 {
00342 return submain(argc, argv);
00343 }
00344 catch (...)
00345 {
00346 REPORT_CURRENT_EXCEPTION;
00347 }
00348 }
00349
00350
00351
00352
00353
00354
00355