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 MOTION_OPTICALFLOW_CHANNEL_C_DEFINED
00039 #define MOTION_OPTICALFLOW_CHANNEL_C_DEFINED
00040
00041 #include "Channels/MotionOpticalFlowChannel.H"
00042
00043 #include "Channels/ChannelOpts.H"
00044 #include "Component/ModelOptionDef.H"
00045
00046 #include "Image/ShapeOps.H"
00047
00048 #include "rutz/trace.h"
00049 #include "Util/Timer.H"
00050
00051 #define OF_SELF_MOTION_WEIGHT 1.0F
00052 #define OF_OBJECT_MOTION_WEIGHT 1.0F
00053 #define OF_MAX_FIRING_RATE 100.0F
00054
00055
00056 const ModelOptionDef OPT_OpticalFlowType =
00057 { MODOPT_ARG(OpticalFlowType), "OpticalFlowType", &MOC_CHANNEL, OPTEXP_CORE,
00058 "Type of computation used to compute the optical flow",
00059 "optical-flow-type", '\0', "<LucasKanade|HornSchunck>",
00060 "LucasKanade" };
00061
00062
00063
00064
00065
00066
00067 MotionOpticalFlowChannel::MotionOpticalFlowChannel(OptionManager& mgr) :
00068 ComplexChannel(mgr,
00069 "MotionOpticalFlow",
00070 "motionOpticalFlow",
00071 MOTIONOPTICALFLOW),
00072 itsOpticalFlowType(&OPT_OpticalFlowType, this),
00073 itsNumDirs(&OPT_NumOpticalFlowDirections, this),
00074 itsFoeDetector(new FoeDetector(mgr))
00075 {
00076 GVX_TRACE(__PRETTY_FUNCTION__);
00077
00078
00079
00080 buildSubChans();
00081
00082 itsWin.reset();
00083 }
00084
00085
00086 MotionOpticalFlowChannel::~MotionOpticalFlowChannel()
00087 {
00088 GVX_TRACE(__PRETTY_FUNCTION__);
00089 }
00090
00091
00092 DirectionOpticalFlowChannel& MotionOpticalFlowChannel::dirChan
00093 (const uint idx) const
00094 {
00095 GVX_TRACE(__PRETTY_FUNCTION__);
00096 return *(dynCast<DirectionOpticalFlowChannel>(subChan(idx)));
00097 }
00098
00099
00100 void MotionOpticalFlowChannel::buildSubChans()
00101 {
00102 GVX_TRACE(__PRETTY_FUNCTION__);
00103
00104 this->removeAllSubChans();
00105
00106
00107
00108
00109
00110 LINFO("Using %d directions spanning [0..360]deg", itsNumDirs.getVal());
00111
00112 itsDirectionOpticalFlowChannels.clear();
00113
00114
00115 for (uint i = 0; i < itsNumDirs.getVal(); i++)
00116 {
00117 nub::ref<DirectionOpticalFlowChannel> chan =
00118 makeSharedComp(new DirectionOpticalFlowChannel
00119 (getManager(), i,
00120 360.0 * double(i)/double(itsNumDirs.getVal()),
00121 itsOpticalFlowType.getVal()));
00122
00123 itsDirectionOpticalFlowChannels.push_back(chan);
00124
00125 this->addSubChan(chan);
00126 chan->exportOptions(MC_RECURSE);
00127 }
00128 }
00129
00130
00131 void MotionOpticalFlowChannel::paramChanged(ModelParamBase* const param,
00132 const bool valueChanged,
00133 ParamClient::ChangeStatus* status)
00134 {
00135 GVX_TRACE(__PRETTY_FUNCTION__);
00136 ComplexChannel::paramChanged(param, valueChanged, status);
00137
00138
00139
00140 if (param == &itsNumDirs &&
00141 numChans() != itsNumDirs.getVal())
00142 buildSubChans();
00143 }
00144
00145
00146 void MotionOpticalFlowChannel::doInput(const InputFrame& inframe)
00147 {
00148 GVX_TRACE(__PRETTY_FUNCTION__);
00149 ASSERT(inframe.grayFloat().initialized());
00150
00151 Image<byte> image(inframe.grayFloat());
00152 if(!itsCurrentImage.initialized())
00153 {
00154 itsCurrentImage = image; return;
00155 }
00156 else
00157 itsPreviousImage = itsCurrentImage;
00158 itsCurrentImage = image;
00159
00160
00161 itsOpticalFlow =
00162 getLucasKanadeOpticFlow(itsPreviousImage, itsCurrentImage);
00163
00164
00165
00166 for (uint i = 0; i < numChans(); i++)
00167 {
00168 itsDirectionOpticalFlowChannels[i]
00169 ->setLucasKanadeOpticalFlow(itsOpticalFlow);
00170 subChan(i)->input(inframe);
00171
00172 LINFO("Motion Optical flow pyramid (%d/%d) ok.", i+1, numChans());
00173 }
00174
00175
00176 computeConspicuityMap();
00177 }
00178
00179
00180 void MotionOpticalFlowChannel::computeConspicuityMap()
00181 {
00182 GVX_TRACE(__PRETTY_FUNCTION__);
00183
00184 uint cmWidth = subChan(0)->getMapDims().w();
00185 uint cmHeight = subChan(0)->getMapDims().h();
00186 Image<float> result(cmWidth, cmHeight, ZEROS);
00187
00188 Dims imDims = itsOpticalFlow->getImageDims();
00189 uint mtWidth = imDims.w()/4;
00190 uint mtHeight = imDims.h()/4;
00191
00192 for (uint i = 0; i < itsNumDirs.getVal(); i++)
00193 {
00194 Image<float> tmap = itsDirectionOpticalFlowChannels[i]
00195 ->getDirectionalOpticalFlow();
00196
00197 Image<float> submap = downSizeClean(tmap, Dims(cmWidth, cmHeight));
00198
00199 Image<float> psubmap;
00200 if (itsUseOlderVersion.getVal())
00201 {
00202 LDEBUG("%s[%d]: applying %s(%f .. %f)",
00203 tagName().c_str(), i,
00204 maxNormTypeName(itsNormType.getVal()), MAXNORMMIN, MAXNORMMAX);
00205 psubmap = maxNormalize(submap, MAXNORMMIN, MAXNORMMAX,
00206 itsNormType.getVal());
00207 }
00208 else
00209 {
00210 LDEBUG("%s[%d]: applying %s(0.0 .. 0.0)", tagName().c_str(), i,
00211 maxNormTypeName(itsNormType.getVal()));
00212 psubmap = maxNormalize(submap, 0.0f, 0.0f, itsNormType.getVal());
00213 }
00214
00215 result += psubmap;
00216 }
00217 Image<float> tsubmap = maxNormalize(result, MAXNORMMIN, MAXNORMMAX,
00218 itsNormType.getVal());
00219 result = tsubmap * numChans();
00220 Image<float> tres = result;
00221 result = rescale(tres, Dims(mtWidth, mtHeight));
00222
00223
00224
00225
00226
00227
00228
00229 Image<float> foeMap =
00230 itsFoeDetector->getFoeMap
00231 (itsOpticalFlow, FOE_METHOD_AVERAGE, false);
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 float mn, mx; getMinMax(foeMap, mn,mx);
00250
00251 inplaceNormalize(foeMap, 0.0F, 1.0F);
00252 foeMap = toPower(foeMap, 40.0F);
00253 foeMap *= mx;
00254
00255
00256 foeMap *= (OF_SELF_MOTION_WEIGHT * OF_MAX_FIRING_RATE * numChans());
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 result += foeMap;
00273
00274
00275
00276
00277 getMinMax(result,mn,mx);
00278 if (mtWidth > cmWidth)
00279 result = downSize(result, Dims(cmWidth, cmHeight));
00280 else if (mtWidth < cmWidth)
00281 result = rescale(result, Dims(cmWidth, cmHeight));
00282 inplaceNormalize(result,0.0F,mx);
00283 LINFO("Final cmap mn: %f mx: %f", mn, mx);
00284
00285 itsConspicuityMap = result;
00286 }
00287
00288
00289 Image<float> MotionOpticalFlowChannel::getOutput()
00290 {
00291 GVX_TRACE(__PRETTY_FUNCTION__);
00292 return itsConspicuityMap;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301 #endif // MOTION_OPTICALFLOW_CHANNEL_C_DEFINED