Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

AnnotationTable.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_Table_AnnotationTable_h
00002 #define Impala_Core_Table_AnnotationTable_h
00003 
00004 #include "Util/QuickSort.h"
00005 #include "Util/SimpleMap.h"
00006 #include "Core/Table/SelectQuids.h"
00007 #include "Core/Table/Read.h"
00008 #include "Core/Table/Criterion.h"
00009 #include "Core/Table/CollectQuidObjects.h"
00010 #include "Core/Table/Select.h"
00011 #include "Core/Column/Find.h"
00012 #include "Core/Column/FindInAscending.h"
00013 #include "Core/VideoSet/Segmentation.h"
00014 #include "Util/QuasiRandomSequenceIterator.h"
00015 
00016 namespace Impala
00017 {
00018 namespace Core
00019 {
00020 namespace Table
00021 {
00022 
00023 
00024 typedef TableTem<Column::ColumnTem<Quid>,
00025                  Column::ColumnTem<Real64> >
00026         AnnotationTableBaseType;
00027 
00028 
00033 class AnnotationTable : public AnnotationTableBaseType
00034 {
00035 public:
00036 
00037     typedef Column::ColumnTem<Real64> ColumnReal64;
00038     typedef Column::ColumnTem<Quid> ColumnQuid;
00039 
00040     AnnotationTable() :
00041         AnnotationTableBaseType(ColumnQuid(0), ColumnReal64(0))
00042     {
00043         mLabel = "";
00044         mIsAscending = false;
00045         SetInfo("AnnotationTable");
00046         SetColName(1, "annotee");
00047         SetColName(2, "qualifier");
00048     }
00049 
00050     AnnotationTable(String label, int tableSize) :
00051         AnnotationTableBaseType(ColumnQuid(tableSize), ColumnReal64(tableSize))
00052     {
00053         mLabel = label;
00054         mIsAscending = false;
00055         SetInfo("AnnotationTable : " + label);
00056         SetColName(1, "annotee");
00057         SetColName(2, "qualifier " + label);
00058     }
00059 
00060 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00061     static AnnotationTable*
00062     MakeFromFile(String label, String fileName, Util::Database* db)
00063     {
00064         AnnotationTable* res = new AnnotationTable(label, 0);
00065         Read(res, fileName, db);
00066         //res->UpdateQuidMap();
00067         return res;
00068     }
00069 #endif // REPOSITORY_USED
00070 
00071     String
00072     GetLabel() const
00073     {
00074         return mLabel;
00075     }
00076 
00077     void
00078     SetLabel(String label)
00079     {
00080         mLabel = label;
00081     }
00082 
00083     int
00084     GetQuidClass() const
00085     {
00086         if (Size() < 1) // cannot tell
00087             return QUID_CLASS_UNKNOWN;
00088         return QuidClass(Get1(0));
00089     }
00090 
00091     bool
00092     ContainsFrames() const
00093     {
00094         return GetQuidClass() == QUID_CLASS_FRAME;
00095     }
00096 
00097     bool
00098     ContainsShots() const
00099     {
00100         return GetQuidClass() == QUID_CLASS_SHOT;
00101     }
00102 
00103     int
00104     GetNrPositive() const
00105     {
00106         int res = 0;
00107         for (int i=0 ; i<Size() ; i++)
00108             if (IsPositive(i))
00109                 res++;
00110         return res;
00111     }
00112 
00113     int
00114     GetNrNegative() const
00115     {
00116         int res = 0;
00117         for (int i=0 ; i<Size() ; i++)
00118             if (IsNegative(i))
00119                 res++;
00120         return res;
00121     }
00122 
00123     QuidTable*
00124     GetPositive() const
00125     {
00126         CriterionElement2Equals<AnnotationTableBaseType> c(1.);
00127         return SelectQuids(this, c);
00128     }
00129 
00130     QuidTable*
00131     GetNegative() const
00132     {
00133         CriterionElement2Equals<AnnotationTableBaseType> c(-1.);
00134         return SelectQuids(this, c);
00135     }
00136 
00137     QuidTable*
00138     GetAnnotatedQuids() const
00139     {
00140         CriterionElement2NotEquals<AnnotationTableBaseType> c(0.);
00141         return SelectQuids(this, c);
00142     }
00143 
00144     int
00145     GetIndex(Quid annotee) const
00146     {
00147         int index = Size();
00148         if (mQuidMap.Get(annotee, index))
00149             return index;
00150         if (mIsAscending)
00151             return Column::FindInAscending(GetColumn1(), annotee, 0, Size());
00152         return Column::Find(GetColumn1(), annotee, 0, Size());
00153     }
00154 
00155     bool
00156     IsAnnotated(Quid annotee) const
00157     {
00158         return (GetIndex(annotee) != Size());
00159     }
00160 
00161     Real64
00162     GetQualification(Quid annotee) const
00163     {
00164         int index = GetIndex(annotee);
00165         if (index != Size())
00166             return Get2(index);
00167         return -2.0;
00168     }
00169 
00170     bool
00171     IsPositive(int idx) const
00172     {
00173         return Get2(idx) == 1.0;
00174     }
00175 
00176     bool
00177     IsPositive(Quid annotee) const
00178     {
00179         int index = GetIndex(annotee);
00180         if (index != Size())
00181             return IsPositive(index);
00182         return false;
00183     }
00184 
00185     bool
00186     IsNegative(int idx) const
00187     {
00188         return Get2(idx) == -1.0;
00189     }
00190 
00191     bool
00192     IsNegative(Quid annotee) const
00193     {
00194         int index = GetIndex(annotee);
00195         if (index != Size())
00196             return IsNegative(index);
00197         return false;
00198     }
00199 
00200     bool
00201     IsSkip(int idx) const
00202     {
00203         return Get2(idx) == 0.0;
00204     }
00205 
00206     bool
00207     IsSkip(Quid annotee) const
00208     {
00209         int index = GetIndex(annotee);
00210         if (index != Size())
00211             return IsSkip(index);
00212         return false;
00213     }
00214 
00215     void
00216     AddPositive(Quid annotee)
00217     {
00218         Add(annotee, 1.0);
00219     }
00220 
00221     void
00222     AddNegative(Quid annotee)
00223     {
00224         Add(annotee, -1.0);
00225     }
00226 
00227     void
00228     AddSkip(Quid annotee)
00229     {
00230         Add(annotee, 0.0);
00231     }
00232 
00233     // limit annotations to those within the given QuidObject (video) id
00234     void
00235     SelectQuidObjectMaxId(int maxId)
00236     {
00237         if (maxId == -1)
00238             return;
00239 
00240         CriterionQuidObjectMaxId<AnnotationTable> crit(maxId);
00241         Select(this, this, crit, true);
00242     }
00243 
00244     // limit the number of positive annotations per QuidObject (video)
00245     void
00246     SelectQuidObjectMaxPositive(int number)
00247     {
00248         if (number == -1)
00249             return;
00250 
00251         CriterionQuidObjectMaxNumberElement2<AnnotationTable> crit(1.0, number);
00252         Select(this, this, crit, true);
00253     }
00254 
00255     // limit the number of negative annotations per QuidObject (video)
00256     void
00257     SelectQuidObjectMaxNegative(int number)
00258     {
00259         if (number == -1)
00260             return;
00261 
00262         CriterionQuidObjectMaxNumberElement2<AnnotationTable> crit(-1.0, number);
00263         Select(this, this, crit, true);
00264     }
00265 
00266     void
00267     UpdateQuidMap()
00268     {
00269         mIsAscending = true;
00270         for (int i=0 ; i<Size()-1 ; i++)
00271         {
00272             if (Get1(i+1) < Get1(i))
00273             {
00274                 mIsAscending = false;
00275                 break;
00276             }
00277         }
00278         if (!mIsAscending)
00279         {
00280             for (int i=0 ; i<Size() ; i++)
00281                 mQuidMap.Add(Get1(i), i);
00282         }
00283     }
00284 
00285     int
00286     Diff(AnnotationTable* arg) const
00287     {
00288         if (Size() != arg->Size())
00289         {
00290             ILOG_ERROR("Diff: Size differs: " << Size() << " vs " <<
00291                        arg->Size());
00292             return 1;
00293         }
00294         int nDiff = 0;
00295         for (int i=0 ; i<Size() ; i++)
00296         {
00297             if (Get1(i) != arg->Get1(i))
00298             {
00299                 ILOG_DEBUG("Quid " << i << " differs " << Get1(i) <<
00300                            " vs " << arg->Get1(i));
00301                 nDiff++;
00302             }
00303             else if (::fabs(Get2(i) -arg->Get2(i)) > 0.00001)
00304             {
00305                 ILOG_DEBUG("Anno " << i << " differs " << Get2(i) <<
00306                            " vs " << arg->Get2(i));
00307                 nDiff++;
00308             }
00309         }
00310         if (nDiff > 0)
00311             ILOG_ERROR("Found " << nDiff << " differences");
00312         return nDiff;
00313     }
00314 
00315     virtual void
00316     Dump(int from = 0, int to = -1)
00317     {
00318         if (to == -1 || to > Size())
00319             to = Size();
00320         if (to < from)
00321             to = from;
00322         if (to <= from)
00323             return ;
00324 
00325         std::cout << "Dumping table from " << from << " to " << to
00326                   << " (table size=" << Size() << ", capacity=" << Capacity()
00327                   << ")" << std::endl;
00328         for (int i=0 ; i<2 ; i++)
00329             std::cout << i+1 << "=" << GetColName(i+1) << ", ";
00330         std::cout << std::endl;
00331         for (int i=from ; i<to ; i++)
00332         {
00333             std::cout << QuidObj(Get1(i)) << ", " << Get2(i) << std::endl;
00334         }
00335         std::cout << std::endl;
00336     }
00337 
00338     virtual void
00339     Dump(Database::RawDataSet* dataSet, int from = 0, int to = -1)
00340     {
00341         if (dataSet == 0)
00342             return Dump(from, to);
00343 
00344         if (to == -1 || to > Size())
00345             to = Size();
00346         if (to < from)
00347             to = from;
00348         if (to <= from)
00349             return ;
00350 
00351         std::cout << "Dumping table from " << from << " to " << to
00352                   << " (table size=" << Size() << ", capacity=" << Capacity()
00353                   << ")" << std::endl;
00354         for (int i=0 ; i<2 ; i++)
00355             std::cout << i+1 << "=" << GetColName(i+1) << ", ";
00356         std::cout << std::endl;
00357         for (int i=from ; i<to ; i++)
00358         {
00359             Quid quid = Get1(i);
00360             std::cout << dataSet->QuidToString(quid, true) << ", " << Get2(i)
00361                       << std::endl;
00362         }
00363         std::cout << std::endl;
00364     }
00365 
00366     void
00367     DumpSummary()
00368     {
00369         int pos=0, neg=0, skip=0;
00370         for (int i=0 ; i<Size() ; ++i)
00371         {
00372             if (IsPositive(i))
00373                 ++pos;
00374             else if (IsNegative(i))
00375                 ++neg;
00376             else
00377                 ++skip;
00378         }
00379         std::cout << GetLabel() << " : " << pos << " positive, " << neg
00380                   << " negative, " << skip << " skip, " << Size() << " total"
00381                   << std::endl;
00382     }
00383 
00384     void
00385     DumpSummaryObject()
00386     {
00387         std::vector<int> objs = CollectQuidObjects(this);
00388         for (int i=0 ; i<objs.size() ; i++)
00389         {
00390             std::cout << "  obj=" << objs[i] << " : ";
00391             std::vector<int> oneObj;
00392             oneObj.push_back(objs[i]);
00393             CriterionQuidObjectInSet<AnnotationTable> crit(oneObj);
00394             AnnotationTable* tmp = Select(this, crit);
00395             tmp->DumpSummary();
00396             delete tmp;
00397         }
00398     }
00399 
00400 
00405     std::vector<QuidTable*>
00406     MakeEpisodeFolds(int foldCount, int repetition)
00407     {
00408         ILOG_DEBUG("entering MakeEpisodeFolds");
00409 
00410         int quidclass = GetQuidClass();
00411         if(quidclass != QUID_CLASS_SHOT &&
00412            quidclass != QUID_CLASS_KEYFRAME &&
00413            quidclass != QUID_CLASS_FRAME)
00414         {
00415             ILOG_WARNING_ONCE("annotees of wrong quidclass, cannot do episode " <<
00416                               "constrained");
00417             return MakeRandomFolds(foldCount, repetition);
00418         }
00419 
00420         if(foldCount <= 1)
00421         {
00422             ILOG_ERROR("we need at least 2 folds");
00423             return std::vector<QuidTable*>(1, GetAnnotatedQuids());
00424         }
00425 
00426         QuidTable* positive = GetPositive();
00427         QuidTable* negative = GetNegative();
00428         ILOG_DEBUG_NODE("make episode folds: #annotations = " <<
00429                         positive->Size() + negative->Size());
00430 
00431         // group per video
00432         std::vector<int> positiveVideos;
00433         std::vector<int> negativeVideos;
00434         GroupPerVideo(positive, negative, positiveVideos, negativeVideos);
00435         delete positive;
00436         delete negative;
00437 
00438         std::vector<QuidTable*> folds;
00439         for(int i=0 ; i<foldCount ; i++)
00440             folds.push_back(new QuidTable(0));
00441 
00442         // distribute 'positive' videos
00443         int lastFold=0;
00444         Util::QuasiRandomSequenceIterator pos(positiveVideos.size(),repetition);
00445         for(int i=0 ; i<positiveVideos.size() ; ++i)
00446         {
00447             CriterionQuidObjectEquals<AnnotationTable>
00448                 c(positiveVideos[*pos]);
00449             SelectOneColumn(folds[lastFold], this, 1, c, false);
00450             ++pos;
00451             ++lastFold;
00452             if(lastFold >= foldCount)
00453                 lastFold = 0;
00454         }
00455 
00456         // distribute 'negative' videos
00457         Util::QuasiRandomSequenceIterator neg(negativeVideos.size(),repetition);
00458         for(int i=0 ; i<negativeVideos.size() ; ++i)
00459         {
00460             CriterionQuidObjectEquals<AnnotationTable>
00461                 c(negativeVideos[*neg]);
00462             SelectOneColumn(folds[lastFold], this, 1, c, false);
00463             ++neg;
00464             ++lastFold;
00465             if(lastFold >= foldCount)
00466                 lastFold = 0;
00467         }
00468 
00469         ILOG_DEBUG("leaving MakeFolds");
00470         return folds;
00471     }
00472 
00473     std::vector<QuidTable*>
00474     MakeRandomFolds(int foldCount, int repetition)
00475     {
00476         if(foldCount <= 1)
00477         {
00478             ILOG_ERROR("we need at least 2 folds");
00479             return std::vector<QuidTable*>(1, GetAnnotatedQuids());
00480         }
00481 
00482         QuidTable* positive = GetPositive();
00483         QuidTable* negative = GetNegative();
00484         ILOG_DEBUG_NODE("make random folds: #annotations = " <<
00485                         positive->Size() + negative->Size());
00486 
00487         std::vector<QuidTable*> folds;
00488         for(int i=0 ; i<foldCount ; ++i)
00489             folds.push_back(new QuidTable(0));
00490 
00491         int lastFold=0;
00492         Util::QuasiRandomSequenceIterator pos(positive->Size(), repetition);
00493         for(int i=0 ; i<positive->Size() ; ++i)
00494         {
00495             folds[lastFold]->Add(positive->Get1(*pos));
00496             ++pos;
00497             ++lastFold;
00498             if(lastFold >= foldCount)
00499                 lastFold = 0;
00500         }
00501         for (int i=0 ; i<foldCount ; i++)
00502         {
00503             ILOG_DEBUG("fold "<< i <<" has "<< folds[i]->Size() <<" positives");
00504             if (folds[i]->Size() == 0)
00505                 ILOG_ERROR("fold "<< i <<" has NO positives");
00506         }
00507 
00508         Util::QuasiRandomSequenceIterator neg(negative->Size(), repetition);
00509         for(int i=0 ; i<negative->Size() ; ++i)
00510         {
00511             folds[lastFold]->Add(negative->Get1(*neg));
00512             ++neg;
00513             ++lastFold;
00514             if(lastFold >= foldCount)
00515                 lastFold = 0;
00516         }
00517 
00518         delete positive;
00519         delete negative;
00520         return folds;
00521     }
00522 
00529     void Sort()
00530     {
00531         Util::QuickSortDescCo
00532             (GetColumn2()->GetData(), GetColumn1()->GetData(), 0, Size()-1);
00533         //sort positive examples
00534         int to;
00535         for(int i=0 ; i<Size() ; ++i)
00536         {
00537             to = i;
00538             if(Get2(i) != 1)
00539                 break;
00540         }
00541         Util::QuickSort(GetColumn1()->GetData(), 0, to-1);
00542         //sort negative examples
00543         int from;
00544         for(int i=to ; i<Size() ; ++i)
00545         {
00546             from = i;
00547             if(Get2(i) == -1)
00548                 break;
00549         }
00550         Util::QuickSort(GetColumn1()->GetData(), from, Size()-1);
00551     }
00552 
00553 private:
00554 
00555     String                     mLabel;
00556     bool                       mIsAscending;
00557     Util::SimpleMap<Quid, int> mQuidMap;
00558 
00559     /* helper function for MakeFolds, facilitates episode constraining by
00560     grouping video ids (QuidObject(Quid q)) of videos that contain positive
00561     examples vs. videos that do not */ 
00562     void GroupPerVideo(const QuidTable* positive,
00563                        const QuidTable* negative,
00564                        std::vector<int>& positiveVideos,
00565                        std::vector<int>& negativeVideos)
00566     {
00567         Quid lastQuid=0;
00568         // collect all the videoIDs with a positive annotated framequide
00569         for(int i=0 ; i<positive->Size() ; i++)
00570         {
00571             Quid q = positive->Get1(i);
00572             /* QuidObjectEqual is false initially because 0 is not a valid quid.
00573             The object of a framequid is a video. */
00574             if(!QuidObjectEqual(lastQuid,q)) 
00575             {
00576                 lastQuid = q;
00577                 int videoID = QuidObject(q);
00578                 if(find(positiveVideos.begin(), positiveVideos.end(), videoID)
00579                     == positiveVideos.end())
00580                 {
00581                     positiveVideos.push_back(videoID);
00582                 }
00583             }
00584         }
00585 
00586         lastQuid=0;
00587         // collect all the videoIDs with no positive annotated frame, which can
00588         // of course not be in positiveVideos
00589         for(int i=0 ; i<negative->Size() ; i++)
00590         {
00591             Quid q = negative->Get1(i);
00592             if(!QuidObjectEqual(lastQuid,q))
00593             {
00594                 lastQuid = q;
00595                 int videoID = QuidObject(q);
00596                 if(find(positiveVideos.begin(), positiveVideos.end(), videoID)
00597                     == positiveVideos.end())
00598                 {
00599                     if(find(negativeVideos.begin(), negativeVideos.end(),
00600                             videoID) == negativeVideos.end())
00601                     {
00602                         negativeVideos.push_back(videoID);
00603                     }
00604                 }
00605             }
00606         }
00607     }
00608 
00609 
00610 
00611     ILOG_VAR_DEC;
00612 };
00613 
00614 ILOG_VAR_INIT(AnnotationTable, Impala.Core.Table);
00615 
00616 } // namespace Table
00617 } // namespace Core
00618 } // namespace Impala
00619 
00620 #endif

Generated on Fri Mar 19 09:31:19 2010 for ImpalaSrc by  doxygen 1.5.1