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;
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)
00083 offsets[i].mX = 0;
00084 if (offsets[i].mY < 1.0e-10 && offsets[i].mY > -1.0e-10)
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
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
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
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
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
00326
00327
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;
00369
00370 ILOG_VAR_DEC;
00371 };
00372
00373 ILOG_VAR_INIT(LbpEval, Impala.Core.VideoSet);
00374
00375
00376 }
00377 }
00378 }
00379
00380 #endif