00001 /*!@file AppNeuro/test-intChannel.C */ 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/AppNeuro/test-intChannel.C $ 00035 // $Id: test-intChannel.C 11208 2009-05-20 02:03:21Z itti $ 00036 // 00037 00038 #ifndef APPNEURO_TEST_INTCHANNEL_C_DEFINED 00039 #define APPNEURO_TEST_INTCHANNEL_C_DEFINED 00040 00041 #include "Channels/BlueYellowChannel.H" 00042 #include "Channels/ChannelOpts.H" 00043 #include "Channels/ColorChannel.H" 00044 #include "Channels/DirectionChannel.H" 00045 #include "Channels/FlickerChannel.H" 00046 #include "Channels/GaborChannel.H" 00047 #include "Channels/IntegerInput.H" 00048 #include "Channels/IntegerMathEngine.H" 00049 #include "Channels/IntegerOrientationChannel.H" 00050 #include "Channels/IntegerSimpleChannel.H" 00051 #include "Channels/IntensityChannel.H" 00052 #include "Channels/MotionChannel.H" 00053 #include "Channels/OrientationChannel.H" 00054 #include "Channels/RedGreenChannel.H" 00055 #include "Channels/SingleChannel.H" 00056 #include "Component/ModelManager.H" 00057 #include "Component/ModelOptionDef.H" 00058 #include "Image/ColorOps.H" 00059 #include "Image/Image.H" 00060 #include "Image/ImageSet.H" 00061 #include "Image/IntegerMathOps.H" 00062 #include "Image/MathOps.H" 00063 #include "Image/Pixels.H" 00064 #include "Image/PyrBuilder.H" 00065 #include "Image/PyramidCache.H" 00066 #include "Image/PyramidOps.H" 00067 #include "Image/ShapeOps.H" 00068 #include "Media/FrameSeries.H" 00069 #include "Neuro/NeuroOpts.H" 00070 #include "Channels/RawVisualCortex.H" 00071 #include "Channels/IntegerRawVisualCortex.H" 00072 #include "Raster/GenericFrame.H" 00073 #include "Raster/Raster.H" 00074 #include "Transport/FrameInfo.H" 00075 #include "Util/Pause.H" 00076 #include "Util/csignals.H" 00077 #include "rutz/time.h" 00078 00079 #include <map> 00080 00081 static const ModelOptionDef OPT_ALIASsaveall = 00082 { MODOPT_ALIAS, "ALIASsaveall", &MOC_DISPLAY, OPTEXP_SAVE, 00083 "Default save option for test-intChannel", 00084 "saveall", '\0', "", 00085 "--save-channel-outputs --save-vcx-output" }; 00086 00087 namespace 00088 { 00089 struct ChannelCorrcoefData 00090 { 00091 ChannelCorrcoefData() : sum(0.0), n(0) {} 00092 00093 void add(double d) { sum += d; ++n; } 00094 00095 double sum; 00096 int n; 00097 }; 00098 00099 std::map<IntegerChannel*, ChannelCorrcoefData> ccdata; 00100 00101 void compareChannels(int c, 00102 IntegerChannel& ic, 00103 ChannelBase& fc) 00104 { 00105 IntegerComplexChannel* icc = 00106 dynamic_cast<IntegerComplexChannel*>(&ic); 00107 00108 if (icc != 0) 00109 { 00110 ComplexChannel* fcc = 00111 dynamic_cast<ComplexChannel*>(&fc); 00112 00113 ASSERT(icc->numChans() == fcc->numChans()); 00114 00115 for (uint i = 0; i < icc->numChans(); ++i) 00116 compareChannels(c, *(icc->subChan(i)), *(fcc->subChan(i))); 00117 } 00118 00119 float fmi, fma; getMinMax(fc.getOutput(), fmi, fma); 00120 int imi, ima; getMinMax(ic.getOutputInt(), imi, ima); 00121 00122 const double cc = corrcoef(fc.getOutput(), 00123 Image<float>(ic.getOutputInt())); 00124 LINFO("%06d corrcoef(%-20s,%-20s) = %.4f, " 00125 "frange = %.2e .. %.2e, irange = %.2e .. %.2e, imax/fmax = %.2e", 00126 c, fc.tagName().c_str(), ic.tagName().c_str(), cc, 00127 fmi, fma, float(imi), float(ima), float(ima) / fma); 00128 00129 ccdata[&ic].add(cc); 00130 } 00131 } 00132 00133 // ###################################################################### 00134 int submain(int argc, const char** argv) 00135 { 00136 volatile int signum = 0; 00137 catchsignals(&signum); 00138 00139 IntgTrigTable<256, 8> trig; 00140 00141 ModelManager manager("test-intChannel"); 00142 00143 OModelParam<IntegerDecodeType> decodeType 00144 (&OPT_IntInputDecode, &manager); 00145 00146 // Instantiate our various ModelComponents: 00147 nub::ref<InputFrameSeries> ifs(new InputFrameSeries(manager)); 00148 manager.addSubComponent(ifs); 00149 00150 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00151 manager.addSubComponent(ofs); 00152 00153 nub::ref<RawVisualCortex> fvc(new RawVisualCortex(manager)); 00154 manager.addSubComponent(fvc); 00155 00156 nub::ref<IntegerMathEngine> ieng(new IntegerMathEngine(manager)); 00157 manager.addSubComponent(ieng); 00158 00159 nub::ref<IntegerRawVisualCortex> ivc(new IntegerRawVisualCortex(manager, ieng)); 00160 manager.addSubComponent(ivc); 00161 00162 REQUEST_OPTIONALIAS_CHANNEL(manager); 00163 manager.requestOptionAlias(&OPT_ALIASsaveall); 00164 00165 manager.setOptionValString(&OPT_MaxNormType, "Maxnorm"); 00166 manager.setOptionValString(&OPT_DirectionChannelLowThresh, "0"); 00167 manager.setOptionValString(&OPT_IntChannelScaleBits, "16"); 00168 manager.setOptionValString(&OPT_IntMathLowPass5, "lp5optim"); 00169 manager.setOptionValString(&OPT_IntMathLowPass9, "lp9optim"); 00170 00171 // Parse command-line: 00172 if (manager.parseCommandLine(argc, argv, "?prof-only?", 0, 1) == false) 00173 return(1); 00174 00175 const bool profOnly = 00176 manager.numExtraArgs() > 0 ? manager.getExtraArgAs<bool>(0) : false; 00177 00178 manager.start(); 00179 00180 LINFO("using %u bits for integer arithmetic", ieng->getNbits()); 00181 00182 LINFO("using '%s' decoding algorithm", 00183 convertToString(decodeType.getVal()).c_str()); 00184 00185 int c = 0; 00186 00187 PauseWaiter p; 00188 00189 SimTime t; 00190 00191 rutz::time iruser, irsys, fruser, frsys; 00192 00193 PyramidCache<int> cache; 00194 00195 while (true) 00196 { 00197 if (signum != 0) 00198 { 00199 LINFO("quitting because %s was caught", signame(signum)); 00200 break; 00201 } 00202 00203 t += SimTime::HERTZ(30); 00204 00205 if (p.checkPause()) 00206 continue; 00207 00208 const FrameState is = ifs->updateNext(); 00209 if (is == FRAME_COMPLETE) 00210 break; 00211 00212 GenericFrame input = ifs->readFrame(); 00213 if (!input.initialized()) 00214 break; 00215 00216 const FrameState os = ofs->updateNext(); 00217 00218 rutz::time u1 = rutz::time::user_rusage(); 00219 rutz::time s1 = rutz::time::sys_rusage(); 00220 00221 const Image<PixRGB<byte> > rgb = input.asRgb(); 00222 00223 InputFrame finput = InputFrame::fromRgb(&rgb, t); 00224 00225 fvc->input(finput); 00226 00227 (void) fvc->getOutput(); 00228 00229 rutz::time u2 = rutz::time::user_rusage(); 00230 rutz::time s2 = rutz::time::sys_rusage(); 00231 00232 const IntegerInput ii = 00233 IntegerInput::decode(input, decodeType.getVal(), 00234 ieng->getNbits()); 00235 00236 ivc->inputInt(ii, t, &cache); 00237 00238 (void) ivc->getOutputInt(); 00239 00240 rutz::time u3 = rutz::time::user_rusage(); 00241 rutz::time s3 = rutz::time::sys_rusage(); 00242 00243 fruser += (u2 - u1); 00244 frsys += (s2 - s1); 00245 iruser += (u3 - u2); 00246 irsys += (s3 - s2); 00247 00248 if (!profOnly) 00249 { 00250 Image<float> frg, fby; 00251 const float lumthresh = 25.5f; 00252 getRGBY(finput.colorFloat(), frg, fby, lumthresh); 00253 00254 ofs->writeFrame(input, "input", 00255 FrameInfo("copy of input frame", SRC_POS)); 00256 00257 ofs->writeFloat(finput.grayFloat(), FLOAT_NORM_0_255, "fBW", 00258 FrameInfo("floating-point luminance", SRC_POS)); 00259 00260 ofs->writeFloat(frg, FLOAT_NORM_0_255, "fRG", 00261 FrameInfo("floating-point Red-Green", SRC_POS)); 00262 00263 ofs->writeFloat(fby, FLOAT_NORM_0_255, "fBY", 00264 FrameInfo("floating-point Blue-Yellow", SRC_POS)); 00265 00266 ofs->writeFloat(ii.grayInt(), FLOAT_NORM_0_255, "iBW", 00267 FrameInfo("fixed-point luminance", SRC_POS)); 00268 00269 ofs->writeFloat(ii.rgInt(), FLOAT_NORM_0_255, "iRG", 00270 FrameInfo("fixed-point Red-Green", SRC_POS)); 00271 00272 ofs->writeFloat(ii.byInt(), FLOAT_NORM_0_255, "iBY", 00273 FrameInfo("fixed-point Blue-Yellow", SRC_POS)); 00274 00275 fvc->saveResults(ofs); 00276 ivc->saveResults(ofs); 00277 00278 { 00279 const double cc = corrcoef(finput.grayFloat(), Image<float>(ii.grayInt())); 00280 LINFO("%06d corrcoef(fbw,ibw) = %.4f", c, cc); 00281 } 00282 00283 { 00284 const double cc = corrcoef(frg, Image<float>(ii.rgInt())); 00285 LINFO("%06d corrcoef(frg,irg) = %.4f", c, cc); 00286 } 00287 00288 { 00289 const double cc = corrcoef(fby, Image<float>(ii.byInt())); 00290 LINFO("%06d corrcoef(fby,iby) = %.4f", c, cc); 00291 } 00292 00293 if (fvc->hasSubChan("orientation") 00294 && ivc->hasSubChan("int-orientation")) 00295 { 00296 const ImageSet<float> fpyr = 00297 dyn_cast<OrientationChannel>(fvc->subChan("orientation"))->gabor(2).pyramid(0); 00298 const ImageSet<int> ipyr = 00299 dyn_cast<IntegerOrientationChannel>(ivc->subChan("int-orientation"))->gabor(2).intgPyramid(); 00300 00301 for (uint i = 0; i < fpyr.size(); ++i) 00302 if (fpyr[i].initialized()) 00303 ofs->writeFloat(fpyr[i], FLOAT_NORM_0_255, 00304 sformat("fpyr[%u]", i), 00305 FrameInfo(sformat("floating-point pyramid " 00306 "level %u of %u", i, 00307 fpyr.size()), SRC_POS)); 00308 00309 for (uint i = 0; i < ipyr.size(); ++i) 00310 if (ipyr[i].initialized()) 00311 ofs->writeFloat(Image<float>(ipyr[i]), FLOAT_NORM_0_255, 00312 sformat("ipyr[%u]", i), 00313 FrameInfo(sformat("integer pyramid " 00314 "level %u of %u", i, 00315 fpyr.size()), SRC_POS)); 00316 00317 for (uint i = 0; i < fpyr.size(); ++i) 00318 if (fpyr[i].initialized()) 00319 { 00320 const double cc = corrcoef(fpyr[i], Image<float>(ipyr[i])); 00321 LINFO("%06d pyr[%u] corrcoef = %.4f", c, i, cc); 00322 } 00323 } 00324 00325 compareChannels(c, *ivc, *fvc); 00326 } 00327 00328 if (os == FRAME_FINAL) 00329 break; 00330 00331 LDEBUG("frame %d", c); 00332 ++c; 00333 00334 if (ifs->shouldWait() || ofs->shouldWait()) 00335 Raster::waitForKey(); 00336 } 00337 00338 manager.stop(); 00339 00340 for (std::map<IntegerChannel*, ChannelCorrcoefData>::const_iterator 00341 itr = ccdata.begin(), stop = ccdata.end(); 00342 itr != stop; ++itr) 00343 { 00344 LINFO("AVG corrcoef(%-20s) = %.4f", 00345 (*itr).first->tagName().c_str(), 00346 (*itr).second.sum / (*itr).second.n); 00347 } 00348 00349 LINFO("floating-point code: %.3es user + %.3es sys (%.3fms per frame)", 00350 fruser.sec(), frsys.sec(), 00351 c <= 0 ? 0.0 : (fruser.msec() + frsys.msec()) / c); 00352 LINFO("integer code: %.3es user + %.3es sys (%.3fms per frame)", 00353 iruser.sec(), irsys.sec(), 00354 c <= 0 ? 0.0 : (iruser.msec() + irsys.msec()) / c); 00355 00356 if (iruser.sec() + irsys.sec() > 0.0) 00357 LINFO("floating-point/integer runtime ratio: %.2f", 00358 (fruser.sec() + frsys.sec()) / (iruser.sec() + irsys.sec())); 00359 00360 return 0; 00361 } 00362 00363 int main(const int argc, const char **argv) 00364 { 00365 try 00366 { 00367 return submain(argc, argv); 00368 } 00369 catch (...) 00370 { 00371 REPORT_CURRENT_EXCEPTION; 00372 } 00373 00374 return 1; 00375 } 00376 00377 // ###################################################################### 00378 /* So things look consistent in everyone's emacs... */ 00379 /* Local Variables: */ 00380 /* mode: c++ */ 00381 /* indent-tabs-mode: nil */ 00382 /* End: */ 00383 00384 #endif // APPNEURO_TEST_INTCHANNEL_C_DEFINED