00001 /*!@file Parallel/SingleChannelBeoServer.C server to work with SingleChannelBeo */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 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/Parallel/SingleChannelBeoServer.C $ 00035 // $Id: SingleChannelBeoServer.C 8264 2007-04-17 21:43:10Z rjpeters $ 00036 // 00037 00038 #include "Parallel/SingleChannelBeoServer.H" 00039 00040 #include "Beowulf/Beowulf.H" 00041 #include "Beowulf/BeowulfOpts.H" 00042 #include "Channels/BlueYellowChannel.H" 00043 #include "Channels/ColorBandChannel.H" 00044 #include "Channels/DirectionChannel.H" 00045 #include "Channels/FlickerChannel.H" 00046 #include "Channels/GaborChannel.H" 00047 #include "Channels/IntensityChannel.H" 00048 #include "Channels/RedGreenChannel.H" 00049 #include "Channels/SingleChannel.H" 00050 #include "Component/OptionManager.H" 00051 #include "Component/ParamMap.H" 00052 #include "Image/PyramidTypes.H" 00053 #include "Neuro/SingleChannelBeo.H" // for the BEO_XXX message IDs 00054 #include "Neuro/VisualCortexSurprise.H" 00055 #include "Util/Assert.H" 00056 #include "Util/sformat.H" 00057 00058 #include <sstream> 00059 00060 // ###################################################################### 00061 SingleChannelBeoServer::SingleChannelBeoServer(OptionManager& mgr, 00062 const std::string& descrName, 00063 const std::string& tagName) : 00064 ModelComponent(mgr, descrName, tagName), 00065 itsQuickMode(&OPT_SingleChannelBeoServerQuickMode, this), 00066 itsBeo(new Beowulf(mgr)) 00067 { 00068 // get our Beowulf as a subcomponent: 00069 addSubComponent(itsBeo); 00070 00071 VisualCortexSurprise::registerSurpriseTypes(mgr); 00072 } 00073 00074 // ###################################################################### 00075 SingleChannelBeoServer::~SingleChannelBeoServer() 00076 { } 00077 00078 // ###################################################################### 00079 void SingleChannelBeoServer::check() 00080 { 00081 // See if we have a new message on our Beowulf: 00082 TCPmessage rmsg; 00083 int32 rframe, raction, rnode = -1; // receive from any node 00084 00085 if (itsBeo->receive(rnode, rmsg, rframe, raction, 50)) // wait up to 50ms 00086 switch(raction) { 00087 case BEO_INIT: // ########## Beowulf reset 00088 { 00089 // ooops, someone wants to re-initialize us! 00090 removeAllSubComponents(); // kill all our channels 00091 // reinitialization of beowulf is handled automatically. 00092 } 00093 break; 00094 case BEO_SCHANCONF: // ########## want to configure a new channel 00095 { 00096 // get the VisualFeature, channel index (if complex channel) 00097 // and the two ParamMaps out of the message: 00098 VisualFeature vs = static_cast<VisualFeature>(rframe); 00099 ParamMap params, coeffs; 00100 00101 const std::string dnam = rmsg.getElementString(); 00102 const std::string tnam = rmsg.getElementString(); 00103 00104 std::string buf = rmsg.getElementString(); 00105 std::stringstream sparam(buf); 00106 params.load(sparam); 00107 00108 buf = rmsg.getElementString(); 00109 std::stringstream scoeff(buf); 00110 coeffs.load(scoeff); 00111 00112 // do we already have a channel for this node? if so, destroy: 00113 nub::soft_ref<SingleChannel> ch = channel(rnode); 00114 if (ch.isValid()) 00115 { 00116 LINFO("Deleting '%s' of node %d", ch->descriptiveName().c_str(), 00117 rnode); 00118 ch->stop(); 00119 removeSubComponent(*ch); 00120 ch.reset(NULL); 00121 } 00122 00123 // let's instantiate the channel according to the 00124 // VisualFeature and descr/tag names. NOTE: for those that 00125 // take extra constructor args (e.g., OrientationChannel), we 00126 // put dummy default values here; they will be re-loaded from 00127 // the ParamMap anyway: 00128 switch(vs) 00129 { 00130 case INTENS: ch.reset(new IntensityChannel(getManager())); break; 00131 case BY: ch.reset(new BlueYellowChannel(getManager())); break; 00132 case RG: ch.reset(new RedGreenChannel(getManager())); break; 00133 case FLICKER: ch.reset(new FlickerChannel(getManager())); break; 00134 case COLBAND: ch.reset(new ColorBandChannel(getManager(), 0)); break; 00135 case ORI: ch.reset(new GaborChannel(getManager(),0, 0.0)); break; 00136 case MOTION: ch.reset(new DirectionChannel(getManager(), 0, 0.0, 00137 Gaussian9)); break; 00138 default: LFATAL("Unsupported VisualFeature %d", rframe); 00139 } 00140 00141 // set our channel's descriptive and tag names: 00142 ch->setDescriptiveName(dnam); 00143 ch->setTagName(tnam); 00144 00145 // let's configure the channel (we we need the correct tagName 00146 // for this to work, which is why we got it in our message): 00147 ch->readParamsFrom(params, false); // generate errors if params wrong 00148 00149 // let's now rename the channel with the requester's Beowulf 00150 // node number, so that we can later find it back using our 00151 // channel() function: 00152 ch->setTagName(sformat("%d", rnode)); 00153 00154 // let's start the channel: 00155 ch->start(); 00156 00157 // let's load the channel's submap coefficients: 00158 ch->readFrom(coeffs); 00159 00160 // let's add the channel as one of our subComponents: 00161 addSubComponent(ch); 00162 00163 // ready for some channel action! 00164 LINFO("Created '%s' for %s [node %d]", 00165 ch->descriptiveName().c_str(), itsBeo->nodeName(rnode), rnode); 00166 } 00167 break; 00168 case BEO_SCHANINPUT: // ########## some input to process 00169 { 00170 // do we have a channel for this node? 00171 nub::soft_ref<SingleChannel> ch = channel(rnode); 00172 if (ch.isInvalid()) 00173 LERROR("Input from node %d but no channel for it -- IGNORING",rnode); 00174 else 00175 { 00176 Timer tim(1000000); // let's keep track of how long we process 00177 Dims dims; // let's also report input size 00178 00179 // let's decode the message, do the processing and send 00180 // the output back: 00181 const double t = rmsg.getElementDouble(); 00182 Image<float> im = rmsg.getElementFloatIma(); 00183 Image<byte> cm = rmsg.getElementByteIma(); 00184 ch->input(InputFrame::fromGrayFloat(&im, SimTime::SECS(t), &cm)); 00185 dims = im.getDims(); 00186 00187 // send our results back: either just time and output (if 00188 // quick mode), or time, output, pyramid, submaps and 00189 // clipPyr (if not quick mode): 00190 TCPmessage msg(rframe, BEO_SCHANOUTPUT); 00191 if (itsQuickMode.getVal() == false) 00192 msg.reset(rframe, BEO_SCHANALLOUT); 00193 00194 msg.addDouble(t); 00195 00196 // getOutput() always works, possibly returning a blank 00197 // image if we have no output available: 00198 msg.addImage(ch->getOutput()); 00199 00200 if (itsQuickMode.getVal() == false) { 00201 // for the other internal maps, if we have an input 00202 // pyramid, then send the maps back, otherwise send 00203 // empty ImageSets back: 00204 if (ch->hasPyramid()) { 00205 msg.addImageSet(ch->pyramid(0)); 00206 00207 uint ns = ch->numSubmaps(); ImageSet<float> submaps(ns); 00208 for (uint i = 0; i < ns; i ++) submaps[i] = ch->getSubmap(i); 00209 msg.addImageSet(submaps); 00210 00211 msg.addImageSet(ch->clipPyramid()); 00212 } else { 00213 ImageSet<float> empty; 00214 msg.addImageSet(empty); // the pyramid 00215 msg.addImageSet(empty); // the submaps 00216 msg.addImageSet(empty); // the clipPyr 00217 } 00218 } 00219 00220 // send the results to our master: 00221 itsBeo->send(rnode, msg); 00222 LINFO("%sProcessed %dx%d input %d in %lluus", 00223 itsQuickMode.getVal()?"Quick":"", dims.w(), dims.h(), 00224 rframe, tim.get()); 00225 } 00226 } 00227 break; 00228 default: 00229 LERROR("Received unknown message from node %d -- IGNORING", rnode); 00230 } 00231 } 00232 00233 // ###################################################################### 00234 nub::soft_ref<SingleChannel> SingleChannelBeoServer::channel(const int32 node) 00235 { 00236 // convention used here: our channels have as tag name the number of 00237 // the node that requested them: 00238 const std::string name = sformat("%d", node); 00239 00240 nub::soft_ref<SingleChannel> chan; 00241 if (hasSubComponent(name)) dynCastWeakToFrom(chan, subComponent(name)); 00242 00243 return chan; 00244 } 00245 00246 // ###################################################################### 00247 /* So things look consistent in everyone's emacs... */ 00248 /* Local Variables: */ 00249 /* indent-tabs-mode: nil */ 00250 /* End: */