00001 /*!@file Channels/JetFiller.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/Channels/JetFiller.C $ 00035 // $Id: JetFiller.C 9412 2008-03-10 23:10:15Z farhan $ 00036 // 00037 00038 #ifndef CHANNELS_JETFILLER_C_DEFINED 00039 #define CHANNELS_JETFILLER_C_DEFINED 00040 00041 #include "Channels/JetFiller.H" 00042 00043 #include "Channels/ComplexChannel.H" 00044 #include "Channels/SingleChannel.H" 00045 #include "Channels/VisualFeatures.H" 00046 #include "Image/PyramidOps.H" 00047 00048 // ###################################################################### 00049 JetFiller::JetFiller(const Point2D<int>& loc, Jet<float>& j, bool do_interp) 00050 : 00051 itsLoc(loc), 00052 itsJet(j), 00053 itsDoInterp(do_interp), 00054 itsIndex() 00055 {} 00056 00057 // ###################################################################### 00058 JetFiller::~JetFiller() 00059 {} 00060 00061 // ###################################################################### 00062 void JetFiller::visitChannelBase(ChannelBase& chan) 00063 { 00064 LFATAL("don't know how to handle %s", chan.tagName().c_str()); 00065 } 00066 00067 // ###################################################################### 00068 void JetFiller::visitSingleChannel(SingleChannel& chan) 00069 { 00070 if (chan.numPyramids() == 0) LFATAL("I have no input pyramid yet!"); 00071 00072 const LevelSpec ls = chan.getLevelSpec(); 00073 00074 // A trivial implementation would go as follows for the RAW case 00075 // (modulo some checking that the jet can accept the indices we 00076 // have): 00077 /* 00078 for (uint i = 0; i < ls.levMax() + ls.delMax(); i++) 00079 { 00080 float pix = getPyrPixel(itsPq.front().pyr, itsLoc, i); 00081 itsIndex.push_back(i); 00082 itsJet.setVal(pix, chan.visualFeature(), RAW, itsIndex); 00083 itsIndex.pop_back(); 00084 } 00085 */ 00086 00087 // The implementation below is slightly faster by minimizing the 00088 // number of Jet index computations, using only one getIndexV() call 00089 // and then raw Jet array accesses. But it is identical in spirit. 00090 int rmin, rmax; 00091 if (itsJet.getIndexRange(chan.visualFeature(), RAW, 00092 itsIndex.size(), rmin, rmax)) 00093 { 00094 itsIndex.push_back(rmin); // raw features use a single index 00095 int idx = itsJet.getSpec()->getIndexV(chan.visualFeature(), 00096 RAW, itsIndex); 00097 const int ns = int(ls.levMax() + ls.delMax()); 00098 const int first = std::max(rmin, 0); 00099 const int last = std::min(rmax, ns); 00100 00101 // We have data for scales [0..ns]; the Jet wants data for 00102 // scales [rmin..rmax] and we will put zeros in the Jet for all 00103 // Jet scales that it has but we don't have 00104 idx -= rmin; // offset to account for rmin 00105 for (int i = rmin; i < 0; ++i) 00106 itsJet.setVal(idx + i, 0.0f); 00107 00108 for (int i = first; i <= last; ++i) 00109 { 00110 const float pix = 00111 itsDoInterp 00112 ? getPyrPixel(chan.pyramid(0), itsLoc, i) 00113 : getPyrPixelNI(chan.pyramid(0), itsLoc, i); 00114 itsJet.setVal(idx + i, pix); 00115 } 00116 for (int i = ns + 1; i <= rmax; i ++) 00117 itsJet.setVal(idx + i, 0.0f); 00118 itsIndex.pop_back(); 00119 } 00120 00121 //FIXME: also do it for RAW_CS and NORM_CS 00122 } 00123 00124 // ###################################################################### 00125 void JetFiller::visitComplexChannel(ComplexChannel& chan) 00126 { 00127 if (chan.isHomogeneous()) 00128 { 00129 itsIndex.push_back(0); // add one index for the subchannels 00130 for (uint i = 0; i < chan.numChans(); ++i) 00131 { 00132 itsIndex.back() = int(i); 00133 chan.subChan(i)->accept(*this); 00134 } 00135 itsIndex.pop_back(); // restore itsIndex for parent to use again 00136 } 00137 else 00138 for (uint i = 0; i < chan.numChans(); ++i) 00139 chan.subChan(i)->accept(*this); 00140 } 00141 00142 // ###################################################################### 00143 JetSpecFiller::JetSpecFiller() 00144 : 00145 itsJetSpec(new JetSpec) 00146 {} 00147 00148 // ###################################################################### 00149 JetSpecFiller::~JetSpecFiller() 00150 {} 00151 00152 // ###################################################################### 00153 void JetSpecFiller::visitChannelBase(ChannelBase& chan) 00154 { 00155 LFATAL("don't know how to handle %s", chan.tagName().c_str()); 00156 } 00157 00158 // ###################################################################### 00159 void JetSpecFiller::visitSingleChannel(SingleChannel& chan) 00160 { 00161 const LevelSpec ls = chan.getLevelSpec(); 00162 00163 itsJetSpec->addIndexRange(chan.visualFeature(), RAW, 0, 00164 ls.levMax() + ls.delMax()); 00165 /* FIXME: FUTURE... 00166 itsJetSpec->addIndexRange(chan.visualFeature(), RAW_CS, 00167 ls.levMin(), 00168 ls.levMax()); 00169 itsJetSpec->addIndexRange(chan.visualFeature(), RAW_CS, 00170 ls.delMin(), 00171 ls.delMax()); 00172 itsJetSpec->addIndexRange(chan.visualFeature(), NORM_CS, 00173 ls.levMin(), 00174 ls.levMax()); 00175 itsJetSpec->addIndexRange(chan.visualFeature(), NORM_CS, 00176 ls.delMin(), 00177 ls.delMax()); 00178 */ 00179 } 00180 00181 // ###################################################################### 00182 void JetSpecFiller::visitComplexChannel(ComplexChannel& chan) 00183 { 00184 if (chan.numChans() > 0) 00185 { 00186 // are we a homogeneous complex channel? If so, add a range for 00187 // number of subchannels and initialize rest from first 00188 // subchannel 00189 if (chan.isHomogeneous()) 00190 { 00191 // create ranges for the number of subchannels we hold: 00192 itsJetSpec->addIndexRange(chan.visualFeature(), RAW, 0, chan.numChans() - 1); 00193 //itsJetSpec->addIndexRange(chan.visualFeature(), RAW_CS, 0, chan.numChans() - 1); 00194 //itsJetSpec->addIndexRange(chan.visualFeature(), NORM_CS, 0, chan.numChans() - 1); 00195 00196 // use the first subchannel to add the range specs for us: 00197 chan.subChan(0)->accept(*this); 00198 } 00199 else 00200 { 00201 // We are heterogeneous; each subchannel holds a different 00202 // VisualFeature; initialize all subchannels in turn, and we 00203 // do not have to do anything for us proper: 00204 for (uint i = 0; i < chan.numChans(); ++i) 00205 chan.subChan(i)->accept(*this); 00206 } 00207 } 00208 } 00209 00210 // ###################################################################### 00211 /* So things look consistent in everyone's emacs... */ 00212 /* Local Variables: */ 00213 /* mode: c++ */ 00214 /* indent-tabs-mode: nil */ 00215 /* End: */ 00216 00217 #endif // CHANNELS_JETFILLER_C_DEFINED