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 #include "Component/JobServerConfigurator.H"
00036 #include "Component/ModelManager.H"
00037 #include "Component/GlobalOpts.H"
00038 #include "Channels/ChannelOpts.H"
00039 #include "Media/FrameSeries.H"
00040 #include "Transport/FrameInfo.H"
00041 #include "Raster/GenericFrame.H"
00042 #include "Image/Image.H"
00043 #include "Image/ImageSet.H"
00044 #include "Image/DrawOps.H"
00045 #include "Image/ShapeOps.H"
00046 #include "Image/Layout.H"
00047 #include "GUI/ImageDisplayStream.H"
00048 #include "GUI/XWinManaged.H"
00049 #include "GUI/DebugWin.H"
00050 #include "GUI/SimpleMeter.H"
00051 #include "Neuro/EnvOpts.H"
00052 #include "Neuro/NeuroOpts.H"
00053 #include "Apps/BorderWatch/ImageInfo.H"
00054 #include "Simulation/SimulationOpts.H"
00055 #include "Simulation/SimEventQueue.H"
00056 #include "Simulation/SimEventQueueConfigurator.H"
00057 #include "Util/Timer.H"
00058 #include <queue>
00059 #include <cmath>
00060 #include <cstdio>
00061 #include <fstream>
00062
00063 const ModelOptionCateg MOC_BORDERWATCH = {
00064 MOC_SORTPRI_3, "BorderWatch-Related Options" };
00065
00066 static const ModelOptionDef OPT_ShowDebugWin =
00067 { MODOPT_FLAG, "ShowDebugWin", &MOC_BORDERWATCH, OPTEXP_CORE,
00068 "Whether to show the input image, the saliency maps, and the beliefs. "
00069 "This is used for debugging and setting the thresholds. ",
00070 "show-debug-win", '\0', "", "false" };
00071
00072 static const ModelOptionDef OPT_ShowThumbs =
00073 { MODOPT_FLAG, "ShowThumbs", &MOC_BORDERWATCH, OPTEXP_CORE,
00074 "Show thumbnails of the most recent frames that had surprise above threshold",
00075 "show-thumbs", '\0', "", "false" };
00076
00077 static const ModelOptionDef OPT_Threshold =
00078 { MODOPT_ARG(float), "Threshold", &MOC_BORDERWATCH, OPTEXP_CORE,
00079 "The threshold level at which to save images to disk. ",
00080 "threshold", '\0', "<float>", "3.5e-10" };
00081
00082 static const ModelOptionDef OPT_ImgQLen =
00083 { MODOPT_ARG(uint), "ImgQLen", &MOC_BORDERWATCH, OPTEXP_CORE,
00084 "Length of the queue of images for movie context, in frames",
00085 "imgqlen", '\0', "<uint>", "50" };
00086
00087 const ModelOptionDef OPT_OutFname =
00088 { MODOPT_ARG_STRING, "OutFname", &MOC_BORDERWATCH, OPTEXP_CORE,
00089 "File name for text output data (or empty to not save output data)",
00090 "out-fname", '\0', "<file>", "" };
00091
00092
00093 void displayOutput(const Image<PixRGB<byte> >& img, nub::ref<OutputFrameSeries> ofs, bool showThumbs)
00094 {
00095 static const uint nx = 15, ny = 12;
00096 static ImageSet<PixRGB<byte> > thumbs(nx*ny, Dims(img.getWidth()/2, img.getHeight()/2), ZEROS);
00097
00098
00099 if (showThumbs) {
00100 thumbs.push_back(quickLocalAvg2x2(img)); while(thumbs.size() > nx*ny) thumbs.pop_front();
00101 Layout<PixRGB<byte> > t = arrcat(thumbs, nx);
00102 ofs->writeRgbLayout(t, "Thumbnails", FrameInfo("Thumbnails", SRC_POS));
00103 }
00104
00105
00106 ofs->writeRGB(img, "Output", FrameInfo("Output", SRC_POS));
00107 ofs->updateNext();
00108 }
00109
00110
00111 int main(const int argc, const char **argv)
00112 {
00113 MYLOGVERB = LOG_INFO;
00114 ModelManager mgr("Border Watch");
00115
00116 nub::ref<JobServerConfigurator> jsc(new JobServerConfigurator(mgr));
00117 mgr.addSubComponent(jsc);
00118
00119 nub::ref<SimEventQueueConfigurator> seqc(new SimEventQueueConfigurator(mgr));
00120 mgr.addSubComponent(seqc);
00121
00122 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(mgr));
00123 mgr.addSubComponent(ofs);
00124
00125 nub::ref<InputFrameSeries> ifs(new InputFrameSeries(mgr));
00126 mgr.addSubComponent(ifs);
00127
00128 nub::ref<ImageInfo> imageInfo(new ImageInfo(mgr));
00129 mgr.addSubComponent(imageInfo);
00130
00131 OModelParam<bool> optShowDebugWin(&OPT_ShowDebugWin, &mgr);
00132 OModelParam<bool> optShowThumbs(&OPT_ShowThumbs, &mgr);
00133 OModelParam<float> optThreshold(&OPT_Threshold, &mgr);
00134 OModelParam<uint> optQLen(&OPT_ImgQLen, &mgr);
00135 OModelParam<std::string> optOutFname(&OPT_OutFname, &mgr);
00136
00137 mgr.exportOptions(MC_RECURSE);
00138 mgr.setOptionValString(&OPT_SimulationTimeStep, "30ms");
00139 mgr.setOptionValString(&OPT_LevelSpec, "1,3,3,4,4");
00140 mgr.setOptionValString(&OPT_VisualCortexType, "Env");
00141 mgr.setOptionValString(&OPT_EvcMultithreaded, "true");
00142 mgr.setOptionValString(&OPT_EnvLevelSpec, "1,3,3,4,4");
00143 mgr.setOptionValString(&OPT_UseRandom, "false");
00144
00145 if (mgr.parseCommandLine(argc, argv, "", 0, 0) == false)
00146 { LFATAL("This program takes no non-option command-line argument; try --help"); return 1; }
00147
00148 nub::ref<SimEventQueue> seq = seqc->getQ();
00149
00150
00151 std::ofstream *outFile = 0;
00152 if (optOutFname.getVal().empty() == false)
00153 {
00154 outFile = new std::ofstream(optOutFname.getVal().c_str());
00155 if (outFile->is_open() == false)
00156 LFATAL("Cannot open '%s' for writing", optOutFname.getVal().c_str());
00157 }
00158
00159
00160 mgr.start();
00161 MYLOGVERB = LOG_CRIT;
00162
00163 std::queue<Image<PixRGB<byte> > > imgQueue;
00164 SimStatus status = SIM_CONTINUE;
00165 Timer tim;
00166
00167
00168 while(status == SIM_CONTINUE) {
00169 ifs->updateNext();
00170
00171
00172 GenericFrame input = ifs->readFrame(); if (!input.initialized()) break;
00173 Image<PixRGB<byte> > img = input.asRgb();
00174
00175
00176 ImageInfo::ImageStats stats = imageInfo->update(seq, img, ifs->frame());
00177
00178 float mi, ma;
00179 Image<float> smapf = stats.smap; inplaceNormalize(smapf, 0.0F, 255.0F, mi, ma);
00180 Image<byte> smap = smapf; smap = rescaleNI(smap, img.getDims());
00181
00182
00183 char msg[255]; time_t rawtime; time(&rawtime);
00184 struct tm *timeinfo; timeinfo = localtime(&rawtime);
00185 sprintf(msg, " %s- S=%g %d", asctime(timeinfo), stats.score, ifs->frame());
00186 writeText(img, Point2D<int>(0,0), msg, PixRGB<byte>(255,0,0), PixRGB<byte>(0), SimpleFont::FIXED(6), true);
00187 sprintf(msg, " Saliency [%.4g .. %.4g] %d ", mi, ma, ifs->frame());
00188 writeText(smap, Point2D<int>(0,0), msg, byte(255), byte(0), SimpleFont::FIXED(6));
00189
00190
00191 const Point2D<int> sp = stats.salpoint * img.getWidth() / smapf.getWidth();
00192 if (stats.score > optThreshold.getVal()) drawCircle(img, sp, 15, PixRGB<byte>(255,255,0), 2);
00193 else drawCircle(img, sp, 5, PixRGB<byte>(0,128,0), 1);
00194
00195
00196 imgQueue.push(img);
00197 if (imgQueue.size() > optQLen.getVal()) imgQueue.pop();
00198
00199
00200 if (optShowDebugWin.getVal())
00201 {
00202 if (stats.belief1.initialized() && stats.belief2.initialized()) {
00203 Image<float> b1f = stats.belief1; inplaceNormalize(b1f, 0.0F, 255.0F, mi, ma);
00204 Image<byte> b1 = b1f; b1 = rescaleNI(b1, img.getDims());
00205 sprintf(msg, " Beliefs 1 [%.4g .. %.4g] ", mi, ma);
00206 writeText(b1, Point2D<int>(0,0), msg, byte(255), byte(0), SimpleFont::FIXED(6));
00207 drawLine(b1, Point2D<int>(0,0), Point2D<int>(0, b1.getHeight()-1), byte(255));
00208
00209 Image<float> b2f = stats.belief2; inplaceNormalize(b2f, 0.0F, 255.0F, mi, ma);
00210 Image<byte> b2 = b2f; b2 = rescaleNI(b1, img.getDims());
00211 sprintf(msg, " Beliefs 2 [%.4g .. %.4g] ", mi, ma);
00212 writeText(b2, Point2D<int>(0,0), msg, byte(255), byte(0), SimpleFont::FIXED(6));
00213 drawLine(b2, Point2D<int>(0,0), Point2D<int>(0, b2.getHeight()-1), byte(255));
00214
00215 Layout<byte> smapDisp;
00216 smapDisp = hcat(hcat(smap, b1), b2);
00217 ofs->writeGrayLayout(smapDisp, "Smap", FrameInfo("Smap", SRC_POS));
00218 } else ofs->writeGray(smap, "Smap", FrameInfo("Smap", SRC_POS));
00219
00220 const MeterInfo infos[] = {
00221 { "", stats.score, optThreshold.getVal()*3, optThreshold.getVal(), PixRGB<byte>(0, 255, 0) }
00222 };
00223 Image<PixRGB<byte> > meterImg =
00224 drawMeters(&infos[0], sizeof(infos) / sizeof(infos[0]), 1, Dims(img.getWidth(),20));
00225
00226 Layout<PixRGB<byte> > inputDisp;
00227 inputDisp = vcat(img, meterImg);
00228 ofs->writeRgbLayout(inputDisp, "Input", FrameInfo("Input", SRC_POS));
00229 }
00230
00231 if (stats.score > optThreshold.getVal())
00232 {
00233 if (imgQueue.size() == optQLen.getVal())
00234 {
00235 Image<PixRGB<byte> > title = imgQueue.back();
00236
00237 sprintf(msg, "Date: %s ", asctime(timeinfo));
00238 writeText(title, Point2D<int>(0,title.getHeight()-40), msg, PixRGB<byte>(255), PixRGB<byte>(0));
00239 sprintf(msg, "Surprise: %e ", stats.score);
00240 writeText(title, Point2D<int>(0,title.getHeight()-20), msg, PixRGB<byte>(255), PixRGB<byte>(0));
00241
00242 for (int i = 0; i < 3; ++i) displayOutput(title, ofs, optShowThumbs.getVal());
00243 }
00244
00245 while(!imgQueue.empty())
00246 {
00247 Image<PixRGB<byte> > tImg = imgQueue.front(); imgQueue.pop();
00248 displayOutput(tImg, ofs, optShowThumbs.getVal());
00249 }
00250 }
00251
00252
00253 if (ifs->frame() > 0 && (ifs->frame() % 100) == 0) {
00254 printf("Frame %06d - %.2ffps\n", ifs->frame(), 100.0 / tim.getSecs());
00255 tim.reset();
00256 }
00257
00258
00259 if (outFile)
00260 (*outFile)<<sformat("of=%i if=%i score=%e x=%d y=%d sal=%e ener=%e uniq=%e entr=%e rand=%e kls=%e msds=%e %s",
00261 ofs->frame(), ifs->frame(), stats.score, sp.i, sp.j, stats.saliency, stats.energy,
00262 stats.uniqueness, stats.entropy, stats.rand, stats.KLsurprise, stats.MSDsurprise,
00263 asctime(timeinfo));
00264
00265
00266 status = seq->evolve();
00267 }
00268
00269 LINFO("Simulation terminated.");
00270 mgr.stop();
00271 if (outFile) { outFile->close(); delete outFile; }
00272
00273 return 0;
00274 }
00275
00276