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 #ifndef CHANNELS_INTEGERSIMPLECHANNEL_C_DEFINED
00039 #define CHANNELS_INTEGERSIMPLECHANNEL_C_DEFINED
00040
00041 #include "Channels/IntegerSimpleChannel.H"
00042
00043 #include "Channels/ChannelOpts.H"
00044 #include "Component/GlobalOpts.H"
00045 #include "Component/ModelOptionDef.H"
00046 #include "Image/Image.H"
00047 #include "Image/ImageSetOps.H"
00048 #include "Image/IntegerMathOps.H"
00049 #include "Image/MathOps.H"
00050 #include "Image/PyrBuilder.H"
00051 #include "Transport/FrameInfo.H"
00052 #include "Transport/FrameOstream.H"
00053 #include "Util/Assert.H"
00054 #include "Util/log.H"
00055 #include "Util/sformat.H"
00056 #include "rutz/trace.h"
00057
00058 #include "Image/CutPaste.H"
00059 #include <cmath>
00060 #include <limits>
00061
00062 const int INTMAXNORMMIN = 0;
00063 const int INTMAXNORMMAX = 32768;
00064
00065
00066 IntegerSimpleChannel::
00067 IntegerSimpleChannel(OptionManager& mgr, const std::string& descrName,
00068 const std::string& tag,
00069 const VisualFeature vs,
00070 rutz::shared_ptr<PyrBuilder<int> > pbuild,
00071 nub::ref<IntegerMathEngine> eng) :
00072 IntegerChannel(mgr, descrName, tag, vs, eng),
00073 itsTakeAbs("IntegerSimpleChannelTakeAbs", this, false),
00074 itsNormalizeOutput("IntegerSimpleChannelNormalizeOutput", this, false),
00075 itsScaleNoiseToMax("IntegerSimpleChannelScaleNoiseToMax", this, false),
00076 itsLowThresh("IntegerSimpleChannelLowThresh", this, 0),
00077 itsRectifyPyramid("IntegerSimpleChannelRectifyPyramid", this, false),
00078 itsUseRandom(&OPT_UseRandom, this),
00079 itsLevelSpec(&OPT_LevelSpec, this),
00080 itsNormType(&OPT_MaxNormType, this),
00081 itsQlen(&OPT_SingleChannelQueueLen, this),
00082 itsUseOlderVersion(&OPT_UseOlderVersion, this),
00083 itsSaveRawMaps(&OPT_SingleChannelSaveRawMaps, this),
00084 itsSaveFeatureMaps(&OPT_SingleChannelSaveFeatureMaps, this),
00085 itsSaveOutputMap(&OPT_SingleChannelSaveOutputMap, this),
00086 itsOutputRangeMin(&OPT_IntChannelOutputRangeMin, this),
00087 itsOutputRangeMax(&OPT_IntChannelOutputRangeMax, this),
00088 itsPyr(),
00089 itsT(SimTime::ZERO()),
00090 itsOutputCache(),
00091 itsSubmapCache(NULL),
00092 itsPyrBuilder(pbuild),
00093 itsClipPyr()
00094 {
00095 GVX_TRACE(__PRETTY_FUNCTION__);
00096 }
00097
00098
00099 IntegerSimpleChannel::~IntegerSimpleChannel()
00100 {
00101 GVX_TRACE(__PRETTY_FUNCTION__);
00102 }
00103
00104
00105 void IntegerSimpleChannel::start1()
00106 {
00107 GVX_TRACE(__PRETTY_FUNCTION__);
00108 const int maxind = itsLevelSpec.getVal().maxIndex();
00109 itsSubmapCache = new Image<int>[maxind];
00110
00111
00112
00113 if (itsUseOlderVersion.getVal() == false)
00114 {
00115 itsOutputRangeMin.setVal(0);
00116 itsOutputRangeMax.setVal(0);
00117 }
00118
00119
00120
00121
00122
00123 if (itsUseOlderVersion.getVal() && itsNormType.getVal() != VCXNORM_MAXNORM)
00124 {
00125 itsOutputRangeMin.setVal(0);
00126 itsOutputRangeMax.setVal(0);
00127 }
00128
00129 if (itsPyrBuilder.get() == 0)
00130 LFATAL("Oops! I have no PyrBuilder!");
00131 }
00132
00133
00134 void IntegerSimpleChannel::stop2()
00135 {
00136 GVX_TRACE(__PRETTY_FUNCTION__);
00137 delete [] itsSubmapCache; itsSubmapCache = 0;
00138 }
00139
00140
00141 void IntegerSimpleChannel::reset1()
00142 {
00143 GVX_TRACE(__PRETTY_FUNCTION__);
00144
00145 itsPyrBuilder->reset();
00146 itsPyr.clear();
00147 itsClipPyr.clear();
00148 killCaches();
00149
00150
00151 IntegerChannel::reset1();
00152 }
00153
00154
00155 void IntegerSimpleChannel::readFrom(const ParamMap& pmap)
00156 {
00157 GVX_TRACE(__PRETTY_FUNCTION__);
00158
00159 if (!this->started())
00160 CLFATAL("must be start()-ed before using readFrom()");
00161
00162 IntegerChannel::readFrom(pmap);
00163 ChannelFacetMap::readFacetsFrom(pmap);
00164 }
00165
00166
00167 void IntegerSimpleChannel::writeTo(ParamMap& pmap) const
00168 {
00169 GVX_TRACE(__PRETTY_FUNCTION__);
00170
00171 if (!this->started())
00172 CLFATAL("must be start()-ed before using readFrom()");
00173
00174 IntegerChannel::writeTo(pmap);
00175 ChannelFacetMap::writeFacetsTo(pmap);
00176 }
00177
00178
00179 bool IntegerSimpleChannel::outputAvailable() const
00180 {
00181 GVX_TRACE(__PRETTY_FUNCTION__);
00182
00183 return (itsPyr.isEmpty() == false) || itsOutputCache.initialized();
00184 }
00185
00186
00187 Dims IntegerSimpleChannel::getMapDims() const
00188 {
00189 GVX_TRACE(__PRETTY_FUNCTION__);
00190 const int lev = itsLevelSpec.getVal().mapLevel();
00191
00192 return Dims(this->getInputDims().w() / (1 << lev),
00193 this->getInputDims().h() / (1 << lev));
00194 }
00195
00196
00197 uint IntegerSimpleChannel::numSubmaps() const
00198 {
00199 GVX_TRACE(__PRETTY_FUNCTION__);
00200 return itsLevelSpec.getVal().maxIndex();
00201 }
00202
00203
00204 Image<int> IntegerSimpleChannel::getSubmapInt(const uint i) const
00205 {
00206 GVX_TRACE(__PRETTY_FUNCTION__);
00207
00208 if (itsSubmapCache[i].initialized() == false)
00209 {
00210 itsSubmapCache[i] = this->getRawCSmapInt(i);
00211 uint clev = 0, slev = 0;
00212 itsLevelSpec.getVal().indexToCS(i, clev, slev);
00213
00214
00215
00216 if (itsSubmapCache[i].getWidth() > getMapDims().w())
00217 itsSubmapCache[i] = intgDownSize(itsSubmapCache[i], getMapDims(),
00218 9, this->getImath());
00219 else if (itsSubmapCache[i].getWidth() < getMapDims().w())
00220 itsSubmapCache[i] = intgRescale(itsSubmapCache[i], getMapDims());
00221
00222
00223 if (itsUseRandom.getVal())
00224 {
00225
00226 if (itsScaleNoiseToMax.getVal())
00227 {
00228 int fMin, fMax; getMinMax(itsSubmapCache[i], fMin, fMax);
00229 intgInplaceAddBGnoise(itsSubmapCache[i], fMax);
00230 }
00231 else
00232 intgInplaceAddBGnoise(itsSubmapCache[i],
00233 (1 << this->getImath()->nbits));
00234 }
00235
00236
00237
00238
00239 if (itsUseOlderVersion.getVal())
00240 {
00241 LDEBUG("%s(%d,%d): applying %s(%f .. %f)", tagName().c_str(), clev, slev,
00242 maxNormTypeName(itsNormType.getVal()), MAXNORMMIN, MAXNORMMAX);
00243 itsSubmapCache[i] =
00244 intgMaxNormalize(itsSubmapCache[i], INTMAXNORMMIN, INTMAXNORMMAX,
00245 itsNormType.getVal());
00246 }
00247 else
00248 {
00249 LDEBUG("%s(%d,%d): applying %s(0.0 .. 0.0)", tagName().c_str(),
00250 clev, slev, maxNormTypeName(itsNormType.getVal()));
00251 itsSubmapCache[i] =
00252 intgMaxNormalize(itsSubmapCache[i], 0, 0,
00253 itsNormType.getVal());
00254 }
00255
00256
00257 if (MYLOGVERB >= LOG_DEBUG)
00258 {
00259 int mi, ma; getMinMax(itsSubmapCache[i], mi, ma);
00260 LDEBUG("%s(%d,%d): final range [%d .. %d]",
00261 tagName().c_str(), clev, slev, mi, ma);
00262 }
00263 }
00264
00265 return itsSubmapCache[i];
00266 }
00267
00268
00269 Image<int> IntegerSimpleChannel::getRawCSmapInt(const uint idx) const
00270 {
00271 GVX_TRACE(__PRETTY_FUNCTION__);
00272 ASSERT(itsLevelSpec.getVal().indexOK(idx));
00273 if (itsPyr.isEmpty()) CLFATAL("I have no input pyramid yet!");
00274
00275
00276 uint clev = 0, slev = 0;
00277 itsLevelSpec.getVal().indexToCS(idx, clev, slev);
00278
00279
00280 const Image<int> submap =
00281 intgCenterSurround(itsPyr, clev, slev, itsTakeAbs.getVal(), &itsClipPyr);
00282
00283
00284 if (MYLOGVERB >= LOG_DEBUG)
00285 {
00286 int mi, ma; getMinMax(submap, mi, ma);
00287 LDEBUG("%s(%d,%d): raw range [%d .. %d]", tagName().c_str(),
00288 clev, slev, mi, ma);
00289 }
00290
00291 return submap;
00292 }
00293
00294
00295 std::string IntegerSimpleChannel::getSubmapName(const uint idx) const
00296 {
00297 GVX_TRACE(__PRETTY_FUNCTION__);
00298 ASSERT( itsLevelSpec.getVal().indexOK(idx) );
00299
00300 uint clev = 0, slev = 0;
00301 itsLevelSpec.getVal().indexToCS(idx, clev, slev);
00302
00303 return sformat("%s lev: %d delta: %d",
00304 descriptiveName().c_str(), clev, slev-clev);
00305 }
00306
00307
00308 std::string IntegerSimpleChannel::getSubmapNameShort(const uint idx) const
00309 {
00310 GVX_TRACE(__PRETTY_FUNCTION__);
00311 ASSERT( itsLevelSpec.getVal().indexOK(idx) );
00312
00313 uint clev = 0, slev = 0;
00314 itsLevelSpec.getVal().indexToCS(idx, clev, slev);
00315
00316 return sformat("%s(%d,%d)", tagName().c_str(), clev, slev);
00317 }
00318
00319
00320 void IntegerSimpleChannel::getFeatures(const Point2D<int>& locn,
00321 std::vector<float>& mean) const
00322 {
00323 CLFATAL("not implemented");
00324 }
00325
00326
00327 void IntegerSimpleChannel::getFeaturesBatch(std::vector<Point2D<int>*> *locn,
00328 std::vector<std::vector<float> > *mean,
00329 int *count) const
00330 {
00331 CLFATAL("not implemented");
00332 }
00333
00334
00335 void IntegerSimpleChannel::killCaches()
00336 {
00337 GVX_TRACE(__PRETTY_FUNCTION__);
00338 IntegerChannel::killCaches();
00339
00340 itsOutputCache.freeMem();
00341
00342
00343 if (started())
00344 for (uint i = 0; i < itsLevelSpec.getVal().maxIndex(); ++i)
00345 itsSubmapCache[i] = Image<int>();
00346 }
00347
00348
00349 void IntegerSimpleChannel::doInputInt(const IntegerInput& inp,
00350 const SimTime& t,
00351 PyramidCache<int>* cache,
00352 const Image<byte>& clipMask)
00353 {
00354 ASSERT(inp.grayInt().initialized());
00355
00356
00357 if (clipMask.initialized())
00358 {
00359 itsClipPyr = intgBuildPyrGaussian
00360 (intgScaleFromByte(&clipMask, this->getImath()->nbits),
00361 itsLevelSpec.getVal().maxDepth(), 9,
00362 this->getImath());
00363 intgDoLowThresh(itsClipPyr, 255, 0);
00364 }
00365 else
00366 itsClipPyr.clear();
00367
00368
00369 itsPyr = itsPyrBuilder->
00370 build(inp.grayInt(),
00371 this->getMinPyrLevel(), this->getMaxPyrLevel(), cache);
00372
00373
00374 if (itsLowThresh.getVal() > 0)
00375 {
00376 if (itsRectifyPyramid.getVal())
00377 intgDoLowThresh(itsPyr, itsLowThresh.getVal());
00378 else
00379 intgDoLowThreshAbs(itsPyr, itsLowThresh.getVal());
00380 }
00381 else if (itsRectifyPyramid.getVal())
00382 intgDoRectify(itsPyr);
00383
00384 itsT = t;
00385
00386
00387 ASSERT(isDyadic(itsPyr.subSet
00388 (this->getMinPyrLevel(), this->getMaxPyrLevel())));
00389 }
00390
00391
00392 LevelSpec IntegerSimpleChannel::getLevelSpec() const
00393 {
00394 GVX_TRACE(__PRETTY_FUNCTION__);
00395 return itsLevelSpec.getVal();
00396 }
00397
00398
00399 Image<int> IntegerSimpleChannel::getOutputInt()
00400 {
00401 GVX_TRACE(__PRETTY_FUNCTION__);
00402
00403 if (!this->hasInput())
00404
00405
00406 CLFATAL("Oops! can't get output -- I don't even have any input yet");
00407
00408 if (!this->outputAvailable())
00409 {
00410
00411
00412
00413
00414
00415
00416 LERROR("No %s channel yet! -- IGNORING.", this->tagName().c_str());
00417
00418 return Image<int>(this->getMapDims(), ZEROS);
00419 }
00420
00421 if (!itsOutputCache.initialized())
00422 {
00423 itsOutputCache = Image<int>(getMapDims(), ZEROS);
00424
00425
00426 for (uint idx = 0; idx < itsLevelSpec.getVal().maxIndex(); ++idx)
00427 {
00428 const Image<int> submap = getSubmapInt(idx);
00429
00430
00431 itsOutputCache += (submap / int(itsLevelSpec.getVal().maxIndex()));
00432
00433 if (MYLOGVERB >= LOG_DEBUG)
00434 {
00435 uint clev = 0, slev = 0;
00436 itsLevelSpec.getVal().indexToCS(idx, clev, slev);
00437 LDEBUG("%s(%d,%d): weight %f", tagName().c_str(), clev, slev, 1.0f);
00438 }
00439 }
00440
00441
00442
00443 if (itsNormalizeOutput.getVal())
00444 {
00445 LDEBUG("%s: Normalizing output: %s(%d .. %d)", tagName().c_str(),
00446 maxNormTypeName(itsNormType.getVal()), itsOutputRangeMin.getVal(),
00447 itsOutputRangeMax.getVal());
00448
00449 itsOutputCache =
00450 intgMaxNormalize(itsOutputCache, itsOutputRangeMin.getVal(),
00451 itsOutputRangeMax.getVal(), itsNormType.getVal());
00452 }
00453
00454
00455 if (MYLOGVERB >= LOG_DEBUG)
00456 {
00457 int mi, ma; getMinMax(itsOutputCache, mi, ma);
00458 LDEBUG("%s: final range [%d .. %d]", tagName().c_str(), mi, ma);
00459 }
00460
00461 LINFO("Computed %s Conspicuity Map", descriptiveName().c_str());
00462 }
00463
00464 return itsOutputCache;
00465 }
00466
00467
00468 uint IntegerSimpleChannel::csToIndex(const uint centerlev,
00469 const uint surroundlev) const
00470 {
00471 GVX_TRACE(__PRETTY_FUNCTION__);
00472 return itsLevelSpec.getVal().csToIndex(centerlev, surroundlev);
00473 }
00474
00475
00476 void IntegerSimpleChannel::saveResults(const nub::ref<FrameOstream>& ofs)
00477 {
00478 GVX_TRACE(__PRETTY_FUNCTION__);
00479
00480 if (itsPyr.isEmpty() == false)
00481 {
00482
00483 if (itsSaveRawMaps.getVal()) {
00484 for (uint i = 0; i < itsPyr.size(); i ++)
00485 ofs->writeFloat(Image<float>(itsPyr[i]), FLOAT_NORM_0_255,
00486 sformat("ISR%s-%d-", tagName().c_str(),i),
00487 FrameInfo(sformat("%s IntegerSimpleChannel raw map (%u of %u)",
00488 this->descriptiveName().c_str(),
00489 i, itsPyr.size()),
00490 SRC_POS));
00491 }
00492
00493
00494 if (itsSaveFeatureMaps.getVal())
00495 for (uint i = 0; i < numSubmaps(); i ++) {
00496 uint clev = 0, slev = 0;
00497 itsLevelSpec.getVal().indexToCS(i, clev, slev);
00498 ofs->writeFloat(Image<float>(getSubmapInt(i)),
00499 FLOAT_NORM_0_255,
00500 sformat("ISF%s-%d-%d-", tagName().c_str(),clev, slev),
00501 FrameInfo(sformat("%s IntegerSimpleChannel center-surround map (c=%u s=%u)",
00502 this->descriptiveName().c_str(),
00503 clev, slev),
00504 SRC_POS));
00505 }
00506 }
00507
00508
00509 if (itsSaveOutputMap.getVal())
00510 ofs->writeFloat(getOutput(), FLOAT_NORM_0_255,
00511 sformat("ISO%s-", tagName().c_str()),
00512 FrameInfo(sformat("%s IntegerSimpleChannel output",
00513 this->descriptiveName().c_str()),
00514 SRC_POS));
00515 }
00516
00517
00518 void IntegerSimpleChannel::setPyrBuilder(rutz::shared_ptr<PyrBuilder<int> > pbuild)
00519 {
00520 GVX_TRACE(__PRETTY_FUNCTION__);
00521
00522 ASSERT(pbuild.get() != 0);
00523 this->killCaches();
00524 itsPyrBuilder = pbuild;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534 #endif // CHANNELS_INTEGERSIMPLECHANNEL_C_DEFINED