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 ORIENTATIONCHANNEL_C_DEFINED
00039 #define ORIENTATIONCHANNEL_C_DEFINED
00040
00041 #include "Channels/OrientationChannel.H"
00042
00043 #include "Channels/ChannelOpts.H"
00044 #include "Channels/GaborChannel.H"
00045 #include "Component/OptionManager.H"
00046 #include "Image/ImageSetOps.H"
00047 #include "Image/PyramidOps.H"
00048 #include "Image/PyramidCache.H"
00049 #include "rutz/mutex.h"
00050 #include "rutz/trace.h"
00051 #include "Util/sformat.H"
00052
00053 #include <cstdio>
00054
00055
00056
00057
00058
00059
00060 OrientationChannel::OrientationChannel(OptionManager& mgr) :
00061 ComplexChannel(mgr, "Orientation", "orientation", ORI),
00062 itsNumOrients(&OPT_NumOrientations, this),
00063 itsInteractString(&OPT_OriInteraction, this),
00064 itsInteractType(NONE),
00065 itsDidInteractions(false),
00066 itsOverideTagName(false)
00067 {
00068 GVX_TRACE(__PRETTY_FUNCTION__);
00069
00070
00071 buildSubChans();
00072 }
00073
00074
00075 OrientationChannel::OrientationChannel(OptionManager& mgr, const char* tag, const char* desc, const char* gabortag) :
00076 ComplexChannel(mgr, "Orientation", "orientation", ORI),
00077 itsNumOrients(&OPT_NumOrientations, this),
00078 itsInteractString(&OPT_OriInteraction, this),
00079 itsInteractType(NONE),
00080 itsDidInteractions(false),
00081 itsOverideTagName(true)
00082 {
00083 GVX_TRACE(__PRETTY_FUNCTION__);
00084
00085
00086
00087 setDescriptiveName(sformat("%s", desc));
00088 setTagName(sformat("%s", tag));
00089
00090 itsGaborOverideTag = gabortag;
00091
00092 buildSubChans();
00093
00094 }
00095
00096 void OrientationChannel::buildSubChans()
00097 {
00098 GVX_TRACE(__PRETTY_FUNCTION__);
00099
00100 this->removeAllSubChans();
00101
00102
00103
00104
00105
00106 if(itsOverideTagName)
00107 {
00108 LINFO("Using %d %s orientations spanning [0..180]deg", itsNumOrients.getVal(),itsGaborOverideTag.c_str());
00109 for (uint ori = 0; ori < itsNumOrients.getVal(); ++ori)
00110 {
00111 nub::ref<GaborChannel> chan =
00112 makeSharedComp
00113 (new GaborChannel(getManager(), ori,
00114 180.0 * double(ori) /
00115 double(itsNumOrients.getVal()),
00116 itsGaborOverideTag.c_str(),
00117 itsGaborOverideTag.c_str()));
00118 this->addSubChan(chan);
00119
00120
00121 chan->exportOptions(MC_RECURSE);
00122 }
00123 }
00124 else
00125 {
00126 LINFO("Using %d orientations spanning [0..180]deg", itsNumOrients.getVal());
00127 for (uint ori = 0; ori < itsNumOrients.getVal(); ++ori)
00128 {
00129 nub::ref<GaborChannel> chan =
00130 makeSharedComp
00131 (new GaborChannel(getManager(), ori,
00132 180.0 * double(ori) /
00133 double(itsNumOrients.getVal())));
00134 this->addSubChan(chan);
00135
00136
00137 chan->exportOptions(MC_RECURSE);
00138 }
00139 }
00140
00141 }
00142
00143
00144 void OrientationChannel::parseInteractString(const std::string& value)
00145 {
00146 GVX_TRACE(__PRETTY_FUNCTION__);
00147
00148
00149 itsInteractCoeffs.clear();
00150
00151 if (value.compare("None") == 0)
00152 {
00153 itsInteractType = NONE;
00154 return;
00155 }
00156
00157 if (value.compare("SubtractMean") == 0)
00158 {
00159 itsInteractType = SUB_MEAN;
00160 return;
00161 }
00162
00163 itsInteractType = CUSTOM;
00164
00165
00166 int curpos = 0, len = value.length();
00167 while (curpos < len)
00168 {
00169
00170 int nextpos = value.find_first_not_of("-.0123456789eE",curpos);
00171 if (nextpos == -1) nextpos = len;
00172
00173
00174 if (nextpos == curpos)
00175 LFATAL("Error parsing the OriInteract string '%s' - found '%c' "
00176 "instead of a number.",value.c_str(),value[curpos]);
00177
00178
00179 float coeff;
00180 int nscan = sscanf(value.substr(curpos,nextpos-curpos).c_str(),"%g",&coeff);
00181
00182
00183 if (nscan != 1)
00184 LFATAL("Error parsing OriInteract string '%s' - found '%s' instead of "
00185 "a number.", value.c_str(),
00186 value.substr(curpos,nextpos-curpos).c_str());
00187
00188
00189 itsInteractCoeffs.push_back(coeff);
00190
00191 LDEBUG("coeff = %g; value[nextpos] = '%c'",coeff,value[nextpos]);
00192
00193
00194 if ((nextpos < len) && (value[nextpos] != ','))
00195 LFATAL("Error parsing the OriInteract string '%s' - found '%c' "
00196 "instead of ','.",value.c_str(),value[nextpos]);
00197
00198
00199 curpos = nextpos + 1;
00200 }
00201
00202
00203 return;
00204 }
00205
00206
00207 void OrientationChannel::paramChanged(ModelParamBase* const param,
00208 const bool valueChanged,
00209 ParamClient::ChangeStatus* status)
00210 {
00211 GVX_TRACE(__PRETTY_FUNCTION__);
00212 ComplexChannel::paramChanged(param, valueChanged, status);
00213
00214
00215
00216 if (param == &itsNumOrients &&
00217 numChans() != itsNumOrients.getVal())
00218 buildSubChans();
00219
00220
00221 else if (param == &itsInteractString)
00222 parseInteractString(itsInteractString.getVal());
00223 }
00224
00225
00226 OrientationChannel::~OrientationChannel()
00227 {
00228 GVX_TRACE(__PRETTY_FUNCTION__);
00229 }
00230
00231
00232 GaborChannel& OrientationChannel::gabor(const uint idx) const
00233 {
00234 GVX_TRACE(__PRETTY_FUNCTION__);
00235
00236
00237 return *(dynCast<GaborChannel>(subChan(idx)));
00238 }
00239
00240
00241 void OrientationChannel::doInput(const InputFrame& inframe)
00242 {
00243 GVX_TRACE(__PRETTY_FUNCTION__);
00244 ASSERT(inframe.grayFloat().initialized());
00245
00246 if (numChans() == 0)
00247 return;
00248
00249 rutz::mutex_lock_class lock;
00250 if (inframe.pyrCache().get() != 0
00251 && inframe.pyrCache()->laplacian9.beginSet(inframe.grayFloat(), &lock))
00252 {
00253 inframe.pyrCache()->laplacian9.endSet
00254 (inframe.grayFloat(),
00255 buildPyrLaplacian
00256 (inframe.grayFloat(), gabor(0).getMinPyrLevel(),
00257 gabor(0).getMaxPyrLevel(), 9),
00258 &lock);
00259 }
00260
00261 for (uint i = 0; i < numChans(); ++i)
00262 {
00263 gabor(i).input(inframe);
00264 LINFO("Orientation pyramid (%d/%d) ok.", i+1, numChans());
00265 }
00266 itsDidInteractions = false;
00267 }
00268
00269
00270 void OrientationChannel::doInteractions()
00271 {
00272 GVX_TRACE(__PRETTY_FUNCTION__);
00273 LINFO("OriInteractionType is %s.",itsInteractString.getVal().c_str());
00274 switch(itsInteractType)
00275 {
00276 case NONE:
00277 {
00278
00279 break;
00280 }
00281
00282 case SUB_MEAN:
00283 {
00284
00285
00286
00287 ImageSet<float> mean;
00288
00289
00290 for (uint i = 0; i < numChans(); ++i)
00291 {
00292 gabor(i).getOutput();
00293 if (mean.isEmpty())
00294 mean = gabor(i).itsPq.back().pyr;
00295 else
00296 mean += gabor(i).itsPq.back().pyr;
00297 }
00298 mean /= (float)numChans();
00299
00300
00301
00302 for (uint i = 0; i < numChans(); ++i)
00303 {
00304 gabor(i).getOutput();
00305 gabor(i).itsPq.back().pyr =
00306 clampedDiff(gabor(i).itsPq.back().pyr,mean);
00307 LINFO("Orientation pyramid interactions (%d/%d) ok.",
00308 i+1, numChans());
00309 }
00310
00311
00312 break;
00313 }
00314
00315 case CUSTOM:
00316 {
00317
00318
00319
00320
00321 ASSERT(itsInteractCoeffs.size() == numChans());
00322 std::vector< ImageSet<float> > resPyrs(numChans());
00323
00324
00325 for (uint i = 0; i < numChans(); ++i)
00326 {
00327 ImageSet<float> curPyr = gabor(i).itsPq.back().pyr;
00328 uint coeff_ptr = i;
00329
00330
00331 for (uint j = 0; j < numChans(); ++j)
00332 {
00333 if (resPyrs[j].isEmpty())
00334 resPyrs[j] = (curPyr * itsInteractCoeffs[coeff_ptr]);
00335 else
00336 resPyrs[j] += (curPyr * itsInteractCoeffs[coeff_ptr]);
00337
00338
00339
00340
00341 coeff_ptr = (coeff_ptr - 1) % numChans();
00342 }
00343 }
00344
00345
00346 for (uint i = 0; i < numChans(); ++i)
00347 {
00348 doLowThresh(resPyrs[i],0.0f,0.0f);
00349 gabor(i).itsPq.back().pyr = resPyrs[i];
00350 LINFO("Orientation pyramid interactions (%d/%d) ok.",
00351 i+1, numChans());
00352 }
00353
00354
00355 break;
00356 }
00357 default: LFATAL("Unknown orientation interaction type: %d",
00358 itsInteractType);
00359 }
00360 }
00361
00362
00363 Image<float> OrientationChannel::getOutput()
00364 {
00365 GVX_TRACE(__PRETTY_FUNCTION__);
00366 if (!itsDidInteractions)
00367 {
00368 doInteractions();
00369 itsDidInteractions = true;
00370 }
00371 return ComplexChannel::getOutput();
00372 }
00373
00374
00375 OrientationChannel::InteractType OrientationChannel::getInteractType()
00376 {
00377 GVX_TRACE(__PRETTY_FUNCTION__);
00378 return itsInteractType;
00379 }
00380
00381
00382 void OrientationChannel::setInteractType(OrientationChannel::InteractType type)
00383 {
00384 GVX_TRACE(__PRETTY_FUNCTION__);
00385 itsInteractType = type;
00386 }
00387
00388
00389 std::vector<float> OrientationChannel::getInteractCoeffs()
00390 {
00391 GVX_TRACE(__PRETTY_FUNCTION__);
00392 return itsInteractCoeffs;
00393 }
00394
00395
00396 void OrientationChannel::setInteractCoeffs(std::vector<float>& coeffs)
00397 {
00398 GVX_TRACE(__PRETTY_FUNCTION__);
00399 itsInteractCoeffs = coeffs;
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 #endif // ORIENTATIONCHANNEL_C_DEFINED