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 "Apps/BorderWatch/ImageInfo.H"
00039 #include "Image/DrawOps.H"
00040 #include "GUI/DebugWin.H"
00041 #include "Util/StringUtil.H"
00042 #include "Channels/ChannelMaps.H"
00043 #include "Channels/ChannelOpts.H"
00044 #include "Neuro/NeuroSimEvents.H"
00045 #include "Simulation/SimEventQueue.H"
00046 #include "Transport/FrameInfo.H"
00047 #include <cmath>
00048
00049 const ModelOptionCateg MOC_ImageInfo = {
00050 MOC_SORTPRI_3, "Image Info-related options" };
00051
00052 const ModelOptionDef OPT_RandGain =
00053 { MODOPT_ARG(float), "RandGain", &MOC_ImageInfo, OPTEXP_CORE,
00054 "The multiplier for the rand when computing the chip score",
00055 "k-rand", '\0', "<float>", "0.0" };
00056
00057 const ModelOptionDef OPT_EntropyGain =
00058 { MODOPT_ARG(float), "EntropyGain", &MOC_ImageInfo, OPTEXP_CORE,
00059 "The multiplier for the entropy when computing the chip score",
00060 "k-entropy", '\0', "<float>", "0.0" };
00061
00062 const ModelOptionDef OPT_SaliencyGain =
00063 { MODOPT_ARG(float), "SaliencyGain", &MOC_ImageInfo, OPTEXP_CORE,
00064 "The multiplier for the saliency when computing the chip score",
00065 "k-saliency", '\0', "<float>", "0.0" };
00066
00067 const ModelOptionDef OPT_UniquenessGain =
00068 { MODOPT_ARG(float), "UniquenessGain", &MOC_ImageInfo, OPTEXP_CORE,
00069 "The multiplier for the uniqueness when computing the chip score",
00070 "k-uniqueness", '\0', "<float>", "0.0" };
00071
00072 const ModelOptionDef OPT_MSDSurpriseGain =
00073 { MODOPT_ARG(float), "MSDSurpriseGain", &MOC_ImageInfo, OPTEXP_CORE,
00074 "The multiplier for the msd surprise when computing the chip score",
00075 "k-msdsurprise", '\0', "<float>", "0.0" };
00076
00077 const ModelOptionDef OPT_KLSurpriseGain =
00078 { MODOPT_ARG(float), "KLSurpriseGain", &MOC_ImageInfo, OPTEXP_CORE,
00079 "The multiplier for the kl surprise when computing the chip score",
00080 "k-klsurprise", '\0', "<float>", "1.0" };
00081
00082
00083
00084 ImageInfo::ImageInfo(OptionManager& mgr, const std::string& descrName, const std::string& tagName) :
00085 SimModule(mgr, descrName, tagName),
00086 itsVcc(new VisualCortexConfigurator(mgr)),
00087 itsRandGain(&OPT_RandGain, this, 0),
00088 itsEntropyGain(&OPT_EntropyGain, this, 0),
00089 itsSaliencyGain(&OPT_SaliencyGain, this, 0),
00090 itsUniquenessGain(&OPT_UniquenessGain, this, 0),
00091 itsMSDSurpriseGain(&OPT_MSDSurpriseGain, this, 0),
00092 itsKLSurpriseGain(&OPT_KLSurpriseGain, this, 0)
00093 {
00094 addSubComponent(itsVcc);
00095 }
00096
00097
00098 ImageInfo::~ImageInfo()
00099 { }
00100
00101
00102 ImageInfo::ImageStats ImageInfo::update(nub::ref<SimEventQueue>& q,
00103 const Image<PixRGB<byte> >& img, const int frameID)
00104 {
00105 ImageStats stats;
00106
00107
00108 q->post(rutz::make_shared(new SimEventRetinaImage(this, InputFrame(InputFrame::fromRgb(&img, q->now())),
00109 Rectangle(Point2D<int>(0,0), img.getDims()),
00110 Point2D<int>(0,0))));
00111
00112 if (SeC<SimEventVisualCortexOutput> e = q->check<SimEventVisualCortexOutput>(this, SEQ_ANY))
00113 stats.smap = e->vco(1.0F);
00114 else LFATAL("Can not get the Visual cortex output");
00115
00116
00117 findMax(stats.smap, stats.salpoint, stats.saliency);
00118
00119
00120 if (itsUniquenessGain.getVal() != 0.0F || itsRandGain.getVal() != 0.0F || itsEntropyGain.getVal() != 0.0F)
00121 stats.energy = sum(stats.smap);
00122 else stats.energy = 0.0F;
00123
00124
00125
00126 const uint sz = stats.smap.getSize();
00127 if (itsUniquenessGain.getVal() != 0.0F)
00128 stats.uniqueness = stats.saliency - ( (stats.energy - stats.saliency) / (sz - 1) );
00129 else stats.uniqueness = 0.0F;
00130
00131
00132
00133 if (itsRandGain.getVal() != 0.0F || itsEntropyGain.getVal() != 0.0F) {
00134 stats.entropy = 0.0F; stats.rand = 0.0F;
00135 for (uint i = 0; i < sz; ++i)
00136 if (stats.smap[i] > 0.0F)
00137 {
00138 stats.entropy += (stats.smap[i] / stats.energy) * logf(stats.smap[i] / stats.energy);
00139 stats.rand += stats.smap[i] * logf(stats.smap[i]) / sz;
00140 }
00141 } else { stats.entropy = 0.0F; stats.rand = 0.0F; }
00142
00143
00144 if (itsKLSurpriseGain.getVal() != 0.0F) {
00145
00146 (void)integrateData(stats.smap,
00147 5,
00148 0.1,
00149 itsBelief1Mu, itsBelief1Sig);
00150
00151 stats.KLsurprise = integrateData(itsBelief1Mu,
00152 5,
00153 0.01,
00154 itsBelief2Mu, itsBelief2Sig);
00155 stats.belief1 = itsBelief1Mu;
00156 stats.belief2 = itsBelief2Mu;
00157 } else stats.KLsurprise = 0.0F;
00158
00159
00160 if (itsMSDSurpriseGain.getVal() != 0.0F) stats.MSDsurprise = updateMSDiff(img, stats.smap);
00161 else stats.MSDsurprise = 0.0F;
00162
00163
00164 stats.score = itsRandGain.getVal() * stats.rand + itsEntropyGain.getVal() * stats.entropy +
00165 itsSaliencyGain.getVal() * stats.saliency + itsUniquenessGain.getVal() * stats.uniqueness +
00166 itsMSDSurpriseGain.getVal() * stats.MSDsurprise + itsKLSurpriseGain.getVal() * stats.KLsurprise;
00167
00168 return stats;
00169 }
00170
00171
00172
00173
00174
00175 float ImageInfo::updateMSDiff(const Image<PixRGB<byte> >& img, Image<float> salMap)
00176 {
00177
00178 if (!salMap.initialized()) { LINFO("Current smap not set"); return 0.0; }
00179
00180
00181 if (!itsPrevSmap.initialized()) { itsPrevSmap = salMap; return 0.0; }
00182
00183
00184 const float sCurr = sum(salMap);
00185 const float sPrev = sum(itsPrevSmap);
00186
00187
00188 float diffSum = 0.0F;
00189 for (int i = 0; i < salMap.getSize(); ++i)
00190 {
00191 const float cVal = salMap.getVal(i);
00192 const float pVal = itsPrevSmap.getVal(i);
00193 const float diff = cVal / sCurr - pVal / sPrev;
00194 diffSum += diff * diff;
00195 }
00196
00197
00198 float surprise = diffSum / float(salMap.getSize());
00199
00200
00201 const float m = 2.8900e-05F, s = 9.6030e-06F;
00202 surprise = 1.0F / (1.0F + expf(-(surprise - m) / s));
00203
00204
00205 itsPrevSmap = salMap;
00206
00207 return surprise;
00208 }
00209
00210
00211 float ImageInfo::integrateData(const Image<float> &data, const float R, const float Q,
00212 Image<float>& bel_mu, Image<float>& bel_sig)
00213 {
00214 if (!bel_mu.initialized()) { bel_mu = data; bel_sig.resize(bel_mu.getDims(), true); }
00215
00216 Image<float>::const_iterator inPtr = data.begin(), inStop = data.end();
00217 Image<float>::iterator muPtr = bel_mu.beginw(), sigPtr = bel_sig.beginw();
00218 float surprise = 0.0F;
00219
00220
00221 while (inPtr != inStop)
00222 {
00223
00224 const float mu_hat = *muPtr;
00225 const float sig_hat = *sigPtr + Q;
00226
00227
00228 const float K = sig_hat / (sig_hat + R);
00229 *muPtr = mu_hat + K * (*inPtr - mu_hat);
00230 *sigPtr = (1.0F - K) * sig_hat;
00231
00232
00233
00234
00235
00236
00237
00238
00239 float localSurprise = fabs(*muPtr - mu_hat);
00240 surprise += localSurprise;
00241
00242 ++inPtr; ++muPtr; ++sigPtr;
00243 }
00244
00245 return surprise;
00246 }
00247