00001 #ifndef Impala_Core_VideoSet_IndexAnnotation_h
00002 #define Impala_Core_VideoSet_IndexAnnotation_h
00003
00004 #include "Persistency/AnnotationTableSetRepository.h"
00005 #include "Persistency/Mpeg7DocRepository.h"
00006 #include "Persistency/QuidTableRepository.h"
00007 #include "Core/Table/AnnotationTableSet.h"
00008 #include "Core/Table/Sort.h"
00009 #include "Core/VideoSet/Reporter.h"
00010 #include "Core/VideoSet/Mpeg7Doc.h"
00011
00012 namespace Impala
00013 {
00014 namespace Core
00015 {
00016 namespace VideoSet
00017 {
00018
00019
00020 class IndexAnnotation : public Listener
00021 {
00022 public:
00023
00024 IndexAnnotation(Reporter* reporter, CmdOptions& options)
00025 {
00026 mReporter = reporter;
00027 if (options.GetNrArg() < 3)
00028 {
00029 ILOG_ERROR("Missing argument");
00030 return;
00031 }
00032 mConceptSet = options.GetArg(2);
00033 mConceptExtra = "";
00034 if (options.GetNrArg() > 3)
00035 mConceptExtra = options.GetArg(3);
00036 mNrExtra = 0;
00037 if (options.GetNrArg() > 4)
00038 mNrExtra = atol(options.GetArg(4));
00039 mKeyframes = 0;
00040 mSegmentation = 0;
00041 mRkfMask = options.GetBool("rkfMask");
00042 }
00043
00044 virtual void
00045 HandleNewWalk(VideoSet* vs)
00046 {
00047 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00048 mAnnoShot = Table::AnnotationTableSet::MakeFromFile(vs, mConceptSet,
00049 false, 0);
00050 mAnnoFrame = Table::AnnotationTableSet::MakeFromFile(vs, mConceptSet,
00051 false, 0);
00052 #else // REPOSITORY_USED
00053 Persistency::KeywordListLocator loc(vs->GetLocator(), mConceptSet);
00054 Table::KeywordList keyList =
00055 *(Persistency::KeywordListRepository().Get(loc));
00056 mAnnoShot = new Table::AnnotationTableSet(keyList, 0);
00057 mAnnoFrame = new Table::AnnotationTableSet(keyList, 0);
00058 #endif // REPOSITORY_USED
00059 if (! (mAnnoShot && mAnnoFrame))
00060 {
00061 ILOG_ERROR("Unable to read conceptSet");
00062 }
00063 mAnnoExtra = 0;
00064 mQuidExtra = 0;
00065 if (!mConceptExtra.empty())
00066 {
00067 ILOG_INFO("Reading extra : " << mConceptExtra);
00068 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00069 mAnnoExtra = Table::AnnotationTableSet::MakeFromFile(vs,
00070 mConceptExtra,
00071 false, 0);
00072 #else // REPOSITORY_USED
00073 loc.SetConceptSet(mConceptExtra);
00074 keyList = *(Persistency::KeywordListRepository().Get(loc));
00075 mAnnoExtra = new Table::AnnotationTableSet(keyList, 0);
00076 #endif // REPOSITORY_USED
00077 if (!mAnnoExtra)
00078 {
00079 ILOG_ERROR("Unable to read conceptExtra");
00080 }
00081 mQuidExtra = new Table::QuidTable(100);
00082 }
00083 int nr = mAnnoShot->Size();
00084 mTotalNrAnno.resize(nr);
00085 mTotalNrSingleFrame.resize(nr);
00086 mTotalNrFrames.resize(nr);
00087 mTotalNrAnnoPos.resize(nr);
00088 mTotalNrSingleFramePos.resize(nr);
00089 mTotalNrFramesPos.resize(nr);
00090 }
00091
00092 virtual void
00093 HandleNewWalk(VideoSet* vs, Keyframes* keyframes, bool* keyframeMask)
00094 {
00095 mKeyframes = keyframes;
00096 }
00097
00098 virtual void
00099 HandleNewWalk(VideoSet* vs, Segmentation* segmentation)
00100 {
00101 mSegmentation = segmentation;
00102 }
00103
00104 virtual void
00105 HandleNewFile(VideoSet* vs, int fileId, Stream::RgbDataSrc* src)
00106 {
00107 if (mAnnoExtra && (!(mKeyframes && mSegmentation)))
00108 {
00109 ILOG_ERROR("Need keyframes and segmentation for extra annotations");
00110 delete mAnnoExtra;
00111 mAnnoExtra = 0;
00112 delete mQuidExtra;
00113 mQuidExtra = 0;
00114 }
00115
00116 for (int c=0 ; c<mAnnoShot->Size() ; c++)
00117 {
00118 String concept = mAnnoShot->GetLabel(c);
00119 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00120 String fName;
00121 fName = vs->GetFilePathMpeg7Anno(fileId, mConceptSet,
00122 concept + ".xml", false, true);
00123 if (fName.empty())
00124 continue;
00125
00126 Mpeg7Doc mp7(fName, vs->GetDatabase());
00127 for (int s=0 ; s<mp7.NrShots() ; s++)
00128 {
00129 mTotalNrAnno[c]++;
00130 int len = mp7.EndFrame(s) - mp7.StartFrame(s);
00131 if (len <= 1)
00132 mTotalNrSingleFrame[c]++;
00133 else
00134 mTotalNrFrames[c] += len;
00135 if (mp7.IsPositiveAnno(s))
00136 {
00137 mTotalNrAnnoPos[c]++;
00138 if (len <= 1)
00139 mTotalNrSingleFramePos[c]++;
00140 else
00141 mTotalNrFramesPos[c] += len;
00142 }
00143 }
00144 if (mKeyframes)
00145 DoKeyframes(vs, fileId, c, &mp7);
00146 if (mSegmentation)
00147 DoShots(vs, fileId, c, &mp7);
00148 #else // REPOSITORY_USED
00149 String container = mConceptSet + "/" + vs->GetContainerFile(fileId);
00150 typedef Persistency::Mpeg7DocLocator MP7Loc;
00151 MP7Loc loc(vs->GetLocator(), MP7Loc::MPEG7_ANNOTATION, container,
00152 concept + ".xml");
00153 if (!Persistency::Mpeg7DocRepository().Exists(loc))
00154 continue;
00155
00156 Mpeg7Doc* mp7 = Persistency::Mpeg7DocRepository().Get(loc);
00157 for (int s=0 ; s<mp7->NrShots() ; s++)
00158 {
00159 mTotalNrAnno[c]++;
00160 int len = mp7->EndFrame(s) - mp7->StartFrame(s);
00161 if (len <= 1)
00162 mTotalNrSingleFrame[c]++;
00163 else
00164 mTotalNrFrames[c] += len;
00165 if (mp7->IsPositiveAnno(s))
00166 {
00167 mTotalNrAnnoPos[c]++;
00168 if (len <= 1)
00169 mTotalNrSingleFramePos[c]++;
00170 else
00171 mTotalNrFramesPos[c] += len;
00172 }
00173 }
00174 if (mKeyframes)
00175 DoKeyframes(vs, fileId, c, mp7);
00176 if (mSegmentation)
00177 DoShots(vs, fileId, c, mp7);
00178 delete mp7;
00179 #endif // REPOSITORY_USED
00180 }
00181 }
00182
00183 virtual void
00184 HandleDoneWalk(VideoSet* vs)
00185 {
00186 Persistency::AnnotationTableSetLocator loc(vs->GetLocator(), 0,
00187 mConceptSet);
00188 for (int c=0 ; c<mAnnoShot->Size() ; c++)
00189 {
00190 String concept = mAnnoShot->GetLabel(c);
00191 int nrShot = mTotalNrAnno[c] - mTotalNrSingleFrame[c];
00192 double avg = (double) mTotalNrFrames[c] / nrShot;
00193 if (nrShot == 0)
00194 avg = 1;
00195 ILOG_INFO("Indexed " << mTotalNrAnno[c] << " annotations for "
00196 << concept);
00197 ILOG_INFO("total of " << mTotalNrSingleFrame[c] << " frames and "
00198 << nrShot << " shots with avg length of " << avg);
00199 nrShot = mTotalNrAnnoPos[c] - mTotalNrSingleFramePos[c];
00200 avg = (double) mTotalNrFramesPos[c] / nrShot;
00201 if (nrShot == 0)
00202 avg = 1;
00203 ILOG_INFO("postives: total of " << mTotalNrSingleFramePos[c] <<
00204 " frames and " << nrShot << " shots with avg length of "
00205 << avg);
00206 }
00207 if (mSegmentation)
00208 {
00209 ILOG_INFO("Number of shots " << mSegmentation->GetNrShots());
00210 ILOG_INFO("Saving shot annotations");
00211 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00212 mAnnoShot->SaveTables(vs, mConceptSet, true);
00213 #else // REPOSITORY_USED
00214 Persistency::AnnotationTableSetRepository().Add(loc, mAnnoShot);
00215 #endif // REPOSITORY_USED
00216 }
00217 if (mKeyframes)
00218 {
00219 ILOG_INFO("Number of keyframes " << mKeyframes->GetNrKeyframes());
00220 ILOG_INFO("Saving keyframe annotations");
00221 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00222 mAnnoFrame->SaveTables(vs, mConceptSet, true);
00223 #else // REPOSITORY_USED
00224 Persistency::AnnotationTableSetRepository().Add(loc, mAnnoFrame);
00225 #endif // REPOSITORY_USED
00226 }
00227 if (mAnnoExtra)
00228 {
00229 ILOG_INFO("Saving extra annotations");
00230 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00231 mAnnoExtra->SaveTables(vs, mConceptExtra, true);
00232 #else // REPOSITORY_USED
00233 loc.SetConceptSet(mConceptExtra);
00234 Persistency::AnnotationTableSetRepository().Add(loc, mAnnoExtra);
00235 #endif // REPOSITORY_USED
00236 ILOG_INFO("Sorting and saving quids");
00237 Table::Sort(mQuidExtra, 1, true);
00238 String qName = FileNameBase(mConceptExtra) + "_quids.tab";
00239 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00240 String fName = vs->GetFilePathAnnotation(qName, true, false);
00241 if (!fName.empty())
00242 Table::Write(mQuidExtra, fName, vs->GetDatabase(), true);
00243 #else // REPOSITORY_USED
00244 Persistency::QuidTableLocator qLoc(vs->GetLocator(), "Annotations",
00245 qName);
00246 Persistency::QuidTableRepository().Add(qLoc, mQuidExtra);
00247 #endif // REPOSITORY_USED
00248 }
00249 }
00250
00251 private:
00252
00253 void
00254 AddExtra(VideoSet* vs, int fileId, int concept, Mpeg7Doc* mp7, int key,
00255 int idx)
00256 {
00257 Table::AnnotationTable* frameExtra = mAnnoExtra->GetTable(concept);
00258 int shot = mKeyframes->GetShotId(key);
00259 int begin = Max(mSegmentation->GetStart(shot), mp7->StartFrame(idx));
00260 int end = Max(mSegmentation->GetEnd(shot), mp7->EndFrame(idx));
00261 int step = (end - begin) / (mNrExtra + 2);
00262 int frame = begin + step;
00263 while (frame <= end - step)
00264 {
00265 Quid q = MakeQuidFrame(vs->GetSetId(), fileId, frame);
00266 if (!frameExtra->IsAnnotated(q))
00267 {
00268 frameExtra->AddPositive(q);
00269 if (!mQuidExtra->Contains(q))
00270 mQuidExtra->Add(q);
00271 }
00272 frame += step;
00273 }
00274 }
00275
00276 void
00277 DoKeyframes(VideoSet* vs, int fileId, int concept, Mpeg7Doc* mp7)
00278 {
00279 Table::AnnotationTable* frameTable = mAnnoFrame->GetTable(concept);
00280 Table::AnnotationTable* frameExtra = 0;
00281 if (mAnnoExtra)
00282 frameExtra = mAnnoExtra->GetTable(concept);
00283 int startKey = mKeyframes->GetFirstKeyframeVideo(fileId);
00284 int endKey = startKey + mKeyframes->GetNrKeyframesVideo(fileId);
00285 for (int k=startKey ; k<endKey ; k++)
00286 {
00287 if (mRkfMask && (!mKeyframes->IsRKF(k)))
00288 continue;
00289 int frame = mKeyframes->GetFrameNr(k);
00290 int idx = mp7->FindShot(frame);
00291 if (idx != -1)
00292 {
00293 Quid q = MakeQuidFrame(vs->GetSetId(), fileId, frame);
00294 if (mQuidExtra && (!mQuidExtra->Contains(q)))
00295 mQuidExtra->Add(q);
00296 if (mp7->IsPositiveAnno(idx))
00297 {
00298 frameTable->AddPositive(q);
00299 if (frameExtra)
00300 {
00301 frameExtra->AddPositive(q);
00302 int len = mp7->EndFrame(idx) - mp7->StartFrame(idx);
00303 if (len > 1)
00304 {
00305 AddExtra(vs, fileId, concept, mp7, k, idx);
00306 }
00307 }
00308 }
00309 else if (mp7->IsNegativeAnno(idx))
00310 {
00311 frameTable->AddNegative(q);
00312 if (frameExtra)
00313 frameExtra->AddNegative(q);
00314 }
00315 else
00316 {
00317 frameTable->AddSkip(q);
00318 if (frameExtra)
00319 frameExtra->AddSkip(q);
00320 }
00321 }
00322 }
00323 }
00324
00325 void
00326 DoShots(VideoSet* vs, int fileId, int concept, Mpeg7Doc* mp7)
00327 {
00328 Table::AnnotationTable* shotTable = mAnnoShot->GetTable(concept);
00329 int startShot = mSegmentation->GetFirstShotVideo(fileId);
00330 int endShot = startShot + mSegmentation->GetNrShotsVideo(fileId);
00331 for (int s=startShot ; s<endShot ; s++)
00332 {
00333 int startFrame = mSegmentation->GetStart(s);
00334 int endFrame = mSegmentation->GetEnd(s);
00335 std::vector<int> idx = mp7->FindShots(startFrame, endFrame);
00336
00337 if (idx.size() > 0)
00338 {
00339 Quid q = MakeQuidShot(vs->GetSetId(), fileId, s - startShot);
00340
00341 bool hasPos = false;
00342 bool hasNeg = false;
00343 for (int i=0 ; i<idx.size() ; i++)
00344 {
00345 if (mp7->IsPositiveAnno(idx[i]))
00346 hasPos = true;
00347 else if (mp7->IsNegativeAnno(idx[i]))
00348 hasNeg = true;
00349 }
00350
00351 if (hasPos)
00352 shotTable->AddPositive(q);
00353 else if (hasNeg)
00354 shotTable->AddNegative(q);
00355 else
00356 shotTable->AddSkip(q);
00357 }
00358 }
00359 }
00360
00361 Reporter* mReporter;
00362 String mConceptSet;
00363 String mConceptExtra;
00364 int mNrExtra;
00365 Segmentation* mSegmentation;
00366 Keyframes* mKeyframes;
00367 bool mRkfMask;
00368 std::vector<String> mConcepts;
00369 Table::AnnotationTableSet* mAnnoShot;
00370 Table::AnnotationTableSet* mAnnoFrame;
00371 Table::AnnotationTableSet* mAnnoExtra;
00372 Table::QuidTable* mQuidExtra;
00373
00374 std::vector<int> mTotalNrAnno;
00375 std::vector<int> mTotalNrSingleFrame;
00376 std::vector<int> mTotalNrFrames;
00377 std::vector<int> mTotalNrAnnoPos;
00378 std::vector<int> mTotalNrSingleFramePos;
00379 std::vector<int> mTotalNrFramesPos;
00380
00381 ILOG_VAR_DEC;
00382
00383 };
00384
00385 ILOG_VAR_INIT(IndexAnnotation, Impala.Core.VideoSet);
00386
00387 }
00388 }
00389 }
00390
00391 #endif