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

LbpEval.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_VideoSet_LbpEval_h
00002 #define Impala_Core_VideoSet_LbpEval_h
00003 
00004 #include "Core/Array/RGB2Gray.h"
00005 #include "Core/Feature/Computor.h"
00006 #include "Core/VideoSet/Reporter.h"
00007 #include "Core/Geometry/PointR.h"
00008 #include "Core/Geometry/PointZ.h"
00009 #include "Core/Histogram/MakeCooccurenceMatrix.h"
00010 #include "Core/Histogram/Histogram2dTem.h"
00011 #include "Core/Feature/MarkovStationaryFeature.h"
00012 
00013 namespace Impala
00014 {
00015 namespace Core
00016 {
00017 namespace VideoSet
00018 {
00019 
00020 namespace BitOperation
00021 {
00022     int onecount(unsigned int c, int bits)
00023     {
00024         int count = 0, base = 1;
00025         for (int i=0;i<bits;i++)
00026         {
00027             if (c & base)
00028                 count++;
00029             base <<= 1;
00030         }
00031         return count;
00032     }
00033 
00034     int transitions(unsigned int c, int bits)
00035     {
00036         int base = 1;
00037         int current = c & base;
00038         int current2;
00039         int changes = 0;
00040         for (int i=1;i<bits;i++)
00041         {
00042             base <<= 1;
00043             current2 = (c & base) >> i;
00044             if (current ^ current2)
00045                 changes++;
00046             current = current2;
00047         }
00048         return changes; //(changes <= 2)? 1 : 0;
00049     }
00050 }
00051 
00052 void MakeMap(int samples, int*& map)
00053 {
00054     ILOG_VAR(Impala.Core.VidSet.LbpEval.MakeMap);
00055     ILOG_DEBUG("creating map");
00056     int size = 1<<samples;
00057     map = new int[size];
00058     for (int i=0;i<(1<<samples);i++)
00059     {
00060         if (BitOperation::transitions(i,samples) <= 2)
00061             map[i] = BitOperation::onecount(i,samples);
00062         else
00063             map[i] = samples+1;
00064     }
00065 }
00066 
00067 void MakePoints(int samples, int radius, Geometry::PointZ*& points, double*& multipliers)
00068 {
00069     points = new Geometry::PointZ[samples];
00070     multipliers = new double[samples*4];
00071     Geometry::PointR* offsets = new Geometry::PointR[samples];
00072 
00073     double step = 2 * M_PI / samples;
00074     for (unsigned int i=0;i<samples;i++)
00075     {
00076         double tmpX = radius * cos(i * step);
00077         double tmpY = radius * sin(i * step);
00078         points[i].mX = (int)tmpX;
00079         points[i].mY = (int)tmpY;
00080         offsets[i].mX = tmpX - points[i].mX;
00081         offsets[i].mY = tmpY - points[i].mY;
00082         if (offsets[i].mX < 1.0e-10 && offsets[i].mX > -1.0e-10) //rounding error
00083             offsets[i].mX = 0;
00084         if (offsets[i].mY < 1.0e-10 && offsets[i].mY > -1.0e-10) //rounding error
00085             offsets[i].mY = 0;
00086         
00087         if (tmpX < 0 && offsets[i].mX != 0)
00088         {
00089             points[i].mX -= 1;
00090             offsets[i].mX += 1;
00091         }
00092         if (tmpY < 0 && offsets[i].mY != 0)
00093         {
00094             points[i].mY -= 1;
00095             offsets[i].mY += 1;
00096         }
00097 
00098         double dx = 1-offsets[i].mX;
00099         double dy = 1-offsets[i].mY;
00100         multipliers[i*4+0] = dx*dy;
00101         multipliers[i*4+1] = offsets[i].mX*dy;
00102         multipliers[i*4+2] = dx*offsets[i].mY;
00103         multipliers[i*4+3] = offsets[i].mX*offsets[i].mY;
00104     }
00105     delete offsets;
00106 }
00107 
00108 template <class T>
00109 inline double
00110 InterpolateAtPtr(T* ptr, int i, int width, double* multipliers)
00111 {
00112     if(multipliers[(i*4)] != 1.0)
00113     {
00114         return ptr[0] * multipliers[(i*4)] + 
00115                ptr[1] * multipliers[(i*4)+1] + 
00116                ptr[width] * multipliers[(i*4)+2] + 
00117                ptr[width+1] * multipliers[(i*4)+3] + 1e-10;
00118     }
00119     return ptr[0];
00120 }
00121 
00122 
00123 void
00124 Lbp(Array::Array2dScalarUInt8*& dst,
00125     Array::Array2dScalarReal64* src,
00126     int* patternMap,
00127     int samples,
00128     int radius)
00129 {
00130     ILOG_VAR(Impala.Core.VidSet.LbpEval);
00131     int border2 = radius * 2;
00132     int height = src->CH();
00133     int width = src->CW();
00134     if(dst == 0)
00135         dst = new Array::Array2dScalarUInt8(width - border2, height - border2, 0, 0);
00136     if(patternMap == 0)
00137     {
00138         ILOG_ERROR("LBP features without map not supported");
00139         return;
00140     }
00141     
00142     // by multiplying with width+1 we go down and sideways at the same time
00143     double* center = src->CPB() + radius * (1 + width);
00144     double** ptr = new double*[samples];
00145     Geometry::PointZ* points;
00146     double* multipliers;
00147     MakePoints(samples, radius, points, multipliers);
00148 
00149     for(int i=0 ; i<samples ; i++)
00150         ptr[i] = center + points[i].mX + points[i].mY * width;
00151 
00152     for(int y=0 ; y<height-border2 ; y++)
00153     {
00154         unsigned char* dstPtr = dst->CPB(0,y);
00155         for(int x=0 ; x<width-border2 ; x++)
00156         {
00157             unsigned int value = 0;
00158             unsigned int base = 1;
00159             for (int i=0;i<samples;i++)
00160             {
00161                 if (InterpolateAtPtr(ptr[i],i,width,multipliers) >= *center)
00162                     value |= base;
00163                 base <<= 1;
00164                 ptr[i]++;
00165             }
00166             center++;
00167             *dstPtr = patternMap[value];
00168             ++dstPtr;
00169         }
00170         for(int i=0 ; i<samples ; i++)
00171             ptr[i] += border2;
00172         center += border2;
00173     }
00174 
00175     delete points;
00176     delete multipliers;
00177     delete ptr;
00178 }
00179 
00185 class LbpEval : public Listener
00186 {
00187 public:
00188 
00189     LbpEval(Reporter* reporter, CmdOptions& options)
00190     {
00191         ILOG_DEBUG("LbpEval c'tor");
00192         int featureLengthFactor = 1;
00193         mDoMSF = options.GetBool("msf-feature");
00194         if(mDoMSF)
00195         {
00196             featureLengthFactor = 2;
00197             ILOG_INFO("computing msf feature");
00198         }
00199         else
00200         {
00201             ILOG_INFO("making histogram feature");
00202         }
00203         mReporter = reporter;
00204         mWalkType = "unknown";
00205         mIsPartial = false;
00206         mTableSet = new Feature::FeatureTableSet();
00207         int tableSize = 1000;
00208         int regions = 6;
00209         mMaps = new int*[3];
00210         mTableSet->Add(new Feature::FeatureTable(GetDefinition(8, 1.0), tableSize,
00211                                         (8+2)*featureLengthFactor*regions));
00212         MakeMap(8, mMaps[0]);
00213         mTableSet->Add(new Feature::FeatureTable(GetDefinition(16, 2.0), tableSize,
00214                                         (16+2)*featureLengthFactor*regions));
00215         MakeMap(16, mMaps[1]);
00216         mTableSet->Add(new Feature::FeatureTable(GetDefinition(24, 3.0), tableSize,
00217                                         (24+2)*featureLengthFactor*regions));
00218         MakeMap(24, mMaps[2]);
00219     }
00220 
00221     virtual ~LbpEval()
00222     {
00223         delete mMaps[0];
00224         delete mMaps[1];
00225         delete mMaps[2];
00226         delete mTableSet;
00227     }
00228 
00229     virtual void
00230     HandleNewWalkPartial(VideoSet* vs, int startFrame, int stepSize,
00231                          int numberFrames)
00232     {
00233         mIsPartial = true;
00234         mStartFrame = startFrame;
00235     }
00236 
00237     virtual void
00238     HandleNewWalk(VideoSet* vs, String walkType)
00239     {
00240         mWalkType = walkType;
00241     }
00242 
00243     virtual void
00244     HandleNewFrame(VideoSet* vs, int fileId, Stream::RgbDataSrc* src)
00245     {
00246         Array::Array2dVec3UInt8* im = Array::ArrayCreate<Array::Array2dVec3UInt8>
00247             (src->FrameWidth(), src->FrameHeight(), 0, 0, src->DataPtr(), true);
00248         Array::Array2dScalarReal64* greyim = 0;
00249         Array::RGB2Gray(greyim, im);
00250         delete im;
00251         Quid quid = vs->GetQuidFrame(fileId, src->FrameNr());
00252         for(int i=0 ; i<mTableSet->Size() ; ++i)
00253         {
00254             Feature::FeatureDefinition fd = mTableSet->GetFeatureDefinition(i);
00255             //ILOG_DEBUG("processing " << fd.AsString());
00256             int samples = atoi(fd.GetParameterValue("samples"));
00257             int radius = atoi(fd.GetParameterValue("radius"));
00258             Array::Array2dScalarUInt8* lbpIm = 0;
00259             Lbp(lbpIm, greyim, mMaps[i], samples, radius);
00260 
00261             //here we could loop over the image parts (patatsnijden)
00262             Vector::VectorTem<Real64> vector;
00263             Vector::VectorTem<Real64>& accu = vector;
00264             std::vector<Geometry::Rectangle> rects;
00265             ILOG_DEBUG("greyim w:"<<lbpIm->CW()<<" h:"<<lbpIm->CH());
00266             GetRectangles(rects, lbpIm->CW(), lbpIm->CH(), radius);
00267             for(int r=0 ; r<6 ; ++r)
00268             {
00269                 ILOG_DEBUG("rect "<<r<<" -> "<<rects[r]);
00270             }
00271             for(int r=0 ; r<6 ; ++r)
00272             {
00273                 //either simple histogram, or cooccurence matrix
00274                 if(mDoMSF)
00275                 {
00276                     Histogram::Histogram2dTem<double> hist(-1.5, samples+1.5, samples+2, -1.5, samples+1.5, samples+2);
00277                     Histogram::MakeCooccurenceMatrix(&hist, lbpIm, rects[i]);
00278                     const Vector::VectorTem<Real64>& v =
00279                         Feature::MarkovStationaryFeature(&hist);
00280                     accu = Append(accu, v);
00281                 }
00282                 else
00283                 {
00284                     double dummy=0;
00285                     Histogram::Histogram1dTem<double> hist(-0.5, samples+1.5, samples+2, &dummy);
00286                     MakeHistogram1d(&hist, lbpIm, rects[i]);
00287                     hist.Normalize();
00288                     if(dummy != 0)
00289                         ILOG_ERROR("lbp with map should not create outliers in histogram");
00290                     accu = Append(accu, hist);
00291                 }
00292             }
00293             ILOG_DEBUG("feature length: " << accu.Size());
00294             Feature::FeatureTable* t = mTableSet->GetTable(i);
00295             t->Add(quid, accu);
00296             delete lbpIm;
00297         }
00298         delete greyim;
00299     }
00300 
00301     virtual void
00302     HandleDoneFile(VideoSet* vs, int fileId, Stream::RgbDataSrc* src)
00303     {
00304         bool binary = true;
00305         for (int i=0 ; i<mTableSet->Size() ; i++)
00306         {
00307             if (mIsPartial && (mTableSet->GetTable(i)->Size() < 2))
00308                 continue;
00309             Feature::FeatureDefinition def = mTableSet->GetFeatureDefinition(i);
00310             String fName = vs->GetFilePathFeatureData(mWalkType, def, fileId,
00311                                                       mIsPartial, mStartFrame,
00312                                                       true, false);
00313             if (!fName.empty())
00314             {
00315                 Table::Write(mTableSet->GetTable(i), fName, vs->GetDatabase(),
00316                              binary);
00317             }
00318             mTableSet->GetTable(i)->SetSize(0);
00319         }
00320     }
00321 
00322     virtual void
00323     HandleDoneWalk(VideoSet* vs)
00324     {
00325 //        std::cout << "Feature definitions: " << std::endl;
00326 //        for (int i=0 ; i<mTableSet->Size() ; i++)
00327 //            std::cout << mTableSet->GetDefinitionAsString(i) << std::endl;
00328     }
00329 
00330 private:
00331     void
00332     GetRectangles(std::vector<Geometry::Rectangle>& rects, int width, int height, int border)
00333     {
00334         rects.resize(6);
00335         int halfWidth = width/2;
00336         int halfHeight = height/2;
00337         rects[0] = Geometry::Rectangle(border, border, width-border-1, height-border-1);
00338         rects[1] = Geometry::Rectangle(border, border, halfWidth-1, halfHeight-1);
00339         rects[2] = Geometry::Rectangle(halfWidth, border, width-border-1, halfHeight-1);
00340         rects[3] = Geometry::Rectangle(border, halfHeight, halfWidth-1, height-border-1);
00341         rects[4] = Geometry::Rectangle(halfWidth, halfHeight, width-border-1, height-border-1);
00342         int width4 = width/4;
00343         int height4 = height/4;
00344         rects[5] = Geometry::Rectangle(width4, height4, height4+halfWidth-1, height4+halfHeight-1);
00345     }
00346 
00347     Feature::FeatureDefinition
00348     GetDefinition(int samples, double radius)
00349     {
00350         Feature::FeatureDefinition def("lbp");
00351         def.AddParameter("samples", samples);
00352         def.AddParameter("radius", radius);
00353         if(mDoMSF)
00354             def.AddParameter("vector", "msf");
00355         else
00356             def.AddParameter("vector", "hist");
00357         return def;
00358     }
00359 
00360     int mGridHeight;
00361     int mGridWidth;
00362     Reporter*          mReporter;
00363     String             mWalkType;
00364     bool               mIsPartial;
00365     bool               mDoMSF;
00366     int                mStartFrame;
00367     int**              mMaps;
00368     Feature::FeatureTableSet* mTableSet; // a table for each LBP variation
00369 
00370     ILOG_VAR_DEC;
00371 };
00372 
00373 ILOG_VAR_INIT(LbpEval, Impala.Core.VideoSet);
00374 
00375 
00376 } // namespace VideoSet
00377 } // namespace Core
00378 } // namespace Impala
00379 
00380 #endif

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