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

InterestPointFeature.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_Feature_InterestPointFeature_h
00002 #define Impala_Core_Feature_InterestPointFeature_h
00003 
00004 #include "Core/Array/MakeRoi.h"
00005 #include "Core/Geometry/Rectangle.h"
00006 #include "Core/Feature/FeatureDefinition.h"
00007 #include "Core/Feature/FeatureTable.h"
00008 #include "Core/Feature/Surf.h"
00009 #include "Core/Feature/RandomForest.h"
00010 #include "Basis/Timer.h"
00011 
00012 #include "Core/Matrix/MatNorm2Dist.h"
00013 #include "Core/Matrix/VectorQuantize.h"
00014 #include "Core/Matrix/MatTrace.h"
00015 #include "Core/Matrix/MatEye.h"
00016 #include "Util/Random.h"
00017 
00018 #include "Core/Feature/RegionDescriptor.h"
00019 #include "Core/Feature/KoenFIST2.h"
00020 #include "Core/Feature/HarrisLaplaceDetector.h"
00021 #include "Core/Feature/LaplacianDetector.h"
00022 #include "Core/Geometry/InterestPointSelector.h"
00023 #include "Core/Geometry/MaskedInterestPointSelector.h"
00024 
00025 #include "Core/Feature/FeatureTableResult.h"
00026 #include "Core/Feature/PointDescriptorTable.h"
00027 #include "Core/Feature/ReadCodebook.h"
00028 #include "Core/Table/Select.h"
00029 #include "Core/Matrix/MatFunc.h"
00030 #include "Persistency/RepositoryInFileSystem.h"
00031 
00032 #include <iostream>
00033 #include <fstream>
00034 #include <algorithm>
00035 
00036 namespace Impala
00037 {
00038 namespace Core
00039 {
00040 namespace Feature
00041 {
00042 
00043 
00044 class InterestPointFeature
00045 {
00046 public:
00047     typedef Array::Array2dScalarReal64 Array2dScalarReal64;
00048     typedef Matrix::Mat Mat;
00049     typedef Geometry::InterestPointSelector InterestPointSelector;
00050     typedef std::vector<Vector::VectorTem<Real64>*> CodebookVectors;
00051     typedef Persistency::FileLocator FileLocator;
00052     typedef Persistency::File File;
00053 
00054     bool              mClusterInput;
00055     FeatureTable*     mClusterInputData;
00056     String            mClusterInputImage;
00057 
00058     InterestPointFeature(CmdOptions& options) :
00059         mVerbose(0),
00060         mStripBorder(0),
00061         mUseRecGauss(false),
00062         mKeepLimited(0),
00063         mCodebook(0),
00064         mDescriptorReduce(0),
00065         mExtraBoxes(0),
00066         mResultOutput(0),
00067         mClusterInput(false),
00068         mClusterInputData(0),
00069         mDynamicPointSelector(false)
00070     {
00071         mVerbose     = options.GetInt("verb");
00072         mUseRecGauss = options.GetBool("recGauss");
00073         mStripBorder = options.GetInt("borderWidth");
00074         mOutputFormat = options.GetString("outputFormat");
00075 
00076         mClusterInput = options.GetBool("clusterInput");
00077         mKeepLimited = options.GetInt("keepLimited");
00078         if (!options.GetBool("noRandomizeSeed"))
00079             mRNG.RandomizeSeed();
00080         mTimeStats.AddGroup("detector");
00081         mTimeStats.AddGroup("descriptor");
00082         mTimeStats.AddGroup("projection");
00083 
00084         String detector    = options.GetString("detector");
00085         mName              = detector + "-" + options.GetString("descriptor");
00086         mFeatureDefinition = FeatureDefinition(options.GetString("featurePrefix") + mName);
00087 
00088         String descriptor = options.GetString("descriptor");
00089         if((descriptor.size() >= 4) &&
00090            (descriptor.substr(descriptor.size()-4,4) == "surf"))
00091         {
00092             Core::Feature::GetDSurfOptions(options, mSurfParams[0],
00093                                            mSurfParams[1], mSurfParams[2]);
00094             mFeatureDefinition.AddParameter
00095                 ("sc", MakeString(mSurfParams[0]) + "-" +
00096                  MakeString(mSurfParams[1]) + "-" + MakeString(mSurfParams[2]));
00097         }
00098         if((detector == "harrislaplace") || (detector == "harrislaplace2"))
00099         {
00100             if(options.GetString("harrisThreshold") != "1e-9")
00101             {
00102                 mFeatureDefinition.AddParameter
00103                     ("ht", options.GetString("harrisThreshold"));
00104             }
00105         }
00106         if((detector == "densesampling") || (detector == "denseall"))
00107         {
00108             // detector config
00109             int spacing = options.GetInt("ds_spacing");
00110             String scales = options.GetString("ds_scales");
00111 
00112             Util::StringParser sp(scales);
00113             while(!sp.TheEnd())
00114             {
00115                 Real64 scale = sp.GetDouble('+', false, true);
00116                 mDenseSamplingScales.push_back(scale);
00117             }
00118             if(mDenseSamplingScales.size() == 0)
00119             {
00120                 // fallback to estimate
00121                 Real64 scale = Real64(spacing) / 5;
00122                 // Most computation code uses 4*scale for the circular region size.
00123                 // Therefore, it makes sense to not provide the 'actual' region of
00124                 // interest here, but something smaller.
00125                 mDenseSamplingScales.push_back(scale);
00126             }
00127             String name = MakeString(spacing);
00128             for(int i = 0; i < mDenseSamplingScales.size(); i++)
00129             {
00130                 name += "-" + MakeString(mDenseSamplingScales[i]);
00131             }
00132             mFeatureDefinition.AddParameter("ds", name);
00133         }
00134 
00135         mDescriptorReduceFilename = options.GetString("descriptorReduce");
00136         if(!mDescriptorReduceFilename.empty())
00137             mFeatureDefinition.AddParameter("red", "1");
00138 
00139         if(!options.GetString("descriptorOpponentWeight").empty())
00140         {
00141             mFeatureDefinition.AddParameter
00142                 ("ow", options.GetString("descriptorOpponentWeight"));
00143         }
00144         if(StringStartsWith(options.GetString("pointSelector"), "dynamic-"))
00145         {
00146             // keep mPointSelector empty: we load it on-demand
00147             mDynamicPointSelector = true;
00148             String config = options.GetString("pointSelector");
00149             mFeatureDefinition.AddParameter("ps", config);
00150             config = StringReplace(config, "dynamic-", "");
00151             mDynamicPointSelectorConfig = config;
00152         }
00153         else if(options.GetString("pointSelector").size() != 0)
00154         {
00155             // filter on location (spatial pyramid)
00156             String config = options.GetString("pointSelector");
00157             String configName = config;
00158             if(config == "pyramid-1x1-2x2")
00159             {
00160                 config = "P1x1#0+P2x2#0+P2x2#1+P2x2#2+P2x2#3";
00161             }
00162             else if(config == "pyramid-1x1-2x2-3x1")
00163             {   // this is vertical (!)
00164                 config = "P1x1#0+P2x2#0+P2x2#1+P2x2#2+P2x2#3+P3x1#0+P3x1#1+P3x1#2";
00165             }
00166             else if(config == "pyramid-1x1-2x2-1x3")
00167             {
00168                 // this is division into three horizontal bars
00169                 config = "P1x1#0+P2x2#0+P2x2#1+P2x2#2+P2x2#3+P1x3#0+P1x3#1+P1x3#2";
00170             }
00171             else if(config == "pyramid-1x1-2x2-4x4")
00172             {
00173                 // this is three levels classic
00174                 config = "P1x1#0+P2x2#0+P2x2#1+P2x2#2+P2x2#3+P4x4#0+P4x4#1+P4x4#2+P4x4#3+P4x4#4+P4x4#5+P4x4#6+P4x4#7+P4x4#8+P4x4#9+P4x4#10+P4x4#11+P4x4#12+P4x4#13+P4x4#14+P4x4#15";
00175             }
00176             else if(config == "pyramid-1x1-2x2-4x4-1x3")
00177             {
00178                 // this is three levels classic plus horizontal bars
00179                 config = "P1x1#0+P2x2#0+P2x2#1+P2x2#2+P2x2#3+P4x4#0+P4x4#1+P4x4#2+P4x4#3+P4x4#4+P4x4#5+P4x4#6+P4x4#7+P4x4#8+P4x4#9+P4x4#10+P4x4#11+P4x4#12+P4x4#13+P4x4#14+P4x4#15+P1x3#0+P1x3#1+P1x3#2";
00180             }
00181             Util::StringParser sp(config);
00182             while(!sp.TheEnd())
00183             {
00184                 String selectorConfig = sp.GetString('+', false);
00185                 if(selectorConfig.size() == 0) break;
00186                 InterestPointSelector* selector =
00187                     new InterestPointSelector(selectorConfig, mStripBorder);
00188                 mPointSelector.push_back(selector);
00189             }
00190             configName = StringReplaceAll(configName, "+", "");
00191             configName = StringReplaceAll(configName, "#", "x");
00192             mFeatureDefinition.AddParameter("ps", configName);
00193         }
00194         else
00195         {
00196             // default: a filter spanning the complete image
00197             InterestPointSelector* selector =
00198                 new InterestPointSelector("P1x1#0", mStripBorder);
00199             mPointSelector.push_back(selector);
00200         }
00201     }
00202 
00203     ~InterestPointFeature()
00204     {
00205         if(mCodebook)
00206         {
00207             delete mCodebook;
00208             mCodebook = 0;
00209         }
00210     }
00211 
00212     static void AddCmdOptions()
00213     {
00214         CmdOptions& options = CmdOptions::GetInstance();
00215         options.AddOption(0, "borderWidth",      "size",        "0");
00216         options.AddOption(0, "recGauss",         "",            "0");
00217         options.AddOption(0, "loadRegions",      "filename",    "");
00218         options.AddOption(0, "saveRegions",      "filename",    "");
00219         options.AddOption(0, "descriptor",       "mode",        "");
00220         options.AddOption(0, "output",           "filename",    "");
00221         options.AddOption(0, "outputFormat",     "mode",    "");
00222         options.AddOption(0, "descriptorBinCount","bins",        "15");
00223         options.AddOption(0, "descriptorPreSmoothing","",        "0");
00224         options.AddOption(0, "descriptorOpponentWeight","weight","");
00225 
00226         /* clustering support (i.e. when not in codebook mode) */
00227         options.AddOption(0, "clusterInput",     "",            "0");
00228         options.AddOption(0, "keepLimited",      "count",       "-1");
00229         options.AddOption(0, "noRandomizeSeed",  "",            "0");
00230 
00231         /* codebook support */
00232         options.AddOption(0, "descriptorReduce", "filename",    "");
00233         options.AddOption(0, "codebook",         "filename",    "");
00234         options.AddOption(0, "codebookMode",     "name",        "hard");
00235         options.AddOption(0, "codebookSigma",    "sigma",       "");
00236         options.AddOption(0, "codebookName",     "name",        "");
00237 
00238         /* Lazebnik spatial pyramid support */
00239         options.AddOption(0, "pointSelector",    "config",      "");
00240         options.AddOption(0, "extraBoxes",       "filename",    "");
00241 
00242         /*** detectors ***/
00243         options.AddOption(0, "detector",         "mode",      "harrislaplace");
00244 
00245         /* for Harris-laplace detectors */
00246         options.AddOption(0, "harrisThreshold",  "threshold",   "1e-9");
00247         options.AddOption(0, "harrisK",          "k",           "0.06");
00248         options.AddOption(0, "laplaceThreshold", "threshold",   "0.03");
00249 
00250         /* for the dense sampling detector */
00251         options.AddOption(0, "ds_spacing",  "pixels",                  "6");
00252         options.AddOption(0, "ds_scales",   "scale1+scale2+...",       "");
00253 
00254         options.AddOption(0, "featurePrefix",   "prefix",       "");
00255 
00256         Core::Feature::AddDSurfOptions(options);
00257     }
00258 
00259 
00260     FeatureDefinition
00261     GetFeatureDefinition()
00262     {
00263         return mFeatureDefinition;
00264     }
00265 
00266     String
00267     GetFeatureName()
00268     {
00269         return mFeatureDefinition.AsString();
00270     }
00271 
00272 
00273     String
00274     GetFeatureNameShort()
00275     {
00276         return mFeatureDefinition.GetName();
00277     }
00278 
00279 
00280     void
00281     SetCodebook(String filename, const Persistency::Locator& locator)
00282     {
00283         mLocator = locator;
00284         FileLocator codebookLoc(mLocator, filename);
00285         File file = RepositoryGetFile(codebookLoc, false, false);
00286         Util::IOBuffer* buf = file.GetReadBuffer();
00287         if (!mDescriptorReduceFilename.empty())
00288         {
00289             FileLocator fLoc(mLocator, mDescriptorReduceFilename);
00290             File f = RepositoryGetFile(fLoc, false, false);
00291             ReadRaw(mDescriptorReduce, f);
00292             mFeatureDefinition.AddParameter("red", MakeString(Matrix::MatNrCol(mDescriptorReduce)));
00293         }
00294 
00295         ILOG_DEBUG("SetCodebook after IOBuffer " << buf);
00296         if (!buf)
00297         {
00298             ILOG_ERROR("SetCodebook: IOBuffer is 0");
00299             return;
00300         }
00301         mCodebook = ReadCodebookFromBuffer(buf);
00302         mCodebook->SetFeatureDefinition(FeatureDefinition(filename));
00303         delete buf;
00304         
00305         ILOG_INFO("Reading codebook: " << codebookLoc <<
00306                   "; dimensionCount = " << mCodebook->GetFeatureVectorLength()
00307                   << "; size = " << mCodebook->Size());
00308 
00309         CmdOptions& options = CmdOptions::GetInstance();
00310         String CM = options.GetString("codebookMode");
00311         if(CM != "hard")
00312         {
00313             CM = StringReplace(CM, "llcdump", "llc");
00314             if(CM == "hardindex")
00315             {
00316                 mFeatureDefinition.AddParameter
00317                     ("cm", CM + "-" + FileNameBase(filename));
00318             }
00319             else
00320             {
00321                 mFeatureDefinition.AddParameter("cm", CM);
00322             }
00323         }
00324         if(options.GetString("codebookSigma") != "")
00325         {
00326             mFeatureDefinition.AddParameter
00327                 ("cs", options.GetString("codebookSigma"));
00328         }
00329         if(options.GetString("codebookName") != "")
00330         {
00331             mFeatureDefinition.AddParameter
00332                 ("cn", options.GetString("codebookName"));
00333         }
00334 
00335         if(!options.GetString("extraBoxes").empty())
00336         {
00337             FileLocator fLoc(mLocator, options.GetString("extraBoxes"));
00338             File f = RepositoryGetFile(fLoc, false, false);
00339             ReadRaw(mExtraBoxes, f);
00340         }
00341     }
00342     
00343     void
00344     SetResultOutput(FeatureTableResult* result)
00345     {
00346         mResultOutput = result;
00347     }
00348 
00349     bool
00350     FindInterestPoints(CmdOptions& options, Array::Array2dVec3UInt8* input,
00351                        Quid quid,     // identifies input image data
00352                        String outputFilename, bool borderAlreadyRemoved=false,
00353                        Util::IOBuffer* loadRegionsFile=0)
00354     {
00355         ILOG_DEBUG("start FindInterestPoints");
00356         String saveRegionsFilename = options.GetString("saveRegions");
00357         String detectorMode = options.GetString("detector");
00358         String descriptorMode = options.GetString("descriptor");
00359         Timer timer;
00360         Array::Array2dVec3UInt8* inputNoBorder = input;
00361         if(!borderAlreadyRemoved)
00362         {
00363             // remove the border, if requested
00364             Geometry::Rectangle rect(mStripBorder, mStripBorder,
00365                                      input->CW() - mStripBorder - 1,
00366                                      input->CH() - mStripBorder - 1, true);
00367             inputNoBorder = MakeRoi(input, rect);
00368         }
00369 
00370         PointDescriptorTable* pointData = 0;
00371 
00372         /* Apply detector */
00373         ILOG_DEBUG("applying detector");
00374         mTimeStats.MeasureFirst();
00375         if(loadRegionsFile)
00376         {
00377             // load the points from file
00378             pointData = PointDescriptorTable::ImportFromBuffer(detectorMode, 
00379                                           loadRegionsFile, mStripBorder);
00380         }
00381         else
00382         {
00383             pointData = ApplyDetector(inputNoBorder, detectorMode);
00384         }
00385         if(descriptorMode.empty())
00386         {
00387             // dump the interest regions to the output stream if we are not
00388             // going to compute descriptors later
00389             pointData->ExportToFile(outputFilename, mStripBorder, 
00390                                     mOutputFormat);
00391         }
00392         if(!saveRegionsFilename.empty())
00393         {
00394             ILOG_INFO("Writing to: " << saveRegionsFilename);
00395             pointData->ExportToFile(saveRegionsFilename, mStripBorder,
00396                                     mOutputFormat);
00397         }
00398 
00399         ILOG_DEBUG("[Timing] Region loading / applying detector finished in "
00400                    << timer.SplitTimeStr());
00401 
00402         /* descriptor computation */
00403         ILOG_DEBUG("computing descriptor");
00404         mTimeStats.MeasureNext();
00405         if(descriptorMode.size() != 0)
00406         {
00407             ComputeDescriptors(pointData, inputNoBorder, descriptorMode);
00408 
00409             ILOG_DEBUG("[Timing] Descriptors finished at " << timer.SplitTimeStr());
00410             if(mCodebook)
00411             {
00412                 ILOG_DEBUG("preparing for codebook");
00413                 /* project it onto a codebook */
00414                 Timer timerProjection;
00415                 if(mExtraBoxes)
00416                 {
00417                     for(int j = 0; j < mExtraBoxes->CH(); j++)
00418                     {
00419                         if(*mExtraBoxes->CPB(0, j) == quid)
00420                         {
00421                             // it is a box for this image
00422                             Quid boxQuid = *mExtraBoxes->CPB(1, j);
00423                             UInt64 xlow = *mExtraBoxes->CPB(2, j);
00424                             UInt64 ylow = *mExtraBoxes->CPB(3, j);
00425                             UInt64 xhi = *mExtraBoxes->CPB(4, j);
00426                             UInt64 yhi = *mExtraBoxes->CPB(5, j);
00427                             UInt64 width = xhi - xlow;
00428                             UInt64 height = yhi - ylow;
00429                             // need to make a copy
00430                             PointDescriptorTable* table = new PointDescriptorTable(pointData->GetFeatureDefinition());
00431                             table->SetDescriptorLength(pointData->GetDescriptorLength());
00432                             for(int i = 0; i < pointData->Size(); i++)
00433                             {
00434                                 Real64 x = pointData->GetX(i) - xlow;
00435                                 Real64 y = pointData->GetY(i) - ylow;
00436                                 if((x < 0) || (y < 0) || (x > width) || (y > height))
00437                                 {
00438                                     continue;
00439                                 }
00440                                 table->Add(x, y, 0, 0, 0, pointData->Get6(i));
00441                             }
00442                             ILOG_DEBUG("extrabox:"<<xlow << " "<< ylow << " "<<xhi << " " << yhi << " " << table->Size() << " " << pointData->Size());
00443                             table = ProjectOntoCodebook(table,
00444                                             options.GetString("codebookMode"),
00445                                             width, height, boxQuid);
00446                             delete table;
00447                         }
00448                     }
00449                 }
00450                 else
00451                 {
00452                     mTimeStats.MeasureNext();
00453                     pointData = ProjectOntoCodebook(pointData,
00454                                        options.GetString("codebookMode"),
00455                                        inputNoBorder->CW(), inputNoBorder->CH(),
00456                                        quid);
00457                     mTimeStats.MeasureLast();
00458                     ILOG_INFO("Overall " << mTimeStats.AsString());
00459                     ILOG_DEBUG("Just codebook projection took: " <<
00460                                timerProjection.SplitTimeStr());
00461                     if(outputFilename.size() != 0)
00462                     {
00463                         pointData->ExportToFile(outputFilename, mStripBorder, 
00464                                                 mOutputFormat);
00465                     }
00466                 }
00467             }
00468             else
00469             {
00470                 // do reduction
00471                 if((mKeepLimited > 0) && (pointData->Size() > mKeepLimited))
00472                 {
00473                     ILOG_DEBUG("reducing point count");
00474                     // we might have to limit the number of points
00475                     pointData = ReducePointCount(pointData, mKeepLimited);
00476                 }
00477 
00478                 if(mClusterInput)
00479                 {
00480                     ILOG_DEBUG("doing cluster input");
00481                     int n = pointData->GetDescriptorLength();
00482                     for(int i = 0; i < pointData->Size(); i++)
00483                     {
00484                         Vector::VectorTem<Real64> descriptor(n, 
00485                             pointData->GetDescriptorData(i), true);
00486 
00487                         if(!mClusterInputData)
00488                         {
00489                             ILOG_DEBUG("initializing mClusterInputData");
00490                             // initialize the table
00491                             FeatureDefinition def = GetFeatureName();
00492                             def.AddParameter("clusterinput", "2");
00493                             mClusterInputData = new FeatureTable(def, 500, n);
00494                         }
00495 
00496                         // string representation of point:
00497                         //point->Serialize(borderOffset+1, borderOffset+1)
00498                         //mClusterInputData->Add(mClusterInputImage + " " +
00499                         //point->Serialize(), descriptor); TODO: create proper
00500                         //CLUSTERINPUT quid class
00501                         mClusterInputData->Add(mClusterInputData->Size() + 1,
00502                                                descriptor);
00503                     }
00504                     ILOG_DEBUG("done with cluster input");
00505                 }
00506                 else
00507                 {
00508                     ILOG_DEBUG("writing point list");
00509                     if(outputFilename.empty())
00510                     {
00511                         ILOG_WARN("Warning: no output file to write to. Did you forget to specify --output?");
00512                     }
00513                     else
00514                     {
00515                         pointData->ExportToFile(outputFilename, mStripBorder, 
00516                                                 mOutputFormat);
00517                     }
00518                 }
00519             }
00520             if(!borderAlreadyRemoved)
00521             {
00522                 delete inputNoBorder;
00523             }
00524         }
00525 
00526         ILOG_DEBUG("Completed " << GetFeatureName() << " in " <<
00527                    timer.SplitTimeStr());
00528         delete pointData;
00529 
00530         return true;
00531     }
00532 private:
00533     void
00534     AddToPyramids(CodebookVectors& codebookVectors, int codeword, double x, 
00535                   double y, int imageWidth, int imageHeight, 
00536                   std::vector<Real64>& regionCounts)
00537     {
00538         for(int ps = 0; ps < mPointSelector.size(); ps++)
00539         {
00540             InterestPointSelector* selector = mPointSelector[ps];
00541             if(selector->Accept(x, y, imageWidth, imageHeight))
00542             {
00543                 codebookVectors[ps]->Elem(codeword) =
00544                     codebookVectors[ps]->Elem(codeword) + 1;
00545                 regionCounts[ps] = regionCounts[ps] + 1;
00546             }
00547         }
00548     }
00549     
00550     void
00551     ProjectUNC(CodebookVectors& codebookVectors, Mat* matrixDescriptors,
00552                int imageWidth, int imageHeight, std::vector<int>& X, 
00553                std::vector<int>& Y, std::vector<Real64>& regionCounts)
00554     {
00555         using namespace Matrix;
00556         Timer timerProjection;
00557         if(mDescriptorReduce)
00558         {
00559             matrixDescriptors = MatMul(matrixDescriptors, mDescriptorReduce);
00560         }
00561         Mat* matrixCodebook = mCodebook->GetColumn2()->GetStorage();
00562         ILOG_DEBUG(MatNrRow(matrixDescriptors) << " " <<
00563                    MatNrCol(matrixDescriptors));
00564         ILOG_DEBUG(MatNrRow(matrixCodebook) << " " <<
00565                    MatNrCol(matrixCodebook));
00566         ILOG_DEBUG("Codebook projection (init) took: " <<
00567                    timerProjection.SplitTimeStr());
00568 
00569         int step = Min(Int64(10000), Int64(20000000 / mCodebook->Size()));
00570         for(int k = 0; k < MatNrRow(matrixDescriptors); k += step)
00571         {
00572             int s = MatNrRow(matrixDescriptors) - k;
00573             if(step < s) s = step;
00574     
00575             Mat* partial = MatCreate<Mat>(s, MatNrCol(matrixDescriptors),
00576                                           MatE(matrixDescriptors, k, 0), true);
00577 
00578             // result will be a (#partial-descriptors, codebook size) matrix
00579             Mat* distances = MatNorm2DistTransposed(partial,
00580                                                     matrixCodebook);
00581             delete partial;
00582             
00583             ILOG_DEBUG("Codebook projection (matrix) took: " <<
00584                        timerProjection.SplitTimeStr());
00585             CmdOptions& options = CmdOptions::GetInstance();
00586             Real64 sigma = options.GetDouble("codebookSigma");
00587 
00588             // pull a Gaussian kernel over the Euclidian distances
00589             for(int vj = 0; vj < s; vj++)
00590             {
00591                 for(int i = 0; i < mCodebook->Size(); i++)
00592                 {
00593                     Real64 value = *MatE(distances, vj, i);
00594                     *MatE(distances, vj, i) = exp((-0.5 * value * value) /
00595                                                   (sigma * sigma));
00596                 }
00597             }
00598 
00599             // sum over axis 0 for the normalization factor
00600             // expected size is (#descriptors, 1)
00601             Mat* normalizationFactor = MatSumAxis1(distances);
00602             ILOG_DEBUG("normalizationFactor: " << MatNrRow(normalizationFactor)
00603                        << " " << MatNrCol(normalizationFactor));
00604 
00605             // perform normalization
00606             for(int vj = 0; vj < s; vj++)
00607             {
00608                 for(int i = 0; i < mCodebook->Size(); i++)
00609                 {
00610                     *MatE(distances, vj, i) = *MatE(distances, vj, i) /
00611                         *MatE(normalizationFactor, vj, 0);
00612                 }
00613             }
00614             delete normalizationFactor;
00615 
00616             // remains: sum over the *right* descriptors
00617             for(int vj = 0; vj < s; vj++)
00618             {
00619                 for(int ps = 0; ps < mPointSelector.size(); ps++)
00620                 {
00621                     if(mPointSelector[ps]->Accept(X[k+vj], Y[k+vj],
00622                                                   imageWidth, imageHeight))
00623                     {
00624                         for(int i = 0; i < mCodebook->Size(); i++)
00625                         {
00626                             codebookVectors[ps]->Elem(i) =
00627                                 codebookVectors[ps]->Elem(i) +
00628                                 *MatE(distances, vj, i);
00629                         }
00630                         regionCounts[ps] = regionCounts[ps] + 1;
00631                     }
00632                 }
00633             }
00634             delete distances;
00635             ILOG_DEBUG("Codebook projection (piece) took: " <<
00636                        timerProjection.SplitTimeStr() << " " << mPointSelector.size());
00637         }
00638         ILOG_INFO("Codebook projection (UNC/" << MatNrRow(matrixDescriptors) <<
00639                   ") took: " << timerProjection.SplitTimeStr());
00640         if(mDescriptorReduce)
00641         {
00642             delete matrixDescriptors;
00643         }
00644     }
00645 
00646     void
00647     ProjectLLC(CodebookVectors& codebookVectors, String codebookMode,
00648                Mat* matrixDescriptors, int imageWidth,
00649                int imageHeight, std::vector<int>& X, std::vector<int>& Y,
00650                std::vector<Real64>& regionCounts, Util::IOBuffer* dumpIndices=0)
00651     {
00652         using namespace Matrix;
00653         Timer timerProjection;
00654         if(mDescriptorReduce)
00655         {
00656             matrixDescriptors = MatMul(matrixDescriptors, mDescriptorReduce);
00657         }
00658         Mat* matrixCodebook = mCodebook->GetColumn2()->GetStorage();
00659         ILOG_DEBUG(MatNrRow(matrixDescriptors) << " " <<
00660                    MatNrCol(matrixDescriptors));
00661         ILOG_DEBUG(MatNrRow(matrixCodebook) << " " <<
00662                    MatNrCol(matrixCodebook));
00663         ILOG_DEBUG("Codebook projection (init) took: " <<
00664                    timerProjection.SplitTimeStr());
00665 
00666         int knn = CmdOptions::GetInstance().GetInt("codebookSigma");
00667         Real64 beta = 1e-4;
00668         int step = Min(Int64(10000), Int64(20000000 / mCodebook->Size()));
00669         Mat* II = MatEye<Mat>(knn);
00670         MulVal(II, II, beta);
00671         Mat* onesVector = MatCreate<Mat>(knn, 1);
00672         SetVal(onesVector, 1.0);
00673         
00674         Mat* dumpedIndices = 0;
00675         if(dumpIndices)
00676         {
00677             dumpedIndices = MatCreate<Mat>(MatNrRow(matrixDescriptors), 2*knn+2);
00678         }
00679         String config = codebookMode;
00680         String absolute = StringSplit(config, '-');
00681         String aggregationMode = StringSplit(config, '-');
00682         String normMode = StringSplit(config, '-');
00683         ILOG_INFO("absolute=" << absolute << "; aggregationMode=" <<
00684                   aggregationMode << "; normMode=" << normMode);
00685         for(int kkk = 0; kkk < MatNrRow(matrixDescriptors); kkk += step)
00686         {
00687             int s = MatNrRow(matrixDescriptors) - kkk;
00688             if(step < s) s = step;
00689     
00690             Mat* partial = MatCreate<Mat>(s, MatNrCol(matrixDescriptors),
00691                                           MatE(matrixDescriptors, kkk, 0), true);
00692 
00693             // result will be a (#partial-descriptors, codebook size) matrix
00694             Mat* distances = MatNorm2DistTransposed(partial,
00695                                                     matrixCodebook);
00696 
00697             ILOG_DEBUG("Euclidean distance matrix took: " <<
00698                        timerProjection.SplitTimeStr());
00699                        
00700 
00701             std::vector<std::pair<Real64, int> > distancesAndIndices;
00702             // find k closest codebook elements
00703             for(int vj = 0; vj < s; vj++)
00704             {
00705                 distancesAndIndices.clear();
00706                 distancesAndIndices.reserve(mCodebook->Size());
00707                 for(int i = 0; i < mCodebook->Size(); i++)
00708                 {
00709                     distancesAndIndices.push_back(
00710                                 std::make_pair(*MatE(distances, vj, i), i));
00711                 }
00712                 std::nth_element(distancesAndIndices.begin(), 
00713                                  distancesAndIndices.begin() + knn, 
00714                                  distancesAndIndices.end());
00715                 // the first k elements are now the k smallest
00716                 
00717                 // idx = indices[:, descriptorIdx]
00718                 // z = codebook[idx, :] - 
00719                 //          numpy.tile(descriptors[descriptorIdx, :], (knn, 1))
00720                 Mat* z = MatCreate<Mat>(knn, MatNrCol(matrixDescriptors));
00721                 for(int kk = 0; kk < knn; kk++)
00722                 {
00723                     int closestCodebookIndex = distancesAndIndices[kk].second;
00724                     for(int i = 0; i < MatNrCol(matrixDescriptors); i++)
00725                     {
00726                         *MatE(z, kk, i) = *MatE(matrixCodebook, 
00727                                                 closestCodebookIndex, i) - 
00728                                           *MatE(partial, vj, i);
00729                     }
00730                 }
00731                 
00732                 // C = numpy.dot(z, z.transpose());
00733                 Mat* zT = MatTranspose(z);
00734                 Mat* C = MatMul(z, zT);
00735                 delete z; delete zT;
00736                 
00737                 // C = C + II * beta * numpy.trace(C);
00738                 Mat* tmp = 0;
00739                 MulVal(tmp, II, MatTrace(C));
00740                 Add(C, C, tmp);
00741                 delete tmp;
00742                 
00743                 Mat* invertedC = MatInverse(C);
00744                 Mat* w = MatMul(invertedC, onesVector);
00745                 delete invertedC;
00746                 delete C;
00747                 
00748                 // should we take the absolute value of w ??? TODO
00749                 
00750                 Real64 total = 0.0;
00751                 if(absolute == "llca")
00752                 {
00753                     for(int kk = 0; kk < knn; kk++)
00754                         total += fabs(*MatE(w, kk, 0));
00755                     for(int kk = 0; kk < knn; kk++)
00756                     {
00757                         *MatE(w, kk, 0) = fabs(*MatE(w, kk, 0)) / total;
00758                     }
00759                 }
00760                 else
00761                 {
00762                     for(int kk = 0; kk < knn; kk++)
00763                         total += *MatE(w, kk, 0);
00764                     for(int kk = 0; kk < knn; kk++)
00765                     {
00766                         *MatE(w, kk, 0) = *MatE(w, kk, 0) / total;
00767                     }
00768                 }
00769                 
00770                 if(aggregationMode == "avg")
00771                 {
00772                     for(int ps = 0; ps < mPointSelector.size(); ps++)
00773                     {
00774                         if(mPointSelector[ps]->Accept(X[kkk+vj], Y[kkk+vj],
00775                                                       imageWidth, imageHeight))
00776                         {
00777                             for(int kk = 0; kk < knn; kk++)
00778                             {
00779                                 int closestCodebookIndex = 
00780                                                 distancesAndIndices[kk].second;
00781                                 codebookVectors[ps]->Elem(closestCodebookIndex) =
00782                                     codebookVectors[ps]->Elem(closestCodebookIndex) + *MatE(w, kk, 0);
00783                             }
00784                             regionCounts[ps] = regionCounts[ps] + 1;
00785                         }
00786                     }
00787                 }
00788                 else if(aggregationMode == "max" || aggregationMode.empty())
00789                 {
00790                     for(int ps = 0; ps < mPointSelector.size(); ps++)
00791                     {
00792                         if(mPointSelector[ps]->Accept(X[kkk+vj], Y[kkk+vj],
00793                                                       imageWidth, imageHeight))
00794                         {
00795                             for(int kk = 0; kk < knn; kk++)
00796                             {
00797                                 int closestCodebookIndex = 
00798                                                 distancesAndIndices[kk].second;
00799                                 codebookVectors[ps]->Elem(closestCodebookIndex) =
00800                                     Max(codebookVectors[ps]->Elem(closestCodebookIndex), *MatE(w, kk, 0));
00801                             }
00802                             regionCounts[ps] = 1;
00803                         }
00804                     }
00805                 }
00806                 
00807                 // dump
00808                 if(dumpIndices)
00809                 {
00810                     *MatE(dumpedIndices, kkk+vj, 0) = X[kkk+vj];
00811                     *MatE(dumpedIndices, kkk+vj, 1) = Y[kkk+vj];
00812                     for(int kk = 0; kk < knn; kk++)
00813                     {
00814                         int closestCodebookIndex = 
00815                                         distancesAndIndices[kk].second;
00816                         *MatE(dumpedIndices, kkk+vj, kk*2 + 2) = closestCodebookIndex;
00817                         *MatE(dumpedIndices, kkk+vj, kk*2 + 3) = *MatE(w, kk, 0);
00818                     }
00819                 }
00820                 delete w;
00821             }
00822             delete partial;
00823             delete distances;
00824             ILOG_DEBUG("Codebook projection (piece) took: " <<
00825                        timerProjection.SplitTimeStr() << " " << mPointSelector.size());
00826         }
00827         delete II;
00828         delete onesVector;
00829         ILOG_INFO("Codebook projection (LLC/" << MatNrRow(matrixDescriptors) <<
00830                   ") took: " << timerProjection.SplitTimeStr());
00831         if(mDescriptorReduce)
00832         {
00833             delete matrixDescriptors;
00834         }
00835         if(normMode.empty())
00836         {
00837             // for backward compatibility
00838             for(int ps = 0; ps < mPointSelector.size(); ps++)
00839             {
00840                 regionCounts[ps] = 1;
00841             }
00842         }
00843         else if(normMode == "L2")
00844         {
00845             for(int ps = 0; ps < mPointSelector.size(); ps++)
00846             {
00847                 Real64 tmp = 0.0;
00848                 for(int i = 0; i < mCodebook->Size(); i++)
00849                 {
00850                     tmp += codebookVectors[ps]->Elem(i) * codebookVectors[ps]->Elem(i);
00851                 }
00852                 regionCounts[ps] = sqrt(tmp);
00853             }
00854         }
00855         else if(normMode == "L2a")
00856         {
00857             Real64 tmp = 0.0;
00858             for(int ps = 0; ps < mPointSelector.size(); ps++)
00859             {
00860                 for(int i = 0; i < mCodebook->Size(); i++)
00861                 {
00862                     tmp += codebookVectors[ps]->Elem(i) * codebookVectors[ps]->Elem(i);
00863                 }
00864             }
00865             for(int ps = 0; ps < mPointSelector.size(); ps++)
00866                 regionCounts[ps] = sqrt(tmp);
00867         }
00868         else if(normMode == "L1")
00869         {
00870             for(int ps = 0; ps < mPointSelector.size(); ps++)
00871             {
00872                 Real64 tmp = 0.0;
00873                 for(int i = 0; i < mCodebook->Size(); i++)
00874                 {
00875                     tmp += codebookVectors[ps]->Elem(i);
00876                 }
00877                 regionCounts[ps] = tmp;
00878             }
00879         }
00880         else if(normMode == "L1a")
00881         {
00882             Real64 total = 0.0;
00883             for(int ps = 0; ps < mPointSelector.size(); ps++)
00884             {
00885                 Real64 tmp = 0.0;
00886                 for(int i = 0; i < mCodebook->Size(); i++)
00887                 {
00888                     tmp += codebookVectors[ps]->Elem(i);
00889                 }
00890                 regionCounts[ps] = tmp;
00891                 total += tmp;
00892             }
00893             for(int ps = 0; ps < mPointSelector.size(); ps++)
00894             {
00895                 regionCounts[ps] = total;
00896             }
00897         }
00898 
00899         if(dumpIndices)
00900         {
00901             WriteRaw(dumpedIndices, dumpIndices, 3);
00902             delete dumpedIndices;
00903         }
00904     }
00905 
00906     void
00907     ProjectHardMatrix(CodebookVectors& codebookVectors, Mat* matrixDescriptors,
00908                       int imageWidth, int imageHeight, std::vector<int>& X,
00909                       std::vector<int>& Y, std::vector<Real64>& regionCounts)
00910     {
00911         using namespace Matrix;
00912         Timer timerProjection;
00913         if(mDescriptorReduce)
00914         {
00915             matrixDescriptors = MatMul(matrixDescriptors, mDescriptorReduce);
00916         }
00917         Mat* matrixCodebook = mCodebook->GetColumn2()->GetStorage();
00918         ILOG_DEBUG(MatNrRow(matrixDescriptors) << " " <<
00919                    MatNrCol(matrixDescriptors));
00920         ILOG_DEBUG(MatNrRow(matrixCodebook) << " " <<
00921                    MatNrCol(matrixCodebook));
00922         ILOG_DEBUG("Codebook projection (init) took: " <<
00923                    timerProjection.SplitTimeStr());
00924         // result will be a (#descriptors, 2) matrix
00925         Mat* assignment =
00926             Core::Matrix::VectorQuantize(matrixDescriptors, matrixCodebook);
00927             
00928         ILOG_DEBUG("Codebook projection (matrix) took: " <<
00929                    timerProjection.SplitTimeStr());
00930         for(int vj = 0; vj < MatNrRow(matrixDescriptors); vj++)
00931         {
00932             Real64 bestDistance = *MatE(assignment, vj, 1);
00933             int    bestIndex = static_cast<int>(*MatE(assignment, vj, 0));
00934             AddToPyramids(codebookVectors, bestIndex, X[vj], Y[vj], imageWidth,
00935                           imageHeight, regionCounts);
00936             //std::cout << "Codebook projection (inner loop) took: " <<
00937             //timerProjection.SplitTimeStr() << std::endl;
00938         }
00939         ILOG_DEBUG("Codebook projection (matrix-form) took: " <<
00940                    timerProjection.SplitTimeStr());
00941         delete assignment;
00942         if(mDescriptorReduce)
00943         {
00944             delete matrixDescriptors;
00945         }
00946     }
00947 
00948 
00949     void
00950     ProjectHardIndex(Mat* matrixDescriptors, PointDescriptorTable* pointData)
00951     {
00952         using namespace Matrix;
00953         Timer timerProjection;
00954         if(mDescriptorReduce)
00955         {
00956             matrixDescriptors = MatMul(matrixDescriptors, mDescriptorReduce);
00957         }
00958         Mat* matrixCodebook = mCodebook->GetColumn2()->GetStorage();
00959         ILOG_DEBUG("Codebook projection (init) took: " <<
00960                    timerProjection.SplitTimeStr());
00961         // result will be a (#descriptors, 2) matrix
00962         Mat* assignment =
00963             Core::Matrix::VectorQuantize(matrixDescriptors, matrixCodebook);
00964         ILOG_INFO("Codebook projection (matrix) took: " <<
00965                   timerProjection.SplitTimeStr());
00966 
00967         Array::Array2dScalarReal64* newDesc = new Array::Array2dScalarReal64(1, 
00968                                                    pointData->Size(), 0, 0);
00969         for(int vj = 0; vj < MatNrRow(matrixDescriptors); vj++)
00970         {
00971             Real64 bestDistance = *MatE(assignment, vj, 1);
00972             int    bestIndex = static_cast<int>(*MatE(assignment, vj, 0));
00973             *MatE(newDesc, vj, 0) = bestIndex;
00974         }
00975         // this call also takes ownership
00976         pointData->ReplaceAllDescriptors(newDesc);
00977         delete assignment;
00978         if(mDescriptorReduce)
00979         {
00980             delete matrixDescriptors;
00981         }
00982     }
00983     
00984     
00985     void
00986     ProjectForest(CodebookVectors& codebookVectors, Mat* descriptors, int imageWidth,
00987                   int imageHeight, std::vector<int>& X, std::vector<int>& Y,
00988                   std::vector<Real64>& regionCounts)
00989     {
00990         using namespace Matrix;
00991         // make trees from the table
00992         ILOG_DEBUG("creating random forest from feature table");
00993         RandomForest forest = ReadRandomForest(mCodebook);
00994         //ILOG_DEBUG("codewords: "<<GetCodebookLength(mCodebook)<<", feattable size: "<<
00995         //          mLastCodebookVectors[0]->Size() <<", desc count"<<
00996         //          MatNrRow(descriptors) <<", desc length: "<< MatNrCol(descriptors));
00997         Timer timerProjection;
00998         for(int vj = 0; vj < MatNrRow(descriptors); vj++)
00999         {
01000             for(int i=0; i<forest.size(); ++i)
01001             {
01002                 RandomTree* tree = forest[i];
01003                 ILOG_DEBUG("getting codeword");
01004                 int codeword = tree->GetCodeWord(Vector::VectorTem<Real64>(MatNrCol(descriptors), descriptors->CPB(0, vj), true));
01005                 ILOG_DEBUG("got codeword");
01006                 AddToPyramids(codebookVectors, codeword, X[vj], Y[vj], 
01007                               imageWidth, imageHeight, regionCounts);
01008             }
01009         }
01010         DeleteForest(forest);
01011         ILOG_DEBUG("Codebook projection (forest) took: " <<
01012                    timerProjection.SplitTimeStr());
01013     }
01014     
01015     PointDescriptorTable*
01016     ProjectOntoCodebook(PointDescriptorTable* pointData, String codebookMode,
01017                         int imageWidth, int imageHeight, Quid quid)
01018     {
01025         using namespace Matrix;
01026         ILOG_DEBUG("ProjectOntoCodebook called");
01027         PointDescriptorTable* output = new PointDescriptorTable(
01028                                        pointData->GetFeatureDefinition());
01029         Array::Array2dScalarInt32* tempDynamic = 0;
01030         if(mDynamicPointSelector)
01031         {
01032             // set the point selector configuration based on the image
01033             String filename = "PointSelector/" + mDynamicPointSelectorConfig +
01034                               "/" + MakeString(quid) + ".raw";
01035             FileLocator loc(mLocator, filename);
01036             File file = RepositoryGetFile(loc, false, false);
01037             Util::IOBuffer* buf = file.GetReadBuffer();
01038 
01039             // load the selectors from file
01040             ReadRaw(tempDynamic, buf);
01041             delete buf;
01042             for(int i = 0; i < tempDynamic->CH(); i++)
01043             {
01044                 *tempDynamic->CPB(0, i) -= (mStripBorder + 1);
01045                 *tempDynamic->CPB(1, i) -= (mStripBorder + 1);
01046             }
01047             
01048             for(int ps = 0; ps < tempDynamic->CW() - 2; ps++)
01049             {
01050                 mPointSelector.push_back
01051                     (new Geometry::MaskedInterestPointSelector(tempDynamic, ps));
01052             }
01053         }
01054 
01055         std::vector<Real64> regionCounts;
01056         int codebookLength = mCodebook->Size();
01057         if(codebookMode == "forest")
01058         {
01059             codebookLength = GetCodebookLength(mCodebook);
01060             ILOG_DEBUG("forest codebook length = "<< codebookLength);
01061         }
01062 
01063         CodebookVectors codebookVectors;
01064         for(int ps = 0; ps < mPointSelector.size(); ps++)
01065         {
01066             Vector::VectorTem<Real64>* codebookVector =
01067                 new Vector::VectorTem<Real64>(codebookLength);
01068             for(int i = 0; i < codebookLength; i++)
01069             {
01070                 codebookVector->Elem(i) = 0.0;
01071             }
01072             codebookVectors.push_back(codebookVector);
01073             regionCounts.push_back(0);
01074         }
01075         ILOG_DEBUG("done making codebook vector");
01076         if(pointData->Size() == 0)
01077         {
01078             if(mResultOutput)
01079             {
01080                 for(int i = 0; i < codebookVectors.size(); i++)
01081                 {
01082                     mResultOutput->AddVector(quid, i, *codebookVectors[i]);
01083                 }
01084             }
01085             delete pointData;
01086             return output;
01087         }
01088         int descriptorLength = pointData->GetDescriptorLength();
01089         std::vector<int> X;
01090         std::vector<int> Y;
01091         X.reserve(pointData->Size());
01092         Y.reserve(pointData->Size());
01093 
01094         ILOG_DEBUG("extracting descriptor data");
01095         for(int it = 0; it < pointData->Size(); it++)
01096         {
01097             X.push_back(static_cast<int>(pointData->GetX(it)));
01098             Y.push_back(static_cast<int>(pointData->GetY(it)));
01099         }
01100 
01101         // dimensionality checks
01102         if((codebookMode != "forest") &&
01103            (mCodebook->Get2(0).Size() != descriptorLength))
01104         {
01105             if(mDescriptorReduce)
01106             {
01107                 if((mCodebook->Get2(0).Size() != MatNrCol(mDescriptorReduce))
01108                    || (descriptorLength != MatNrRow(mDescriptorReduce)))
01109                 {
01110                     ILOG_ERROR("Reduced descriptor dimensionality mismatch");
01111                     throw "bye";
01112                 }
01113             }
01114             else
01115             {
01116                 ILOG_ERROR("ProjectOntoCodebook found visual word"<<
01117                        " and descriptor of different sizes!\n\t\t"<<
01118                        "codebook: "<< mCodebook->Get2(0).Size() <<
01119                        ", descriptor:"<< descriptorLength);
01120                 throw "Dimensionality mismatch!";
01121             }
01122         }
01123 
01124         // create a wrapper with the correct dimensions
01125         Array2dScalarReal64* descriptors = 
01126             new Array2dScalarReal64(descriptorLength, pointData->Size(), 0, 0,
01127             pointData->GetColumn6()->GetStorage()->mData, true);
01128             
01129         ILOG_DEBUG("extracted descriptor data");
01130 
01131         // Visual word uncertainty (UNC)
01132         if(codebookMode == "unc")
01133             ProjectUNC(codebookVectors, descriptors, imageWidth, imageHeight, 
01134                        X, Y, regionCounts);
01135         // hard assignment, matrix style
01136         if((codebookMode == "hardmatrix") || (codebookMode == "hard"))
01137             ProjectHardMatrix(codebookVectors, descriptors, imageWidth, 
01138                               imageHeight, X, Y, regionCounts);
01139         // hard assignment, matrix style, and only output the indices (special)
01140         if(codebookMode == "hardindex")
01141         {
01142             ProjectHardIndex(descriptors, pointData);
01143             delete descriptors;
01144             delete output;
01145             for(int i = 0; i < codebookVectors.size(); i++)
01146                 delete codebookVectors[i];
01147             codebookVectors.clear();
01148             return pointData;
01149         }
01150         if(codebookMode == "forest")
01151             ProjectForest(codebookVectors, descriptors, imageWidth, imageHeight,
01152                           X, Y, regionCounts);
01153         // LLC assignment, dump the indices to disk
01154         if(StringStartsWith(codebookMode, "llcdump"))
01155         {
01156             String folder = "ClusterIndices/" + GetFeatureName();
01157             String filename = PathJoin(folder, MakeString(quid) + ".raw");
01158             FileLocator loc(mLocator, filename);
01159             File file = RepositoryGetFile(loc, true, false);
01160             Util::IOBuffer* buf = file.GetWriteBuffer();
01161             codebookMode = StringReplace(codebookMode, "llcdump", "llc");
01162             ProjectLLC(codebookVectors, codebookMode, descriptors, imageWidth, 
01163                        imageHeight, X, Y, regionCounts, buf);
01164             delete buf;
01165         }
01166         else if(StringStartsWith(codebookMode, "llc"))
01167         {
01168             ProjectLLC(codebookVectors, codebookMode, descriptors, imageWidth,
01169                        imageHeight, X, Y, regionCounts);
01170         }
01171         delete descriptors;
01172 
01173         // normalize so it sums to one (although this is not guaranteed,
01174         // it depends on what the functions called above put into the
01175         // regionCount variable)
01176         for(int ps = 0; ps < mPointSelector.size(); ps++)
01177         {
01178             // debugStream << "\n\npyramid part #"<<ps<<"\n";
01179             Real64 regionCount = regionCounts[ps];
01180             ILOG_DEBUG("regCount " << regionCount);
01181             if(regionCount == 0)
01182                 regionCount = 1;
01183             for(int i = 0; i < codebookLength; i++)
01184             {
01185                 codebookVectors[ps]->Elem(i) =
01186                     codebookVectors[ps]->Elem(i) / regionCount;
01187             }
01188         }
01189         if(mPointSelector.size() > 0)
01190             output->SetDescriptorLength(codebookLength);
01191         output->Reserve(mPointSelector.size(), false);
01192         for(int ps = 0; ps < mPointSelector.size(); ps++)
01193         {
01194             output->Add(0, 0, 0, 0, 0);
01195             //for(int i = 0; i < codebookLength; i++)
01196             //    std::cout << mLastCodebookVectors[ps]->Elem(i) << " ";
01197             output->SetDescriptor(ps, *(codebookVectors[ps]));
01198         }
01199 
01200         if(mResultOutput)
01201         {
01202             for(int i = 0; i < codebookVectors.size(); i++)
01203             {
01204                 mResultOutput->AddVector(quid, i, 
01205                                          *codebookVectors[i]);
01206             }
01207         }
01208 
01209         if(mDynamicPointSelector)
01210         {
01211             for(int ps = 0; ps < mPointSelector.size(); ps++)
01212             {
01213                 delete mPointSelector[ps];
01214             }
01215             mPointSelector.clear();
01216             delete tempDynamic;
01217         }
01218         delete pointData;
01219         return output;
01220     }
01221 
01222 
01223     PointDescriptorTable*
01224     ReducePointCount(PointDescriptorTable* pointData, int keepCount)
01225     {
01226         std::vector<int> indices;
01227         bool* keepers = new bool[pointData->Size()];
01228         for(int j = 0; j < pointData->Size(); j++)
01229         {
01230             indices.push_back(j);
01231             keepers[j] = false;
01232         }
01233         std::random_shuffle(indices.begin(), indices.end(), mRNG);
01234         
01235         for(int j = 0; j < keepCount; j++)
01236         {
01237             keepers[indices[j]] = true;
01238         }
01239         
01240         PointDescriptorTable* output = new PointDescriptorTable(pointData->GetFeatureDefinition());
01241         output->SetDescriptorLength(pointData->GetDescriptorLength());
01242         Select(output, pointData, keepers, false);
01243         delete pointData;
01244         return output;
01245     }
01246 
01247 
01248     template<class SrcArrayT>
01249     PointDescriptorTable*
01250     DenseAllDetector(SrcArrayT* input)
01251     {
01252         PointDescriptorTable* output = new PointDescriptorTable();
01253         int w = input->CW();
01254         int h = input->CH();
01255         output->SetEmpty();
01256         output->Reserve(w * h * mDenseSamplingScales.size(), false);
01257         for(int y = 0; y < h; y += 1)
01258         {
01259             for(int x = 0; x < w; x++)
01260             {
01261                 for(int q = 0; q < mDenseSamplingScales.size(); q++)
01262                 {
01263                     output->Add(x, y, mDenseSamplingScales[q], 0, 0);
01264                 }
01265             }
01266         }
01267         ILOG_INFO("Points detected: " << output->Size());
01268         return output;
01269     }
01270 
01271 
01272     template<class SrcArrayT>
01273     PointDescriptorTable*
01274     DenseSamplingDetector(SrcArrayT* input, int spacing)
01275     {
01276         PointDescriptorTable* output = new PointDescriptorTable();
01277         int halfspacing = spacing / 2;
01278         int w = input->CW();
01279         int h = input->CH();
01280         int i = 0;
01281         for(int y = spacing; y < h - spacing; y += spacing)
01282         {
01283             int x = spacing;
01284             if(i % 2 == 0)
01285             {
01286                 x += halfspacing;
01287             }
01288             for(; x < w - spacing; x += spacing)
01289             {
01290                 for(int q = 0; q < mDenseSamplingScales.size(); q++)
01291                 {
01292                     //Real64 scale = sqrt(Real64(spacing * spacing + spacing *
01293                     //spacing));
01298                     //scale = scale / 4;
01299                     output->Add(x, y, mDenseSamplingScales[q], 0, 0);
01300                 }
01301             }
01302             i += 1;
01303         }
01304         return output;
01305     }
01306     
01307     
01308     PointDescriptorTable*
01309     ApplyDetector(Array::Array2dVec3UInt8*  inputNoBorder, String detectorMode)
01310     {
01311         CmdOptions& options = CmdOptions::GetInstance();
01312         Real64 harrisThreshold  = options.GetDouble("harrisThreshold");
01313         Real64 harrisK          = options.GetDouble("harrisK");
01314         Real64 laplaceThreshold = options.GetDouble("laplaceThreshold");
01315         
01316         PointDescriptorTable* output = 0;
01317 
01318         if((detectorMode == "harrislaplace") || (detectorMode == "harrislaplace2"))
01319         {
01320             HarrisLaplaceDetector detector(mUseRecGauss);
01321             detector.mBackwardsCompatible = false;
01322             output = detector.HLDetector(inputNoBorder, harrisThreshold,
01323                                 harrisK, laplaceThreshold);
01324         }
01325         else if(detectorMode == "colorharrislaplace")
01326         {
01327             // recommendation: set harrisThreshold to at least 0.001 in color
01328             // mode (due to very different ranges!)
01329             HarrisLaplaceDetector detector(mUseRecGauss);
01330             detector.mBackwardsCompatible = false;
01331             output = detector.CHLDetector(inputNoBorder, harrisThreshold,
01332                                  harrisK, laplaceThreshold);
01333         }
01334         else if(detectorMode == "laplacian")
01335         {
01336             output = LaplacianDetector(inputNoBorder, true);
01337         }
01338         else if(detectorMode == "densesampling")
01339         {
01340             int spacing = options.GetInt("ds_spacing");
01341             output = DenseSamplingDetector(inputNoBorder, spacing);
01342         }
01343         else if(detectorMode == "denseall")
01344         {
01345             output = DenseAllDetector(inputNoBorder);
01346         }
01347         else if(detectorMode == "none")
01348         {
01349             // we don't add point in the detector phase, they are added in the
01350             // descsriptor fase. see Core/Feature/Surf.h for an example
01351             output = new PointDescriptorTable();
01352         }
01353         else
01354         {
01355             ILOG_ERROR("[ERROR] Unknown detector mode: " << detectorMode);
01356             return 0;
01357         }
01358         output->SetFeatureDefinition(FeatureDefinition(detectorMode));
01359         return output;
01360     }
01361     
01362     
01363     void
01364     ComputeDescriptors(PointDescriptorTable* pointData,
01365                        Array::Array2dVec3UInt8*  inputNoBorder,
01366                        String descriptorMode)
01367     {
01368         if((descriptorMode == "huesift") || (descriptorMode == "huefist"))
01369         {
01370             using namespace Core::Matrix;
01371             CalculateRegionDescriptors(inputNoBorder, pointData,
01372                                        "huehistogram");
01373 
01374             // now fix the range of hue...
01375             Mat* part1 = MatCreate<Mat>(pointData->Size(), pointData->GetDescriptorLength());
01376             for(int i = 0; i < pointData->Size(); i++)
01377             {
01378                 Real64* ptr = pointData->GetDescriptorData(i);
01379                 for(int j = 0; j < MatNrCol(part1); j++)
01380                 {
01381                     *MatE(part1, i, j) = static_cast<int>(ptr[j] * 512);
01382                 }
01383             }
01384             
01385             CalculateFISTDescriptors(inputNoBorder, pointData, "sift");
01386             Mat* part0 = pointData->GetDescriptorMatrix();
01387             std::vector<Mat*> matrices;
01388             matrices.push_back(part0);
01389             matrices.push_back(part1);
01390             Matrix::Mat* descriptors =
01391                 Matrix::MatConcatenateHorizontal(matrices);
01392         
01393             // takes ownership of memory
01394             pointData->ReplaceAllDescriptors(descriptors);
01395             
01396             delete part1;
01397        }
01398         else if((descriptorMode.size() >= 4) &&
01399                 (descriptorMode.substr(descriptorMode.size()-4,4) == "fist"))
01400         {
01401             CalculateFISTDescriptors
01402                 (inputNoBorder, pointData, descriptorMode);
01403         }
01404         else if((descriptorMode.size() >= 4) &&
01405                 (descriptorMode.substr(descriptorMode.size()-4,4) == "sift"))
01406         {
01407             CalculateFISTDescriptors
01408                 (inputNoBorder, pointData, descriptorMode);
01409         }
01410         else if((descriptorMode.size() >= 4) &&
01411                 (descriptorMode.substr(descriptorMode.size()-4,4) == "surf"))
01412         {
01413             CalculateSurfDescriptors
01414                 (inputNoBorder, pointData, descriptorMode, mSurfParams[0],
01415                  mSurfParams[1], mSurfParams[2]);
01416         }
01417         else if(descriptorMode == "none")
01418         {
01419             // do nothing, assume the user knows what he is doing
01420         }
01421         else
01422         {
01423             CalculateRegionDescriptors
01424                 (inputNoBorder, pointData, descriptorMode);
01425         }
01426     }
01427 
01428     // command line parameters
01429     int         mVerbose;
01430     int         mStripBorder;
01431     bool        mUseRecGauss;
01432     String      mName;         // for display/filename purposes
01433     FeatureDefinition mFeatureDefinition;
01434     int         mKeepLimited;
01435     String      mOutputFormat;
01436     FeatureTable*     mCodebook;
01437     Mat*              mDescriptorReduce;
01438     String            mDescriptorReduceFilename;
01439 
01440     FeatureTableResult* mResultOutput;
01441     Array::Array2dScalarUInt64* mExtraBoxes;
01442 
01443     std::vector<InterestPointSelector*> mPointSelector;
01444     bool                         mDynamicPointSelector;
01445     String                       mDynamicPointSelectorConfig;
01446     Persistency::Locator    mLocator;
01447     std::vector<Real64> mDenseSamplingScales;
01448     int                 mSurfParams[3];
01449 
01450     Util::Random mRNG;
01451     Util::TimeStats mTimeStats;
01452 
01453     ILOG_VAR_DEC;
01454 };
01455 
01456 ILOG_VAR_INIT(InterestPointFeature, Core.Feature);
01457 
01458 } // namespace Koen
01459 } // namespace Sandbox
01460 } // namespace Impala
01461 
01462 #endif

Generated on Thu Jan 13 09:04:25 2011 for ImpalaSrc by  doxygen 1.5.1