00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Channels/DirectFeedChannel.H"
00039
00040 #include "Channels/ChannelOpts.H"
00041 #include "Component/OptionManager.H"
00042 #include "Image/ShapeOps.H"
00043 #include "Util/Assert.H"
00044 #include "Util/MathFunctions.H"
00045 #include "Util/StringConversions.H"
00046 #include "Util/sformat.H"
00047
00048
00049 DirectFeedChannel::DirectFeedChannel(OptionManager& mgr, int id)
00050 : ChannelBase(mgr, "DirectFeed", "DirectFeed", DIRECTFEED),
00051 itsMapLevel(&OPT_MapLevel, this),
00052 itsNormType(&OPT_MaxNormType, this),
00053 itsUseOlderVersion(&OPT_UseOlderVersion, this),
00054 itsOutputRangeMin(&OPT_ChannelOutputRangeMin, this),
00055 itsOutputRangeMax(&OPT_ChannelOutputRangeMax, this)
00056 {
00057 if (id >= 0)
00058 {
00059 std::string name("DirectFeed_No_");
00060 name += toStr(id);
00061 setTagName(name);
00062 setDescriptiveName(name);
00063 }
00064 }
00065
00066
00067 DirectFeedChannel::~DirectFeedChannel()
00068 {}
00069
00070
00071 void DirectFeedChannel::start1()
00072 {
00073
00074
00075 if (itsUseOlderVersion.getVal() == false)
00076 {
00077 itsOutputRangeMin.setVal(0.0f);
00078 itsOutputRangeMax.setVal(0.0f);
00079 }
00080
00081
00082
00083
00084
00085 if (itsUseOlderVersion.getVal() && itsNormType.getVal() != VCXNORM_MAXNORM)
00086 {
00087 itsOutputRangeMin.setVal(0.0f);
00088 itsOutputRangeMax.setVal(0.0f);
00089 }
00090 }
00091
00092
00093 void DirectFeedChannel::reset1()
00094 {
00095 itsMapDims = Dims();
00096 itsPyr.reset();
00097 itsInputTime = SimTime::ZERO();
00098 itsPyrTime = SimTime::SECS(-1.0);
00099 itsCoeff.clear();
00100 itsOutputCache.freeMem();
00101
00102 ChannelBase::reset1();
00103 }
00104
00105
00106 void DirectFeedChannel::readFrom(const ParamMap& pmap)
00107 {
00108
00109 ChannelBase::readFrom(pmap);
00110 }
00111
00112
00113 void DirectFeedChannel::writeTo(ParamMap& pmap) const
00114 {
00115
00116 ChannelBase::writeTo(pmap);
00117 }
00118
00119
00120 void DirectFeedChannel::clampCoeffs(const double cmin, const double cmax)
00121 {
00122 killCaches();
00123 for (uint i = 0; i < itsCoeff.size(); ++i)
00124 itsCoeff[i] = clampValue(itsCoeff[i], cmin, cmax);
00125 }
00126
00127
00128 double DirectFeedChannel::absSumCoeffs() const
00129 {
00130 double sum = 0.0;
00131 for (uint i = 0; i < itsCoeff.size(); ++i)
00132 sum += std::abs(itsCoeff[i]);
00133 return sum;
00134 }
00135
00136
00137 void DirectFeedChannel::normalizeCoeffs(const double div)
00138 {
00139 killCaches();
00140 for (uint i = 0; i < itsCoeff.size(); ++i)
00141 itsCoeff[i] /=div;
00142 }
00143
00144
00145 void DirectFeedChannel::setCoeff(const uint idx, const double val)
00146 {
00147 if (itsPyr.isEmpty()) initializeCoeffs(idx+1,1.0);
00148 else ASSERT(idx < numSubmaps());
00149
00150 killCaches();
00151 itsCoeff[idx] = val;
00152 }
00153
00154
00155 double DirectFeedChannel::getCoeff(const uint idx) const
00156 {
00157 ASSERT(idx < numSubmaps());
00158 return itsCoeff[idx];
00159 }
00160
00161
00162 void DirectFeedChannel::initializeCoeffs(const uint numCoeffs,
00163 const double val)
00164 {
00165 itsCoeff.resize(numCoeffs,val);
00166 }
00167
00168
00169 void DirectFeedChannel::inputPyramid(const ImageSet<float>& pyramid,
00170 const SimTime& t)
00171 {
00172 if (itsCoeff.empty()) initializeCoeffs(pyramid.size());
00173 else ASSERT(itsCoeff.size() == pyramid.size());
00174
00175 itsPyr = pyramid;
00176 itsPyrTime = t;
00177 LDEBUG("itsPyrTime: %fms", itsPyrTime.msecs());
00178 }
00179
00180
00181 void DirectFeedChannel::doInput(const InputFrame& inframe)
00182 {
00183 if (inframe.grayFloat().initialized()) LINFO("using bwimg");
00184 else if (inframe.colorFloat().initialized()) LINFO("using colimg");
00185 else LFATAL("Need to have either colimg or bwimg as input!");
00186
00187 itsInputTime = inframe.time();
00188
00189 LDEBUG("itsInputTime: %fms", itsInputTime.msecs());
00190
00191 if (itsInputTime != itsPyrTime)
00192 LFATAL("I don't have any direct-feed input for time=%fms "
00193 "(last input was at time=%fms)",
00194 itsInputTime.msecs(), itsPyrTime.msecs());
00195
00196 const float fac = pow(0.5f,float(itsMapLevel.getVal()));
00197 itsMapDims = Dims(int(this->getInputDims().w()*fac),
00198 int(this->getInputDims().h()*fac));
00199 LDEBUG("itsMapDims = %s; itsInputDims = %s",toStr(itsMapDims).c_str(),
00200 toStr(this->getInputDims()).c_str());
00201 }
00202
00203
00204 bool DirectFeedChannel::outputAvailable() const
00205 {
00206 LDEBUG("itsPyrTime: %fms; itsInputTime: %fms",
00207 itsPyrTime.msecs(), itsInputTime.msecs());
00208 return (itsInputTime == itsPyrTime);
00209 }
00210
00211
00212 Dims DirectFeedChannel::getMapDims() const
00213 { return itsMapDims; }
00214
00215
00216 uint DirectFeedChannel::numSubmaps() const
00217 { return itsPyr.size(); }
00218
00219
00220 Image<float> DirectFeedChannel::getSubmap(const uint index) const
00221 {
00222 ASSERT(index < numSubmaps());
00223 return itsPyr[index];
00224 }
00225
00226
00227 std::string DirectFeedChannel::getSubmapName(const uint index) const
00228 {
00229 ASSERT(index < numSubmaps());
00230 return sformat("%s lev: %d", descriptiveName().c_str(),index);
00231 }
00232
00233
00234 void DirectFeedChannel::getFeatures(const Point2D<int>& locn,
00235 std::vector<float>& mean) const
00236 {
00237
00238 LFATAL("Not implemented yet.");
00239 }
00240
00241
00242 Image<float> DirectFeedChannel::getOutput()
00243 {
00244 ASSERT(itsInputTime == itsPyrTime);
00245 if (!itsOutputCache.initialized()) computeOutput();
00246 return itsOutputCache;
00247 }
00248
00249
00250
00251 void DirectFeedChannel::computeOutput()
00252 {
00253 ASSERT(itsInputTime == itsPyrTime);
00254 Image<float> output(getMapDims(),ZEROS);
00255
00256 for (uint i = 0; i < itsPyr.size(); ++i)
00257 {
00258 Image<float> submap = rescale(itsPyr[i], getMapDims());
00259 applyMaxNorm(submap);
00260 output += (submap * itsCoeff[i]);
00261 }
00262 itsOutputCache = applyMaxNorm(output);
00263 }
00264
00265
00266
00267 Image<float> DirectFeedChannel::applyMaxNorm(Image<float>& map)
00268 {
00269 ASSERT(map.initialized());
00270 map = maxNormalize(map, itsOutputRangeMin.getVal(),
00271 itsOutputRangeMax.getVal(),
00272 itsNormType.getVal());
00273 return map;
00274 }
00275
00276
00277 void DirectFeedChannel::killCaches()
00278 {
00279 itsOutputCache.freeMem();
00280 itsPyrTime = SimTime::SECS(-1.0);
00281 }
00282
00283
00284
00285
00286
00287
00288
00289 MultiDirectFeedChannel::MultiDirectFeedChannel(OptionManager& mgr,
00290 uint num)
00291 : ComplexChannel(mgr,"MultiDirectFeed","MultiDirectFeed",MULTIDIRECTFEED)
00292 {
00293 setNumChans(num);
00294 }
00295
00296 MultiDirectFeedChannel::~MultiDirectFeedChannel()
00297 {}
00298
00299
00300 void MultiDirectFeedChannel::setNumChans(uint num)
00301 {
00302 if (num == 0) LFATAL("Need at least one subchannel.");
00303
00304
00305 if (num == numChans()) return;
00306
00307
00308 if (num > numChans())
00309 for (uint i = numChans(); i < num; ++i)
00310 addSubChan(makeSharedComp(new DirectFeedChannel(getManager(),i)));
00311
00312
00313 else
00314 for (uint i = numChans()-1; i >= num; --i)
00315 removeSubComponent(i);
00316 }
00317
00318
00319 void MultiDirectFeedChannel::inputPyramid(uint chanNum,
00320 const ImageSet<float>& pyramid,
00321 const SimTime& t)
00322 {
00323 ASSERT(chanNum < numChans());
00324 directFeed(chanNum).inputPyramid(pyramid,t);
00325 }
00326
00327
00328 void MultiDirectFeedChannel::inputPyramidVector(const PyrVec& pvec,
00329 const SimTime& t)
00330 {
00331 ASSERT (pvec.size() == numChans());
00332 for (uint i = 0; i < numChans(); ++i)
00333 inputPyramid(i,pvec[i],t);
00334 }
00335
00336
00337 DirectFeedChannel& MultiDirectFeedChannel::directFeed(uint idx)
00338 {
00339 ASSERT(idx < numChans());
00340 return *(dynCast<DirectFeedChannel>(subChan(idx)));
00341 }
00342
00343
00344
00345 Image<float> MultiDirectFeedChannel::combineOutputs()
00346 {
00347 ASSERT(numChans() > 0);
00348
00349 if (numChans() == 1) return directFeed(0).getOutput();
00350
00351 Image<float> output(getMapDims(),ZEROS);
00352
00353 for (uint i = 0; i < numChans(); ++i)
00354 output += directFeed(i).getOutput();
00355
00356 return maxNormalize(output, itsOutputRangeMin.getVal(),
00357 itsOutputRangeMax.getVal(),
00358 itsNormType.getVal());
00359 }
00360
00361
00362
00363 void MultiDirectFeedChannel::doInput(const InputFrame& inframe)
00364 {
00365 ASSERT(inframe.colorFloat().initialized()
00366 || inframe.grayFloat().initialized());
00367 for (uint i = 0; i < numChans(); ++i)
00368 directFeed(i).input(inframe);
00369 }
00370
00371
00372
00373
00374
00375
00376