SimulationViewerStats.C

Go to the documentation of this file.
00001 /*!@file Neuro/SimulationViewerStats.C View/save a bunch of stats */
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: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/SimulationViewerStats.C $
00035 // $Id: SimulationViewerStats.C 13065 2010-03-28 00:01:00Z itti $
00036 //
00037 
00038 #include "Neuro/SimulationViewerStats.H"
00039 #include "Channels/ChannelMaps.H"
00040 #include "Channels/ChannelOpts.H"
00041 #include "Image/colorDefs.H"
00042 #include "Image/CutPaste.H"
00043 #include "Image/ColorOps.H"
00044 #include "Image/DrawOps.H"
00045 #include "Image/fancynorm.H"
00046 #include "Image/FFTWWrapper.H"
00047 #include "Image/ImageSet.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/ShapeOps.H"
00050 #include "Image/NamedImage.H"
00051 #include "Media/MediaSimEvents.H"
00052 #include "Neuro/Brain.H"
00053 #include "Neuro/NeuroOpts.H"
00054 #include "Neuro/NeuroSimEvents.H"
00055 #include "Neuro/VisualCortex.H"
00056 #include "Transport/FrameInfo.H"
00057 #include "Transport/FrameOstream.H"
00058 #include <fcntl.h> // for open()
00059 #include <cerrno> // for errno
00060 
00061 
00062 // ######################################################################
00063 SimulationViewerStats::SimulationViewerStats(OptionManager& mgr,
00064                                          const std::string& descrName,
00065                                          const std::string& tagName) :
00066   SimulationViewer(mgr, descrName, tagName),
00067   SIMCALLBACK_INIT(SimEventSaveOutput),
00068   itsStatsFname(&OPT_SVstatsFname, this),
00069   itsSaveXcombo(&OPT_SVsaveXcombo, this),
00070   itsSaveYcombo(&OPT_SVsaveYcombo, this),
00071   itsComputeAGStats(&OPT_ComputeAGStats, this),
00072   itsAGTargetFrame(&OPT_AGTargetFrame, this),
00073   itsAGMaskFile(&OPT_AGMaskFile, this),
00074   itsAGStatsSaveFile(&OPT_AGStatsSaveFile, this),
00075   itsGetSingleChannelStats(&OPT_GetSingleChannelStats, this),
00076   itsGetSingleChannelStatsFile(&OPT_GetSingleChannelStatsFile, this),
00077   itsSaveStatsPerChannelFreq(&OPT_SaveStatsPerChannelFreq, this),
00078   itsStatsFile(NULL)
00079 { }
00080 
00081 // ######################################################################
00082 SimulationViewerStats::~SimulationViewerStats()
00083 { }
00084 
00085 // ######################################################################
00086 void SimulationViewerStats::start2()
00087 {
00088   // Used by saveCompat for frame counts
00089   itsFrameIdx = 0;
00090 
00091   // Reset counters
00092   itsMaskCount = 0; itsLamCount = 0; itsOverlapCount = 0;
00093 }
00094 
00095 // ######################################################################
00096 void SimulationViewerStats::stop2()
00097 {
00098   // close our stats file if we have one:
00099   if (itsStatsFile)
00100     {
00101       itsStatsFile->flush();
00102       itsStatsFile->close();
00103       delete itsStatsFile;
00104       itsStatsFile = NULL;
00105     }
00106 }
00107 
00108 // #####################################################################
00109 void SimulationViewerStats::lockFile(const std::string fileName,
00110                                      int &fd,
00111                                      struct flock &fl) const
00112 {
00113   // lock file
00114   fd = open(fileName.c_str(), O_RDWR);
00115   if (fd < 0)
00116   {
00117         LINFO("lockFile: Open failure on file %s",fileName.c_str());
00118   }
00119   else
00120   {
00121     fl.l_type   = F_WRLCK;
00122     fl.l_whence = SEEK_SET;
00123     fl.l_start  = 0;
00124     fl.l_len    = 0;
00125     if (fcntl(fd, F_SETLK, &fl) == -1)
00126     {
00127       if (errno == EACCES || errno == EAGAIN)
00128         LINFO("'%s' Already locked by another process",fileName.c_str());
00129       else if(errno == EBADF)
00130         LINFO("'%s' not a valid open file descriptor",fileName.c_str());
00131       else if(errno == EINVAL)
00132         LINFO("'%s In a locking operation, fildes refers to a file with a type that does not support locking, or the struct flock pointed to by the third argument has an incorrect form",fileName.c_str());
00133       else if(errno == EMFILE)
00134         LINFO("'%s' process has already reached its maximum number of file descriptors",fileName.c_str());
00135       else
00136       LINFO("Cannot lock file '%s' Error code '%d' \(Is this an NFS mount?)",fileName.c_str(),errno);
00137     }
00138   }
00139 }
00140 
00141 // #####################################################################
00142 void SimulationViewerStats::unlockFile(const std::string fileName,
00143                                        const  int fd,
00144                                        struct flock &fl) const
00145 {
00146   // unlockfile
00147   fl.l_type   = F_UNLCK;
00148   fl.l_whence = SEEK_SET;
00149   fl.l_start  = 0;
00150   fl.l_len    = 0;
00151   if (fcntl(fd, F_SETLK, &fl) == -1)
00152   {
00153     LINFO("Cannot unlock file '%s'",fileName.c_str());
00154   }
00155   close(fd);
00156 }
00157 
00158 // ######################################################################
00159 void SimulationViewerStats::
00160 onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00161 {
00162   this->save1(e->sinfo());
00163 }
00164 
00165 // ######################################################################
00166 void SimulationViewerStats::save1(const ModelComponentSaveInfo& sinfo)
00167 {
00168   // Use a LINFO here since we are already slowed down by writing
00169   // stats, we should at least have a short debug on this fact
00170   LINFO("SAVING STATS TO %s",itsStatsFname.getVal().c_str());
00171 
00172   // Lock the file. We put this here to support multi-process in the
00173   // future. However, this will not work on NFS mounts.
00174   struct flock fl; int fd;
00175   lockFile(itsStatsFname.getVal().c_str(),fd,fl);
00176 
00177   // Since this is more or less debug info we open and flush every iteration.
00178   // rather than once each run.
00179   std::ofstream statsFile;
00180   statsFile.open(itsStatsFname.getVal().c_str(),std::ios_base::app);
00181 
00182   // get the OFS to save to, assuming sinfo is of type
00183   // SimModuleSaveInfo (will throw a fatal exception otherwise):
00184   nub::ref<FrameOstream> ofs =
00185     dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs;
00186 
00187   // also get the SimEventQueue:
00188   SimEventQueue *q    = dynamic_cast<const SimModuleSaveInfo&>(sinfo).q;
00189 
00190   // initialize our stats dump file if desired:
00191   if(itsFrameIdx == 0)
00192   {
00193     rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this));
00194     q->request(vcxm); // VisualCortex is now filling-in the maps...
00195 
00196     if (itsStatsFname.getVal().size())
00197     {
00198       itsStatsFile = new std::ofstream(itsStatsFname.getVal().c_str());
00199       if (itsStatsFile->is_open() == false)
00200         LFATAL("Failed to open '%s' for writing.",
00201                itsStatsFname.getVal().c_str());
00202 
00203       // dump the settings of the model:
00204       getRootObject()->printout(*itsStatsFile, "# ");
00205 
00206       // list all our channels:
00207       //LFATAL("FIXME");
00208       // also get the SimEventQueue:
00209 
00210       rutz::shared_ptr<ChannelMaps> chm        = vcxm->channelmaps();
00211       uint                          numSubmaps = chm->numSubmaps();
00212 
00213       *itsStatsFile << "# CHANNELS: ";
00214 
00215       for(uint i = 0; i < numSubmaps; i++)
00216       {
00217         NamedImage<float> smap = chm->getRawCSmap(i);
00218         *itsStatsFile << smap.name() << ", ";
00219       }
00220       *itsStatsFile << std::endl;
00221     }
00222   }
00223 
00224   // We flush frequently since this output is debuggy in nature or it's being used
00225   // to collect information which needs assurance of accuracy for instance in
00226   // RSVP analysis. It is better to err on the side of caution.
00227   (*itsStatsFile).flush();
00228   (*itsStatsFile).close();
00229 
00230   // get the basic input frame info
00231   if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this))
00232   {
00233     itsSizeX       = e->frame().getWidth();
00234     itsSizeY       = e->frame().getHeight();
00235     itsFrameNumber = (unsigned int)e->frameNum();
00236     itsFrameIdx    = itsFrameNumber;
00237   }
00238   else
00239   {
00240     itsFrameNumber = itsFrameIdx;
00241     itsFrameIdx++;
00242   }
00243 
00244   // get the latest input frame:
00245   // Since we are only using it's basic statistics (Height / Width) , we don't care about it's
00246   // blackboard status. Use SEQ_ANY then. Otherwise, this will not fetch at any rate.
00247   Image< PixRGB<byte> > input;
00248   if (SeC<SimEventRetinaImage> e = q->check<SimEventRetinaImage>(this,SEQ_ANY))
00249     input = e->frame().colorByte();
00250   else
00251     LINFO("No input? Check the SimEventCue.");
00252 
00253   // Get the current frame number or keep track on your own
00254   /*
00255   if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this))
00256     itsFrameIdx = e->frameNum();
00257   else
00258     itsFrameIdx++;
00259   */
00260 
00261   // get the latest raw AGM:
00262   Image<float> agm;
00263   if (SeC<SimEventAttentionGuidanceMapOutput> e =
00264       q->check<SimEventAttentionGuidanceMapOutput>(this))
00265     agm = e->agm(1.0F);
00266   else
00267     LINFO("No AGM? Check the SimEventCue.");
00268 
00269   // if we are missing input or agm, return:
00270   // We also need to warn so that we know why the stats file may be empty
00271   bool quit = false;
00272   if (input.initialized() == false)
00273     {
00274       LINFO("WARNING!!! Input seems not to be initialized, so detailed stats cannot be saved.");
00275       quit = true;
00276     }
00277   if(agm.initialized() == false)
00278     {
00279       LINFO("WARNING!!! NO Attention Guidance MAP \"AGM\" so detailed stats cannot be saved.");
00280       quit = true;
00281     }
00282 
00283   if(quit == true) return;
00284 
00285   // update the trajectory:
00286   Image< PixRGB<byte> > res;
00287   const int w = input.getWidth();
00288 
00289   // save image results? if so let's prepare it
00290   if (itsSaveXcombo.getVal() || itsSaveYcombo.getVal())
00291     {
00292       Image<float> nagm = getMap(*q);
00293       res = colGreyCombo(input, nagm, itsSaveXcombo.getVal(),
00294                          itsDisplayInterp.getVal());
00295     }
00296 
00297   // if we are saving single channel stats save saliency stats using a compatable format
00298   // SEE: SingleChannel.C / saveStats(..) for more info on format
00299   if (itsGetSingleChannelStats.getVal())
00300     saveCompat(agm);
00301 
00302   // Save a bunch of stats?
00303   if (statsFile)
00304     {
00305       // start with the current simulation time:
00306        statsFile <<std::endl<<"= "<<q->now().msecs()
00307                      <<" # time of frame in ms"<<std::endl;
00308 
00309       // get min/max/avg and stdev and number of peaks in AGM:
00310       float mi, ma, av; getMinMaxAvg(agm, mi, ma, av);
00311       double sdev = stdev(agm);
00312       double peaksum; int npeaks = findPeaks(agm, 0.0f, 255.0f, peaksum);
00313 
00314       // find the location of max in the AGM, at scale of original input:
00315       float maxval; Point2D<int> maxloc;
00316       findMax(agm, maxloc, maxval);
00317       float scale = float(w) / float(agm.getWidth());
00318       maxloc.i = int(maxloc.i * scale + 0.4999F);
00319       maxloc.j = int(maxloc.j * scale + 0.4999F);
00320       if (res.initialized())
00321         {
00322           drawPatch(res, maxloc, 4, COL_YELLOW);
00323           drawPatch(res, maxloc + Point2D<int>(w, 0), 4, COL_YELLOW);
00324         }
00325 
00326       // find the location of min in the AGM, at scale of original input:
00327       float minval; Point2D<int> minloc;
00328       findMin(agm, minloc, minval);
00329       minloc.i = int(minloc.i * scale + 0.4999F);
00330       minloc.j = int(minloc.j * scale + 0.4999F);
00331       if (res.initialized())
00332         {
00333           drawPatch(res, minloc, 4, COL_GREEN);
00334           drawPatch(res, minloc + Point2D<int>(w, 0), 4, COL_GREEN);
00335         }
00336 
00337       // save some stats for that location:
00338        statsFile  <<maxloc.i<<' '<<maxloc.j<<' '<<minloc.i<<' '
00339                   <<minloc.j<<' '<<ma<<' '<<mi<<' '<<av<<' '<<sdev
00340                   <<' '<<npeaks<<' '<<peaksum
00341                   <<" # Xmax Ymax Xmin Ymin max min avg std npeaks peaksum"
00342                   <<std::endl;
00343 
00344       // build a vector of points where we will save samples. First is
00345       // the max, second the min, then a bunch of random locations:
00346       std::vector<Point2D<int> > loc;
00347       loc.push_back(maxloc);
00348       loc.push_back(minloc);
00349       for (uint n = 0; n < 100; n ++)
00350         loc.push_back(Point2D<int>(randomUpToNotIncluding(input.getWidth()),
00351                               randomUpToNotIncluding(input.getHeight())));
00352 
00353       // Get all the conspicuity maps:
00354       ImageSet<float> cmap;
00355       //LFATAL("FIXME");
00356       rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this));
00357       q->request(vcxm); // VisualCortex is now filling-in the maps...
00358       rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps();
00359       uint numSubmaps = chm->numSubmaps();
00360       for(uint i=0;i < numSubmaps; i++)
00361       {
00362         NamedImage<float> tempMap = chm->getRawCSmap(i);
00363         Image<float> m = tempMap;
00364         cmap.push_back(m);
00365 
00366         // also store sample points at the min/max locations:
00367         Point2D<int> p; float v;
00368         findMax(m, p, v); loc.push_back(p);
00369         findMin(m, p, v); loc.push_back(p);
00370       }
00371       /*
00372       for (uint i = 0; i < itsBrain->getVC()->numChans(); i ++)
00373         {
00374           Image<float> m = itsBrain->getVC()->subChan(i)->getOutput();
00375           cmap.push_back(m);
00376 
00377           // also store sample points at the min/max locations:
00378           Point2D<int> p; float v;
00379           findMax(m, p, v); loc.push_back(p);
00380           findMin(m, p, v); loc.push_back(p);
00381         }
00382       */
00383 
00384       // Go over all sample points and save feature map and
00385       // conspicuity map values at those locations:
00386       for (uint i = 0; i < loc.size(); i ++)
00387         {
00388           Point2D<int> p = loc[i];
00389           Point2D<int> pp(int(p.i / scale), int(p.j / scale));
00390 
00391            statsFile <<p.i<<' '<<p.j<<"     ";
00392 
00393           // do the conspicuity maps first. Since they are all at the
00394           // scale of the AGM, we use pp:
00395           for (uint j = 0; j < cmap.size(); j ++)
00396           {
00397             if((int(p.i / scale) < agm.getWidth()) &&
00398                (int(p.j / scale) < agm.getHeight()))
00399             {
00400               (statsFile)<<cmap[j].getVal(pp)<<' ';
00401               (statsFile)<<"    ";
00402             }
00403             else
00404             {
00405               (statsFile)<<"-1"<<' ';
00406               (statsFile)<<"    ";
00407             }
00408           }
00409 
00410           // now the feature maps, we use coordinates p:
00411           /* TOO BOGUS - disabled for now
00412           std::vector<double> f;
00413           itsBrain->getVC()->getFeatures(p, f);
00414           for (uint j = 0; j < f.size(); j ++) (*statsFile)<<f[j]<<' ';
00415           */
00416 
00417            statsFile  <<"# features "<<i<<" at ("<<p.i
00418                          <<", "<<p.j<<')'<<std::endl;
00419         }
00420   }
00421 
00422   statsFile.flush();
00423   statsFile.close();
00424   unlockFile(itsStatsFname.getVal().c_str(),fd,fl);
00425   // save results?
00426   if (res.initialized())
00427     ofs->writeRGB(res, "T",
00428                   FrameInfo("SimulationViewerStats trajectory", SRC_POS));
00429 
00430   // Should we compute attention gate stats
00431   // If we have AG stats we will save the basic LAM stats anyways
00432   if(itsComputeAGStats.getVal())
00433     computeAGStats(*q);
00434   else if (SeC<SimEventAttentionGateOutput> ag =
00435            q->check<SimEventAttentionGateOutput>(this))
00436     computeLAMStats(ag->lam());
00437 
00438   //! Save the overlap image
00439   if(itsOverlap.initialized())
00440     ofs->writeRGB(itsOverlap, "AG-STAT-MASK",
00441                   FrameInfo("Stats mask overlap", SRC_POS));
00442 
00443   if(itsVisualSegments.initialized())
00444     ofs->writeRGB(itsVisualSegments, "AG-STAT-SEGS",
00445                   FrameInfo("Stats segments", SRC_POS));
00446 
00447   if(itsVisualCandidates.initialized())
00448     ofs->writeGray(itsVisualCandidates, "AG-STAT-CAND",
00449                    FrameInfo("Stats candidates", SRC_POS));
00450 
00451 }
00452 
00453 // ######################################################################
00454 void SimulationViewerStats::computeLAMStats(const Image<float> &img)
00455 {
00456 
00457   saveCompat(img,".final-lam.txt",-1);
00458 
00459   Image<float> lamr = rescale(img,itsSizeX,itsSizeY);
00460 
00461   itsMaskCount  = 0; itsLamCount = 0; itsOverlapCount = 0;
00462   itsTotalCount = 0;
00463 
00464   // Threshold the attention mask at 12.5%
00465   for(Image<float>::iterator litr = lamr.beginw();
00466       litr != lamr.endw(); litr++)
00467   {
00468     if(*litr > 32) itsLamCount++;
00469     itsTotalCount++;
00470   }
00471   saveAGMaskStats(lamr,"LAM");
00472 
00473 }
00474 
00475 // ######################################################################
00476 void SimulationViewerStats::computeAGStats(SimEventQueue& q)
00477 {
00478   // Do we have attention gate output
00479   if (SeC<SimEventAttentionGateOutput> ag =
00480       q.check<SimEventAttentionGateOutput>(this))
00481   {
00482     Image<float> lam = ag->lam();
00483     saveCompat(lam,".final-lam.txt",-1);
00484     // Do we have a frame?
00485 
00486     //LINFO("Checking Frame");
00487     // get the mask if we havn't already
00488     if(!itsMask.initialized())
00489     {
00490       // Open the mask file
00491       const Image< PixRGB<byte> > cmask =
00492         Raster::ReadRGB(itsAGMaskFile.getVal());
00493 
00494       LINFO("Target Mask File Read %s",itsAGMaskFile.getVal().c_str());
00495 
00496       //Image<float> fmask = luminance(cmask);
00497       itsMask.resize(cmask.getWidth(),cmask.getHeight());
00498       Image<bool>::iterator mitr = itsMask.beginw();
00499       // Set mask usging a stepper to 1 or 0;
00500       for(Image<PixRGB<byte> >::const_iterator citr = cmask.begin();
00501           citr != cmask.end(); citr++)
00502       {
00503         // Above 90% gray
00504         if(citr->p[0] < 230) *mitr++ = true;
00505         else                 *mitr++ = false;
00506       }
00507 
00508       itsLamMask.resize(itsMask.getWidth(),itsMask.getHeight(),true);
00509       itsOverlap.resize(itsMask.getWidth(),itsMask.getHeight(),true);
00510     }
00511 
00512 
00513     // We are offset by one frame back in the AG
00514     // so we need to make sure we stay in sync
00515     if(itsMask.initialized())
00516     {
00517       LINFO("FRAME %d",itsFrameNumber);
00518       // Are we at the target frame + 1? or
00519       // are we outputing all frame overlaps?
00520       if((itsFrameNumber == (unsigned int)(itsAGTargetFrame.getVal() + 1)) ||
00521          ((itsAGTargetFrame.getVal() == 0) && (itsFrameIdx > 0)))
00522       {
00523 
00524         LINFO("Checking Mask file to target Attention Gate Frame %d",
00525               (itsFrameNumber + 1));
00526         // We need to compute basically how much of the mask and
00527         // the last attention gate overlap.
00528 
00529         // If the mask and attention gate never overlap, then the
00530         // target should never be seen. HOWEVER, if there is some
00531         // overlap, then whether the target is detected or not
00532         // may be more ambiguous.
00533 
00534         // resize lam to the mask size
00535         Image<float> lamr          = rescale(lam,itsMask.getWidth(),
00536                                              itsMask.getHeight());
00537         Image<bool>::iterator mitr = itsLamMask.beginw();
00538 
00539         // Threshold the attention mask at 25%
00540         for(Image<float>::iterator litr = lamr.beginw();
00541             litr != lamr.endw();
00542             litr++)
00543         {
00544           // threshold at 12.5%
00545           if(*litr > 32) *mitr++ = true;
00546           else           *mitr++ = false;
00547         }
00548 
00549         itsMaskCount  = 0; itsLamCount = 0; itsOverlapCount = 0;
00550         itsTotalCount = 0;
00551 
00552         Image<bool>::iterator aitr          = itsMask.beginw();
00553         Image<bool>::iterator litr          = itsLamMask.beginw();
00554         Image<PixRGB<byte> >::iterator oitr = itsOverlap.beginw();
00555 
00556         // count overlapped pixels as well as total pixels active in
00557         // each of the two maps
00558         while(litr != itsLamMask.endw())
00559         {
00560           if(*aitr++)
00561           {
00562             itsMaskCount++;
00563             if(*litr++)
00564             {
00565               itsLamCount++;
00566               itsOverlapCount++;
00567               *oitr++ = PixRGB<byte>(0,0,0);      // Union         = Black
00568             }
00569             else *oitr++ = PixRGB<byte>(255,0,0); // Mask Only     = Red
00570           }
00571           else if(*litr++)
00572           {
00573             itsLamCount++;
00574             *oitr++ = PixRGB<byte>(0,0,255);      // Att Gate Only = Blue
00575           }
00576           else
00577           {
00578             *oitr++ = PixRGB<byte>(255,255,255); // None           = White
00579           }
00580           itsTotalCount++;
00581         }
00582 
00583         //char filename[128];
00584         //sprintf(filename,"mask-AG%0'6d-union.png",(itsFrameIdx - 1));
00585         //Raster::WriteRGB(itsOverlap,filename);
00586 
00587         // Check constistancy of mask. Transparency in PNG can mess it up
00588         if(itsMaskCount      == itsTotalCount)
00589           LFATAL("Constancy Check failed for mask - Too Large!");
00590         else if(itsMaskCount == 0)
00591           LFATAL("Constancy Check failed for mask - Too Small!");
00592 
00593         saveAGMaskStats(lamr,"AG-MASK");
00594       }
00595     }
00596 
00597     // do we have segments from stage two?
00598     if (SeC<SimEventAttentionGateStageTwoSegments> agst =
00599         q.check<SimEventAttentionGateStageTwoSegments>(this))
00600     {
00601       LINFO("Getting Segments Image");
00602       const Image<int> segments = agst->obj().segments;
00603       Image<float> newSegments  = static_cast<Image<float> >(segments);
00604 
00605       float min,max,avg;
00606 
00607       getMinMaxAvg(newSegments,min,max,avg);
00608 
00609       LINFO("Segments min %f max %f",min,max);
00610 
00611       Image<PixHSV<float> > classImage;
00612 
00613       classImage.resize(segments.getWidth(),segments.getHeight());
00614 
00615       if((max-min) > 0.0f)
00616       {
00617         // Create a rainbow to show the classes  using HSV color space
00618         // 330 since 360 is red
00619         newSegments = ((newSegments - min) / (max - min)) * 300.0f;
00620 
00621         Image<PixHSV<float> >::iterator classImageItr = classImage.beginw();
00622 
00623         for(Image<float>::iterator segmentsItr = newSegments.beginw();
00624             segmentsItr != newSegments.endw(); ++segmentsItr)
00625        {
00626          classImageItr->p[0] = *segmentsItr;
00627          //LINFO("%f",*segmentsItr);
00628          classImageItr->p[1] = 100.0f;
00629          classImageItr->p[2] = 255.0f;
00630          ++classImageItr;
00631        }
00632 
00633         // convert back to RGB
00634         Image<PixRGB<float> > temp =
00635           static_cast<Image<PixRGB<float> > >(classImage);
00636 
00637         itsVisualSegments = temp;
00638       }
00639 
00640       const Image<bool> cand = agst->candidates();
00641       Image<float> newCand   = static_cast<Image<float> >(cand);
00642 
00643       newCand = newCand * 255.0f;
00644 
00645       itsVisualCandidates = newCand;
00646 
00647     }
00648   }
00649 }
00650 
00651 
00652 // ######################################################################
00653 void SimulationViewerStats::saveCompat(const Image<float>& img,
00654                                        const std::string suffix,
00655                                        const int frameOffset)
00656 {
00657 
00658 
00659   unsigned int frameIdx = (unsigned int)((int)itsFrameNumber + frameOffset);
00660 
00661   std::string fileName;
00662   std::string txt = suffix;
00663   fileName = itsGetSingleChannelStatsFile.getVal() + txt;
00664 
00665   ushort minx = 0, miny = 0, maxx = 0, maxy = 0;
00666   float  min,  max,  avg,  std;
00667   uint   N;
00668   // get a whole bunch of stats about this output image
00669   getMinMaxAvgEtc(img, min, max, avg, std, minx, miny, maxx, maxy, N);
00670 
00671   LINFO("SAVING COMPAT STATS TO %s",fileName.c_str());
00672 
00673   std::ofstream statsFile(fileName.c_str(), std::ios::app);
00674 
00675   statsFile << "final" << "\t";
00676 
00677   statsFile << frameIdx << "\t";
00678 
00679   // differentiate between scale image stats and the combined max norm
00680   // for compatability with single channel stats
00681 
00682   statsFile << "COMBINED\t-1\t";
00683   //itsFrameIdx++;
00684 
00685   statsFile << "final" << "\t" << "FINAL" << "\t";
00686   statsFile << min  << "\t" << max  << "\t" << avg  << "\t" << std  << "\t"
00687             << minx << "\t" << miny << "\t" << maxx << "\t" << maxy << "\t"
00688             << N    << "\n";
00689   statsFile.close();
00690 
00691   if(itsSaveStatsPerChannelFreq.getVal())
00692     {
00693       std::string txt = ".final.freq.txt";
00694       fileName = itsGetSingleChannelStatsFile.getVal() + txt;
00695 
00696       FFTWWrapper fft(img.getWidth(), img.getHeight());
00697       double dimg[img.getHeight() * img.getWidth()];
00698       Image<float>::const_iterator itr = img.begin();
00699       double *ditr = &dimg[0];
00700       while(itr != img.end()) *ditr++ = double(*itr++);
00701       fft.init(dimg);
00702       double mag[img.getHeight() * (img.getWidth()/2 + 1)];
00703       fft.compute(mag);
00704 
00705       std::ofstream freqFile(fileName.c_str(), std::ios::app);
00706       freqFile << "final" << "\t";
00707       freqFile << frameIdx << "\t";
00708 
00709       freqFile << "COMBINED\t-1\t";
00710 
00711       freqFile << "SIZE\t" << img.getWidth() <<"\t"<< img.getHeight() << "\n";
00712 
00713       for(int i = 0; i < img.getHeight(); i++)
00714         {
00715           for(int j = 0; j < (img.getWidth()/2 + 1); j++)
00716             freqFile << mag[i * (img.getWidth()/2 + 1) + j] << "\t";
00717           freqFile << "\n";
00718         }
00719       freqFile.close();
00720     }
00721 }
00722 
00723 // ######################################################################
00724 void SimulationViewerStats::saveAGMaskStats(const Image<float> &img,
00725                                             const std::string caller,
00726                                             const std::string suffix)
00727 {
00728 
00729   ushort minx = 0, miny = 0, maxx = 0, maxy = 0;
00730   float  min,  max,  avg,  std;
00731   uint   N;
00732   // get a whole bunch of stats about this output image
00733   getMinMaxAvgEtc(img, min, max, avg, std, minx, miny, maxx, maxy, N);
00734 
00735   std::string fileName;
00736   std::string txt = suffix;
00737   fileName = itsGetSingleChannelStatsFile.getVal() + txt;
00738 
00739   LINFO("SAVING AG STATS TO %s",fileName.c_str());
00740 
00741   std::ofstream statsFile(fileName.c_str(), std::ios::app);
00742 
00743   statsFile << "AGstats" << "\t";
00744 
00745   statsFile << (itsFrameNumber - 1) << "\t";
00746 
00747   // differentiate between scale image stats and the combined max norm
00748   // for compatability with single channel stats
00749 
00750   statsFile << "COMBINED\t" << caller << "\t";
00751   //itsFrameIdx++;
00752 
00753   statsFile << "final" << "\t" << "FINAL" << "\t";
00754   statsFile << itsTotalCount   << "\t"
00755             << itsMaskCount    << "\t"
00756             << itsLamCount     << "\t"
00757             << itsOverlapCount << "\t";
00758   statsFile << min  << "\t" << max  << "\t" << avg  << "\t" << std  << "\t"
00759             << minx << "\t" << miny << "\t" << maxx << "\t" << maxy << "\t"
00760             << N    << "\n";
00761 
00762   statsFile.close();
00763 }
00764 
00765 // ######################################################################
00766 /* So things look consistent in everyone's emacs... */
00767 /* Local Variables: */
00768 /* mode: c++ */
00769 /* indent-tabs-mode: nil */
00770 /* End: */
Generated on Sun May 8 08:05:26 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3