00001 /*!@file Transport/StatsOutputSeries.C FrameOstream subclass that writes image statistics to an output file */ 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: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Transport/StatsOutputSeries.C $ 00035 // $Id: StatsOutputSeries.C 14290 2010-12-01 21:44:03Z itti $ 00036 // 00037 00038 #ifndef TRANSPORT_STATSOUTPUTSERIES_C_DEFINED 00039 #define TRANSPORT_STATSOUTPUTSERIES_C_DEFINED 00040 00041 #include "Transport/StatsOutputSeries.H" 00042 00043 #include "Image/ColorOps.H" 00044 #include "Image/Image.H" 00045 #include "Image/MathOps.H" 00046 #include "Image/Pixels.H" 00047 #include "Image/Range.H" 00048 #include "Raster/GenericFrame.H" 00049 #include "Util/FileUtil.H" 00050 00051 #include <cstdio> 00052 00053 template <class T> 00054 Range<T> getRange(const Image<T>& x) 00055 { 00056 Range<T> result; 00057 for (typename Image<T>::const_iterator 00058 itr = x.begin(), stop = x.end(); itr != stop; ++itr) 00059 result.merge(*itr); 00060 return result; 00061 } 00062 00063 struct StatsOutputSeries::Impl 00064 { 00065 Impl() 00066 : 00067 fileName(""), 00068 fileOwned(true), 00069 frameNumber(-1), 00070 file(0), 00071 meanR(0.0), 00072 meanG(0.0), 00073 meanB(0.0), 00074 count(0) 00075 {} 00076 00077 ~Impl() 00078 { 00079 if (this->file != 0) 00080 { 00081 fflush(this->file); 00082 00083 // we don't want to fclose() the file if the file is actually 00084 // stdout or stderr, so check this->fileOwned first: 00085 if (this->fileOwned) 00086 fclose(this->file); 00087 } 00088 } 00089 00090 void openFile() 00091 { 00092 if (this->file == 0) 00093 { 00094 this->file = stdOutputFileOpen(this->fileName, 00095 &this->fileOwned); 00096 00097 // ok, after all is said and done we should have a valid FILE* 00098 ASSERT(this->file != 0); 00099 } 00100 } 00101 00102 void printStatsRGB(const Image<PixRGB<byte> >& img, 00103 const std::string& imgname, const std::string& imgtype) 00104 { 00105 this->openFile(); 00106 00107 Image<byte> r, g, b; 00108 getComponents(img, r, g, b); 00109 00110 const double mean_r = mean(r); 00111 const double stdev_r = stdev(r); 00112 const Range<byte> range_r = getRange(r); 00113 00114 const double mean_g = mean(g); 00115 const double stdev_g = stdev(g); 00116 const Range<byte> range_g = getRange(g); 00117 00118 const double mean_b = mean(b); 00119 const double stdev_b = stdev(b); 00120 const Range<byte> range_b = getRange(b); 00121 00122 fprintf(this->file, 00123 "%06d " 00124 "R=[%d .. %f +/- %f .. %d] " 00125 "G=[%d .. %f +/- %f .. %d] " 00126 "B=[%d .. %f +/- %f .. %d] %% %s (%dx%d %s)\n", 00127 this->frameNumber, 00128 int(range_r.min()), mean_r, stdev_r, int(range_r.max()), 00129 int(range_g.min()), mean_g, stdev_g, int(range_g.max()), 00130 int(range_b.min()), mean_b, stdev_b, int(range_b.max()), 00131 imgname.c_str(), img.getWidth(), img.getHeight(), 00132 imgtype.c_str()); 00133 fflush(this->file); 00134 00135 this->rangeR.merge(range_r); 00136 this->rangeG.merge(range_g); 00137 this->rangeB.merge(range_b); 00138 00139 this->meanR += mean_r; 00140 this->meanG += mean_g; 00141 this->meanB += mean_b; 00142 ++(this->count); 00143 } 00144 00145 void printStatsSummary() 00146 { 00147 this->openFile(); 00148 00149 fprintf(this->file, 00150 "OVERALL " 00151 "R=[%d .. %f .. %d] " 00152 "G=[%d .. %f .. %d] " 00153 "B=[%d .. %f .. %d] %% summary of %d frames\n", 00154 int(rangeR.min()), meanR/count, int(rangeR.max()), 00155 int(rangeG.min()), meanG/count, int(rangeG.max()), 00156 int(rangeB.min()), meanB/count, int(rangeB.max()), 00157 count); 00158 fflush(this->file); 00159 } 00160 00161 std::string fileName; 00162 bool fileOwned; 00163 int frameNumber; 00164 FILE* file; 00165 00166 Range<byte> rangeR; 00167 Range<byte> rangeG; 00168 Range<byte> rangeB; 00169 double meanR; 00170 double meanG; 00171 double meanB; 00172 int count; 00173 }; 00174 00175 // ###################################################################### 00176 StatsOutputSeries::StatsOutputSeries(OptionManager& mgr) 00177 : 00178 FrameOstream(mgr, "Stats Output Series", "StatsOutputSeries"), 00179 rep(new Impl) 00180 {} 00181 00182 // ###################################################################### 00183 StatsOutputSeries::~StatsOutputSeries() 00184 { 00185 delete rep; 00186 } 00187 00188 // ###################################################################### 00189 void StatsOutputSeries::setConfigInfo(const std::string& filename) 00190 { 00191 // NOTE: if you modify any behavior here, then please update the 00192 // corresponding documentation for the global "--out" option inside 00193 // the OPT_OutputFrameSink definition in Media/MediaOpts.C 00194 00195 this->setFileName(filename); 00196 } 00197 00198 // ###################################################################### 00199 bool StatsOutputSeries::setFrameNumber(int n) 00200 { 00201 rep->frameNumber = n; 00202 00203 return true; 00204 } 00205 00206 // ###################################################################### 00207 void StatsOutputSeries::writeFrame(const GenericFrame& f, 00208 const std::string& shortname, 00209 const FrameInfo& auxinfo) 00210 { 00211 const std::string nm = shortname; 00212 const std::string tp = f.nativeTypeName(); 00213 00214 switch (f.nativeType()) 00215 { 00216 case GenericFrame::NONE: break; 00217 case GenericFrame::RGB_U8: rep->printStatsRGB(f.asRgbU8(),nm,tp); break; 00218 case GenericFrame::RGBD: rep->printStatsRGB(f.asRgbU8(),nm,tp); break; 00219 case GenericFrame::RGB_F32: rep->printStatsRGB(f.asRgbU8(),nm,tp); break; 00220 case GenericFrame::GRAY_U8: rep->printStatsRGB(f.asRgbU8(),nm,tp); break; 00221 case GenericFrame::GRAY_F32:rep->printStatsRGB(f.asRgbU8(),nm,tp); break; 00222 case GenericFrame::VIDEO: rep->printStatsRGB(f.asRgbU8(),nm,tp); break; 00223 case GenericFrame::RGB_U16: break; 00224 case GenericFrame::GRAY_U16: break; 00225 } 00226 } 00227 00228 // ###################################################################### 00229 void StatsOutputSeries::closeStream(const std::string& shortname) 00230 { 00231 /* nothing to see here, move along */ 00232 } 00233 00234 // ###################################################################### 00235 void StatsOutputSeries::setFileName(const std::string& s) 00236 { 00237 if (rep->file != 0) 00238 LFATAL("can't change filename while output file is already open"); 00239 00240 rep->fileName = s; 00241 } 00242 00243 // ###################################################################### 00244 void StatsOutputSeries::stop2() 00245 { 00246 rep->printStatsSummary(); 00247 } 00248 00249 // ###################################################################### 00250 /* So things look consistent in everyone's emacs... */ 00251 /* Local Variables: */ 00252 /* mode: c++ */ 00253 /* indent-tabs-mode: nil */ 00254 /* End: */ 00255 00256 #endif // TRANSPORT_STATSOUTPUTSERIES_C_DEFINED