00001 /*!@file Neuro/SimulationViewerRecStats.C View/save a bunch of recognition 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/SimulationViewerRecStats.C $ 00035 // $Id: SimulationViewerRecStats.C 13065 2010-03-28 00:01:00Z itti $ 00036 // 00037 00038 #include "Neuro/SimulationViewerRecStats.H" 00039 #include "Image/colorDefs.H" 00040 #include "Image/CutPaste.H" 00041 #include "Image/DrawOps.H" 00042 #include "Image/ImageSet.H" 00043 #include "Image/MathOps.H" 00044 #include "Neuro/Brain.H" 00045 #include "Neuro/NeuroOpts.H" 00046 #include "Neuro/NeuroSimEvents.H" 00047 #include "Neuro/VisualCortex.H" 00048 #include "Transport/FrameInfo.H" 00049 #include "Transport/FrameOstream.H" 00050 #include "Media/MediaSimEvents.H" 00051 #include <fcntl.h> // for open() 00052 #include <cerrno> // for errno 00053 00054 00055 // ###################################################################### 00056 SimulationViewerRecStats::SimulationViewerRecStats(OptionManager& mgr, 00057 const std::string& descrName, 00058 const std::string& tagName) : 00059 SimulationViewer(mgr, descrName, tagName), 00060 SIMCALLBACK_INIT(SimEventWTAwinner), 00061 itsStatsFname(&OPT_SVstatsFname, this), 00062 itsUseStatsFile(false), 00063 itsStatsFile(NULL), 00064 totalRec(0), //the total number we processed 00065 totalRecScenes(0), //the total scenes recognized 00066 totalRecObj(0) //the total obj recognized 00067 { } 00068 00069 // ###################################################################### 00070 SimulationViewerRecStats::~SimulationViewerRecStats() 00071 { } 00072 00073 // ###################################################################### 00074 void SimulationViewerRecStats::start2() 00075 { 00076 // initialize our stats dump file if desired: 00077 if (itsStatsFname.getVal().size()) 00078 { 00079 itsStatsFile = new std::ofstream(itsStatsFname.getVal().c_str()); 00080 if (itsStatsFile->is_open() == false) 00081 LFATAL("Failed to open '%s' for writing.", 00082 itsStatsFname.getVal().c_str()); 00083 itsUseStatsFile = true; 00084 } 00085 } 00086 00087 // ###################################################################### 00088 void SimulationViewerRecStats::stop2() 00089 { 00090 // close our stats file if we have one: 00091 if (itsStatsFile) 00092 { 00093 itsStatsFile->flush(); 00094 itsStatsFile->close(); 00095 delete itsStatsFile; 00096 itsStatsFile = NULL; 00097 } 00098 } 00099 00100 // ##################################################################### 00101 void SimulationViewerRecStats::lockFile(const std::string fileName, 00102 int &fd, 00103 struct flock &fl) const 00104 { 00105 // lock file 00106 fd = open(fileName.c_str(), O_RDWR); 00107 if (fd < 0) 00108 { 00109 LINFO("lockFile: Open failure on file %s",fileName.c_str()); 00110 } 00111 else 00112 { 00113 fl.l_type = F_WRLCK; 00114 fl.l_whence = SEEK_SET; 00115 fl.l_start = 0; 00116 fl.l_len = 0; 00117 if (fcntl(fd, F_SETLK, &fl) == -1) 00118 { 00119 if (errno == EACCES || errno == EAGAIN) 00120 LINFO("'%s' Already locked by another process",fileName.c_str()); 00121 else if(errno == EBADF) 00122 LINFO("'%s' not a valid open file descriptor",fileName.c_str()); 00123 else if(errno == EINVAL) 00124 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()); 00125 else if(errno == EMFILE) 00126 LINFO("'%s' process has already reached its maximum number of file descriptors",fileName.c_str()); 00127 else 00128 LINFO("Cannot lock file '%s' Error code '%d' \(Is this an NFS mount?)",fileName.c_str(),errno); 00129 } 00130 } 00131 } 00132 00133 // ##################################################################### 00134 void SimulationViewerRecStats::unlockFile(const std::string fileName, 00135 const int fd, 00136 struct flock &fl) const 00137 { 00138 // unlockfile 00139 fl.l_type = F_UNLCK; 00140 fl.l_whence = SEEK_SET; 00141 fl.l_start = 0; 00142 fl.l_len = 0; 00143 if (fcntl(fd, F_SETLK, &fl) == -1) 00144 { 00145 LINFO("Cannot unlock file '%s'",fileName.c_str()); 00146 } 00147 close(fd); 00148 } 00149 00150 // ###################################################################### 00151 void SimulationViewerRecStats:: 00152 onSimEventWTAwinner(SimEventQueue& q, rutz::shared_ptr<SimEventWTAwinner>& e) 00153 { 00154 // Lock the file. We put this here to support multi-process in the 00155 // future. However, this will not work on NFS mounts. 00156 struct flock fl; int fd; 00157 00158 if(itsUseStatsFile) lockFile(itsStatsFname.getVal().c_str(),fd,fl); 00159 00160 double maxProb = 0.0F, normProb = 0.0F; 00161 00162 totalRec++; 00163 //Get the predicted results 00164 std::string predSceneDescription; 00165 std::string predObjName; 00166 // any new input about the scene type 00167 if (SeC<SimEventSceneDescription> ee = q.check<SimEventSceneDescription>(this)) 00168 predSceneDescription = ee->getSceneData()->description; 00169 00170 // any new input about the object type 00171 if (SeC<SimEventObjectDescription> ee = q.check<SimEventObjectDescription>(this)) 00172 { 00173 predObjName = ee->getObjData()->name; 00174 maxProb = ee->getObjData()->maxProb; 00175 normProb = ee->getObjData()->normProb; 00176 } 00177 00178 LINFO("Predicted: scene: %s object: %s", 00179 predSceneDescription.c_str(), 00180 predObjName.c_str()); 00181 00182 00183 //Get the ground truth 00184 rutz::shared_ptr<TestImages::SceneData> sceneData; 00185 //Get the scene data, but dont mark it so we will get it on the next saccade 00186 if (SeC<SimEventInputFrame> ee = q.check<SimEventInputFrame>(this,SEQ_UNMARKED,0)) 00187 { 00188 GenericFrame gf = ee->frame(); 00189 rutz::shared_ptr<GenericFrame::MetaData> metaData = gf.getMetaData(std::string("SceneData")); 00190 if (metaData.get() != 0) 00191 sceneData.dyn_cast_from(metaData); 00192 } 00193 00194 if (sceneData.get() != 0) 00195 { 00196 std::string objName = getObjNameAtLoc(sceneData->objects, e->winner().p); 00197 LINFO("Labeled: scene: %s object: %s", 00198 sceneData->description.c_str(), 00199 objName.c_str()); 00200 00201 if (sceneData->description == predSceneDescription) 00202 totalRecScenes++; 00203 00204 if (objName == predObjName) 00205 totalRecObj++; 00206 00207 LINFO("Recognition Rate: Scene %lu/%lu=%0.2f Object %lu/%lu=%0.2f", 00208 totalRecScenes, totalRec, (float)totalRecScenes/(float)totalRec, 00209 totalRecObj, totalRec, (float)totalRecObj/(float)totalRec); 00210 00211 if(itsUseStatsFile) 00212 { 00213 // print a header 00214 if(totalRec == 1) 00215 (*itsStatsFile) << "Total\tCorrect\tPredicted\tLabeled\tPercent\tmaxProb\tnormProb\n"; 00216 00217 (*itsStatsFile) << sceneData->filename << "\t" 00218 << totalRec << "\t" 00219 << totalRecObj << "\t" 00220 << predObjName.c_str() << "\t" 00221 << objName.c_str() << "\t" 00222 << (float)totalRecObj/(float)totalRec << "\t" 00223 << maxProb << "\t" 00224 << normProb << "\n"; 00225 } 00226 } 00227 00228 if (SeC<SimEventObjectToBias> e = q.check<SimEventObjectToBias>(this,SEQ_UNMARKED,0)) 00229 { 00230 LINFO("Object To Bias: %s", e->name().c_str()); 00231 } 00232 00233 if(itsUseStatsFile) unlockFile(itsStatsFname.getVal().c_str(),fd,fl); 00234 } 00235 00236 // ###################################################################### 00237 std::string SimulationViewerRecStats:: 00238 getObjNameAtLoc(const std::vector<TestImages::ObjData> &objects, const Point2D<int>& loc) 00239 { 00240 00241 for(uint obj=0; obj<objects.size(); obj++) 00242 { 00243 TestImages::ObjData objData = objects[obj]; 00244 00245 LINFO("Checking Object %s in file %s",objData.name.c_str(),objData.filename.c_str()); 00246 00247 //find the object dimention from the polygon 00248 if (objData.polygon.size() > 0) 00249 { 00250 Point2D<int> upperLeft = objData.polygon[0]; 00251 Point2D<int> lowerRight = objData.polygon[0]; 00252 00253 for(uint i=0; i<objData.polygon.size(); i++) 00254 { 00255 //find the bounds for the crop 00256 if (objData.polygon[i].i < upperLeft.i) upperLeft.i = objData.polygon[i].i; 00257 if (objData.polygon[i].j < upperLeft.j) upperLeft.j = objData.polygon[i].j; 00258 00259 if (objData.polygon[i].i > lowerRight.i) lowerRight.i = objData.polygon[i].i; 00260 if (objData.polygon[i].j > lowerRight.j) lowerRight.j = objData.polygon[i].j; 00261 } 00262 00263 //check if point is within the polygon 00264 for(int y=upperLeft.j; y<lowerRight.j; y++) 00265 for(int x=upperLeft.i; x<lowerRight.i; x++) 00266 { 00267 if (pnpoly(objData.polygon, loc)) 00268 return objData.name; 00269 } 00270 } 00271 00272 } 00273 return std::string("Unknown"); 00274 } 00275 00276 // ###################################################################### 00277 /* So things look consistent in everyone's emacs... */ 00278 /* Local Variables: */ 00279 /* mode: c++ */ 00280 /* indent-tabs-mode: nil */ 00281 /* End: */