00001 #ifndef Impala_Core_Feature_VisSem_h
00002 #define Impala_Core_Feature_VisSem_h
00003
00004 #include "Core/Feature/Computor.h"
00005 #include "Core/Vector/HistogramAccumulation.h"
00006 #include "Core/Vector/Concat.h"
00007 #include "Core/Vector/HistogramIntersection.h"
00008 #include "Core/Vector/Similarity.h"
00009 #include "Core/Vector/HistogramNormalization.h"
00010 #include "Core/Vector/Avg.h"
00011 #include "Core/Vector/Max.h"
00012 #include "Core/Vector/ElemAvg.h"
00013 #include "Core/Vector/ElemMax.h"
00014 #include "Core/Vector/AddAssign.h"
00015 #include "Core/Vector/Clear.h"
00016 #include "Core/Vector/VectorSet.h"
00017 #include "Core/Histogram/MakeHistogram1dSet.h"
00018 #include "Core/Vector/WeibullSim.h"
00019 #include "Core/Histogram/ComputeWeibull.h"
00020 #include "Core/Array/InvWiccest.h"
00021 #include "Core/Array/VisSemGabor.h"
00022 #include "Core/Array/PixStat.h"
00023
00024 namespace Impala
00025 {
00026 namespace Core
00027 {
00028 namespace Feature
00029 {
00030
00031
00032 class VisSem : public Computor
00033 {
00034 public:
00035
00036 typedef Array::Array2dVec3UInt8 Array2dVec3UInt8;
00037 typedef Array::Array2dScalarReal64 Array2dScalarReal64;
00038 typedef Vector::VectorTem<Real64> VectorReal64;
00039 typedef Array::ArraySet<Array2dScalarReal64> InvSetType;
00040 typedef Histogram::Histogram1dSet<Array2dScalarReal64> HistSetType;
00041
00042 VisSem(String name, CmdOptions& options) : Computor(name, options)
00043 {
00044 if (GetName() == "vissem")
00045 {
00046 for (int i=0 ; i<options.GetInt("nrScales") ; i++)
00047 {
00048 String s = "spatialSigma_s" + MakeString(i);
00049 AddScale(options.GetDouble(s));
00050 }
00051 mDoRot = options.GetBool("doRot");
00052 mDoC = options.GetBool("doC");
00053 mHistBinCount = options.GetInt("histBinCount");
00054 SetRegionDescriptorLength(2);
00055 }
00056 if (GetName() == "vissemgabor")
00057 {
00058 mNrOrient = 4;
00059 AddScale(2.828);
00060 mFreq.push_back(0.720);
00061 AddScale(1.414);
00062 mFreq.push_back(2.094);
00063 mHistBinCount = 101;
00064 mCumulativeHist = false;
00065 SetRegionDescriptorLength(mHistBinCount);
00066 }
00067
00068 mDoCodebook = options.GetBool("doCodebook");
00069 ILOG_INFO("mDoCodebook: " << mDoCodebook);
00070
00071
00072 mDoUNC = options.GetBool("doUNC");
00073 ILOG_INFO("doUNC: " << mDoUNC);
00074
00075 mKeyframesName = FileNameBase(options.GetString("keyframeMask"));
00076 if (mKeyframesName == "")
00077 mKeyframesName = FileNameBase(options.GetString("keyframeMaskAnno"));
00078 if (mKeyframesName == "")
00079 mKeyframesName = "all";
00080
00081 InvSetType invSet;
00082 ComputePixelFeatureSet(invSet, 0, 0);
00083 SetPixelFeatureSetSize(invSet.Size());
00084
00085 if (!IsClusterBased())
00086 for (int i=0 ; i<GetNrPixelFeatureSets() ; i++)
00087 mHistAccu.push_back(NewHistSet());
00088 }
00089
00090
00091 virtual FeatureDefinition
00092 ExtendFeatureDefinition(FeatureDefinition def)
00093 {
00094 def = Computor::ExtendFeatureDefinition(def);
00095 def.AddParameter("UNC", mDoUNC);
00096 def.AddParameter("Codebook", mDoCodebook);
00097 return def;
00098 }
00099
00100 virtual FeatureTable*
00101 MakeProtoFeatureTable(int pixelFeatureSet, int regionFeatureSet,
00102 String clusterType, String clusterVal)
00103 {
00104 String pName = GetPixelFeatureDefName(pixelFeatureSet);
00105 String pVal = GetPixelFeatureDefVal(pixelFeatureSet);
00106 String rName = GetRegionFeatureDefName(regionFeatureSet);
00107 String rVal = GetRegionFeatureDefVal(regionFeatureSet);
00108 FeatureDefinition def(GetName());
00109 def.AddParameter("proto", FileNameBase(mProtoDataFile));
00110 def.AddParameter("keyframes", mKeyframesName);
00111 def.AddParameter(pName, pVal);
00112 def.AddParameter(rName, rVal);
00113 def.AddParameter(clusterType, clusterVal);
00114 AddProtoFeatureTable(def, 1, GetRegionFeatureLength());
00115 return GetProtoFeatureTableSet()->GetTable(def);
00116 }
00117
00118 virtual void
00119 ReadPrototypes(String protoSet, String maskSet, int maxNr)
00120 {
00121 ReadProtoFeatureTableSet(protoSet, maskSet);
00122 if (maxNr > 0)
00123 LimitProtoFeatureTableSize(maxNr);
00124 MakeFeatureTableSet();
00125 }
00126
00127 virtual void
00128 ComputeRegionFeatures(Array::Array2dVec3UInt8* im, Quid quid)
00129 {
00130 HistSetType* hSet = NewHistSet();
00131 for (int p=0 ; p<GetNrPixelFeatureSets() ; p++)
00132 {
00133 InvSetType invSet;
00134 ComputePixelFeatureSet(invSet, p, im);
00135 Array2dScalarReal64* a = invSet.Array(0);
00136 mPyramid.SetImageSize(a->CW(), a->CH());
00137 for (int l=0 ; l<mPyramid.NrLevels() ; l++)
00138 {
00139 FeatureTable* tab = GetRegionFeatureTable(p, l);
00140 for (int r=0 ; r<mPyramid.NrRects(l) ; r++)
00141 {
00142 Geometry::Rectangle rect = mPyramid.Rect(l, r);
00143 Histogram::MakeHistogram1dSet(hSet, invSet, rect, true);
00144 VectorReal64 vec = ComputeRegionDescriptor(hSet);
00145 if (CheckRegionDescriptor(vec))
00146 tab->Add(quid, vec);
00147 }
00148 }
00149 invSet.Delete();
00150 }
00151 delete hSet;
00152 }
00153
00154 virtual void
00155 ComputeFeatures(Array::Array2dVec3UInt8* im, Quid quid)
00156 {
00157 for (int p=0 ; p<GetNrPixelFeatureSets() ; p++)
00158 {
00159 InvSetType invSet;
00160 ComputePixelFeatureSet(invSet, p, im);
00161 Array2dScalarReal64* a = invSet.Array(0);
00162 mPyramid.SetImageSize(a->CW(), a->CH());
00163 mLazebnikPyramid.SetImageSize(a->CW(), a->CH());
00164 ComputeFeaturesPixelSet(invSet, p, quid);
00165 invSet.Delete();
00166 }
00167 }
00168
00169
00170
00171 void
00172 InitStat()
00173 {
00174 mFeatMin.reserve(GetPixelFeatureSetSize());
00175 mFeatMax.reserve(GetPixelFeatureSetSize());
00176 mFeatMinAll.reserve(GetPixelFeatureSetSize());
00177 mFeatMaxAll.reserve(GetPixelFeatureSetSize());
00178 for (int i=0 ; i<GetPixelFeatureSetSize() ; i++)
00179 {
00180 mFeatMin[i] = 1000;
00181 mFeatMax[i] = -1000;
00182 mFeatMinAll[i] = 1000;
00183 mFeatMaxAll[i] = -1000;
00184 }
00185 }
00186
00187 void
00188 ImageStat(Array::Array2dVec3UInt8* im)
00189 {
00190 for (int p=0 ; p<GetNrPixelFeatureSets() ; p++)
00191 {
00192 InvSetType invSet;
00193 ComputePixelFeatureSet(invSet, p, im);
00194
00195 HistSetType* hSet = NewHistSet();
00196 Geometry::Rectangle roiRect(15, 15, 352-15, 240-15);
00197 Histogram::MakeHistogram1dSet(hSet, invSet, roiRect, true);
00198 for (int i=0 ; i<GetPixelFeatureSetSize() ; i++)
00199 {
00200 Array2dScalarReal64* roi = MakeRoi(invSet.Array(i), roiRect);
00201 Real64 minVal, maxVal, meanVal, varVal;
00202 PixStat(roi, &minVal, &maxVal, &meanVal, &varVal);
00203 mFeatMin[i] = Min(mFeatMin[i], minVal);
00204 mFeatMax[i] = Max(mFeatMax[i], maxVal);
00205 Real64 perc = hSet->Hist(i).OutlierPercentage();
00206 if (perc > 1)
00207 std::cout << "maxVal = " << maxVal << ", perc = "
00208 << perc << ", i = " << i << std::endl;
00209 delete roi;
00210 }
00211 delete hSet;
00212 invSet.Delete();
00213 }
00214 }
00215
00216 void
00217 StatMinMax2All()
00218 {
00219 for (int i=0 ; i<GetPixelFeatureSetSize() ; i++)
00220 {
00221 mFeatMinAll[i] = Min(mFeatMin[i], mFeatMinAll[i]);
00222 mFeatMaxAll[i] = Max(mFeatMax[i], mFeatMaxAll[i]);
00223 std::cout << "feat = " << i << ", min = " << mFeatMin[i] << " ("
00224 << mFeatMinAll[i] << "), max = " << mFeatMax[i]
00225 << " (" << mFeatMaxAll[i] << ")" << std::endl;
00226 mFeatMin[i] = 1000;
00227 mFeatMax[i] = -1000;
00228 }
00229 }
00230
00231
00232
00233 void
00234 ClearAnnoAccu()
00235 {
00236 for (int i=0 ; i<mHistAccu.size() ; i++)
00237 Vector::Clear(mHistAccu[i]);
00238 }
00239
00240 void
00241 AddImageToAccu(Array::Array2dVec3UInt8* im, Geometry::Rectangle rect)
00242 {
00243
00244
00245 rect.mLeft += 1;
00246 rect.mRight -= 1;
00247 rect.mTop += 1;
00248 rect.mBottom -= 1;
00249
00250
00251 for (int p=0 ; p<GetNrPixelFeatureSets() ; p++)
00252 {
00253 InvSetType invSet;
00254 ComputePixelFeatureSet(invSet, p, im);
00255 HistSetType* hSet = NewHistSet();
00256 Histogram::MakeHistogram1dSet(hSet, invSet, rect, true);
00257 Vector::AddAssign(mHistAccu[p], hSet, 0, 0, GetPixelFeatureSetSize());
00258 mHistAccu[p]->SetSize(GetPixelFeatureSetSize());
00259 delete hSet;
00260 invSet.Delete();
00261 }
00262 }
00263
00264 void
00265 AddAccuToAnnoTable(int bookmarkNr, String anno)
00266 {
00267 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00268 Quid quid = mProtoLabels.Add(anno);
00269 #else // REPOSITORY_USED
00270 Quid quid = mProtoLabels->Add(anno);
00271 #endif // REPOSITORY_USED
00272 for (int p=0 ; p<GetNrPixelFeatureSets() ; p++)
00273 {
00274 VectorReal64 v = ComputeRegionDescriptor(mHistAccu[p]);
00275 FeatureTable* tab = GetProtoFeatureTable(p, anno);
00276 tab->Add(quid, v);
00277 }
00278 }
00279
00280 private:
00281
00282 HistSetType*
00283 NewHistSet()
00284 {
00285
00286 HistSetType* hSet = new HistSetType(-1.0, 1.0, mHistBinCount,
00287 GetPixelFeatureSetSize());
00288 if (GetName() == "vissemgabor")
00289 {
00290 for (int i=0 ; i<GetPixelFeatureSetSize()-2 ; i++)
00291 {
00292 if (i%3 == 0)
00293 hSet->SetRange(i, -0.0001, 1.0);
00294 else
00295 hSet->SetRange(i, -0.0001, 0.5);
00296 }
00297 }
00298 return hSet;
00299 }
00300
00301 void
00302 ComputePixelFeatureSet(InvSetType& fSet, int idx, Array2dVec3UInt8* im)
00303 {
00304 if (GetName() == "vissem")
00305 Array::InvWiccest(fSet, im, mDoRot, mDoC, GetScale(idx), 3, true);
00306 if (GetName() == "vissemgabor")
00307 Array::VisSemGabor(fSet, im, GetScale(idx), mFreq[idx], mNrOrient);
00308 }
00309
00310 VectorReal64
00311 ComputeRegionDescriptor(HistSetType* hSet)
00312 {
00313 if (GetName() == "vissemgabor")
00314 {
00315 if (mCumulativeHist)
00316 Vector::HistogramAccumulation(hSet, false, true, 0);
00317 else
00318 Vector::HistogramNormalization(hSet, true, 0);
00319 return Vector::Concat(hSet);
00320 }
00321
00322 VectorReal64 v(GetRegionFeatureLength());
00323 Histogram::ComputeWeibull(v, hSet, false, false);
00324 return v;
00325 }
00326
00327 bool
00328 CheckRegionDescriptor(VectorReal64 vec)
00329 {
00330 if (GetName() == "vissem")
00331 {
00332 bool eliminateZeros = true;
00333 if (!eliminateZeros)
00334 return true;
00335 bool ok = true;
00336 for (int i=0 ; i<vec.Size() ; i++)
00337 {
00338 if (vec[i] == 0)
00339 {
00340 ok = false;
00341 break;
00342 }
00343 }
00344 return ok;
00345 }
00346 return true;
00347 }
00348
00349 VectorReal64
00350 ComputeRegionSimilarity(VectorReal64 regionVec, FeatureTable* protoTab)
00351 {
00352 int nrProto = protoTab->Size();
00353 VectorReal64 res(nrProto);
00354 if (GetName() == "vissem")
00355 {
00356 Vector::Similarity(res.GetData(), regionVec, protoTab->GetColumn2(),
00357 0, 1, Vector::WeibullSim<Real64>);
00358 }
00359 if (GetName() == "vissemgabor")
00360 {
00361 Vector::Similarity(res.GetData(), regionVec, protoTab->GetColumn2(),
00362 0, 1, Vector::HistogramIntersection<Real64>);
00363 Vector::DivAssign(res, Real64(GetPixelFeatureSetSize()));
00364 }
00365 return res;
00366 }
00367
00368
00369 void
00370 DoUNC(FeatureTableSet* regionSim, int regionFeature)
00371 {
00372 for (int r=0 ; r<mPyramid.NrRects(regionFeature) ; r++)
00373 {
00374 Real64 totWeight = 0;
00375 for (int t=0 ; t<regionSim->Size() ; t++)
00376 {
00377 VectorReal64 regionVec = regionSim->GetTable(t)->Get2(r);
00378 totWeight += Sum(regionVec);
00379 }
00380 for (int t=0 ; t<regionSim->Size() ; t++)
00381 {
00382 VectorReal64 regionVec = regionSim->GetTable(t)->Get2(r);
00383 DivAssign(regionVec, totWeight);
00384 regionSim->GetTable(t)->Set2(r, regionVec);
00385 }
00386 }
00387 }
00388
00389
00390 void
00391 DoCodebook(FeatureTableSet* regionSim, int regionFeature)
00392 {
00393 for (int r=0 ; r<mPyramid.NrRects(regionFeature) ; r++)
00394 {
00395 Real64 maxSim = -1;
00396 for (int t=0 ; t<regionSim->Size() ; t++)
00397 {
00398 VectorReal64 regionVec = regionSim->GetTable(t)->Get2(r);
00399 maxSim = Impala::Max(maxSim, ElemMax(regionVec));
00400 }
00401 for (int t=0 ; t<regionSim->Size() ; t++)
00402 {
00403 VectorReal64 regionVec = regionSim->GetTable(t)->Get2(r);
00404 for (int i=0 ; i<regionVec.Size() ; i++)
00405 regionVec[i] = (regionVec[i] == maxSim) ? 1.0 : 0.0;
00406 regionSim->GetTable(t)->Set2(r, regionVec);
00407 }
00408 }
00409 }
00410
00411 VectorReal64
00412 DoSpatialPyramid(Geometry::Rectangle rect, VectorReal64 vec)
00413 {
00414 VectorReal64 res(vec.Size() * mLazebnikPyramid.TotalNrRects());
00415 res = 0.0;
00416
00417 int levelBase = 0;
00418 double normVal = 1.0;
00419
00420 for (int level=mLazebnikPyramid.NrLevels()-1 ; level>=0 ; level--)
00421 {
00422
00423
00424 if (level != mLazebnikPyramid.NrLevels() - 1)
00425 {
00426 normVal = normVal / ((double)mLazebnikPyramid.NrRects(level+1) /
00427 mLazebnikPyramid.NrRects(level));
00428 }
00429
00430 int nrRect = mLazebnikPyramid.NrRects(level);
00431 for (int r=0 ; r<nrRect ; r++)
00432 {
00433 Geometry::Rectangle rectLazeb = mLazebnikPyramid.Rect(level, r);
00434
00435
00436
00437 if (rectLazeb.Intersects(rect))
00438 {
00439 int rectBase = levelBase + r * vec.Size();
00440 for (int i=0 ; i<vec.Size() ; i++)
00441 {
00442
00443
00444
00445 res[rectBase + i] = vec[i] * normVal * normVal;
00446 }
00447 }
00448 }
00449 levelBase += nrRect * vec.Size();
00450 }
00451 return res;
00452 }
00453
00454 void
00455 DoSpatialPyramid(FeatureTableSet* regionSim, int regionFeature,
00456 FeatureTableSet* regionSimSP)
00457 {
00458 for (int r=0 ; r<mPyramid.NrRects(regionFeature) ; r++)
00459 {
00460 Geometry::Rectangle rect = mPyramid.Rect(regionFeature, r);
00461 for (int t=0 ; t<regionSim->Size() ; t++)
00462 {
00463 VectorReal64 regionVec = regionSim->GetTable(t)->Get2(r);
00464 VectorReal64 final = DoSpatialPyramid(rect, regionVec);
00465 regionSimSP->GetTable(t)->Add(0, final);
00466 }
00467 }
00468 }
00469
00470 void
00471 ComputeFeaturesPixelSet(InvSetType& invSet, int p, Quid quid)
00472 {
00473 HistSetType* hSet = NewHistSet();
00474 for (int l=0 ; l<mPyramid.NrLevels() ; l++)
00475 {
00476 std::vector<FeatureTable*> protoTabs = GetProtoFeatureTables(p, l);
00477 if (!IsClusterBased())
00478 protoTabs = GetProtoFeatureTables(p);
00479 FeatureTableSet regionSim;
00480 FeatureTableSet regionSimSP;
00481 for (int t=0 ; t<protoTabs.size() ; t++)
00482 {
00483 int nrCodeWords = (IsClusterBased()) ? protoTabs[t]->Size() : 1;
00484 FeatureDefinition def("sim");
00485 regionSim.Add(new FeatureTable(def, 200, nrCodeWords));
00486 nrCodeWords *= mLazebnikPyramid.TotalNrRects();
00487 regionSimSP.Add(new FeatureTable(def, 200, nrCodeWords));
00488 }
00489
00490 for (int r=0 ; r<mPyramid.NrRects(l) ; r++)
00491 {
00492 Geometry::Rectangle rect = mPyramid.Rect(l, r);
00493 Histogram::MakeHistogram1dSet(hSet, invSet, rect, true);
00494
00495 VectorReal64 exVec = ComputeRegionDescriptor(hSet);
00496
00497 for (int t=0 ; t<protoTabs.size() ; t++)
00498 {
00499 VectorReal64 sVec = ComputeRegionSimilarity(exVec,
00500 protoTabs[t]);
00501 VectorReal64 regionVec;
00502 if (IsClusterBased())
00503 {
00504 regionVec = sVec;
00505 }
00506 else
00507 {
00508 regionVec = VectorReal64(1);
00509 regionVec[0] = Vector::ElemAvg(sVec, 0, 0, -1);
00510 }
00511 regionSim.GetTable(t)->Add(0, regionVec);
00512 }
00513 }
00514
00515 if (mDoUNC)
00516 DoUNC(®ionSim, l);
00517 if (mDoCodebook)
00518 DoCodebook(®ionSim, l);
00519 DoSpatialPyramid(®ionSim, l, ®ionSimSP);
00520
00521 for (int t=0 ; t<protoTabs.size() ; t++)
00522 {
00523 FeatureTable* simTab = regionSimSP.GetTable(t);
00524 VectorReal64 vMax;
00525 Vector::Max(&vMax, simTab->GetColumn2(), simTab->Size(), 0);
00526
00527 VectorReal64 vAvg;
00528 Vector::Avg(&vAvg, simTab->GetColumn2(), simTab->Size(), 0);
00529 FeatureDefinition def = protoTabs[t]->GetFeatureDefinition();
00530 FeatureTable* tab = GetFeatureTable(def, l);
00531 tab->Add(quid, Vector::Concat(vMax, vAvg));
00532 }
00533 regionSim.Delete();
00534 regionSimSP.Delete();
00535 }
00536 delete hSet;
00537 }
00538
00539 bool mDoRot;
00540 bool mDoC;
00541 int mHistBinCount;
00542 bool mCumulativeHist;
00543 int mNrOrient;
00544 std::vector<double> mFreq;
00545
00546 std::vector<Real64> mFeatMin;
00547 std::vector<Real64> mFeatMax;
00548 std::vector<Real64> mFeatMinAll;
00549 std::vector<Real64> mFeatMaxAll;
00550
00551 std::vector<HistSetType*> mHistAccu;
00552
00553 String mKeyframesName;
00554 bool mDoCodebook;
00555 bool mDoUNC;
00556
00557 ILOG_VAR_DEC;
00558 };
00559
00560 ILOG_VAR_INIT(VisSem, Impala.Core.Feature);
00561
00562 }
00563 }
00564 }
00565
00566 #endif