FernFilter.h
Go to the documentation of this file.
00001 /* Copyright (C) 2012 Christian Lutz, Thorsten Engesser
00002  * 
00003  * This file is part of motld
00004  * 
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 
00020 #ifndef FERNFILTER_H
00021 #define FERNFILTER_H
00022 
00023 #include <iostream>
00024 #include <fstream>
00025 #include <cstdlib>
00026 #include <cmath>
00027 #include <algorithm>
00028 #include <vector>
00029 #include <map>
00030 
00031 #ifdef WIN32
00032 #include <time.h>
00033 #else
00034 #include <sys/time.h>
00035 #endif
00036 
00037 #include "Matrix.h"
00038 #include "Utils.h"
00039 
00040 #define USEMAP 1       // Default: 1 - 0 = use lookup table instead: experimental
00041 #define USETBBP 1      // Default: 1 - 0 = use simple pixel comparison: experimental
00042 #define USEFASTSCAN 0  // Default: 0 - 1 = scan only every 2nd box: experimental
00043 
00044 #define TIMING 0
00045 
00046 // some settings - don't change these!
00047 #define CONFIDENCETHRESHOLD             0.7
00048 #define POSOVERLAPTHRESHOLD             0.85
00049 #define NEGOVERLAPTHRESHOLD             0.65
00050 #define INITNEGOVERLAPTHRESHOLD         0.20
00051 #define NUMNEGTRAININGEXAMPLES         100
00052 #define VARIANCETHRESHOLDFACTOR        0.8
00053 #define VARIANCETHRESHOLDDESCENDRATE   0.2
00054 #define VARIANCEMINTHRESHOLD           100
00055 
00056 namespace motld {
00057 
00059   struct WarpSettings
00060   {
00062     int num_closest;
00064     int num_warps;
00066     float noise;
00068     float angle;
00070     float shift;
00072     float scale;
00073   };
00074 
00076   struct FernDetection
00077   {
00079     ObjectBox box;
00081     Matrix patch;
00083     float confidence;
00085     int * featureData;
00086     // temporary values
00087     const void * ss;     // pointer to scan parameters used for this detection
00088     float * imageOffset; // pointer to image / sat position required to compute featureData
00090     static bool fdBetter(FernDetection fd1, FernDetection fd2) { return fd1.confidence > fd2.confidence; }
00091   };
00092 
00094   class FernFilter
00095   {
00096   public:
00098     FernFilter(const int & width, const int & height, const int & numFerns,
00099                const int & featuresPerFern, const int & patchSize = 15, 
00100                const int & scaleMin = -10, const int & scaleMax = 11, const int & bbMin = 24);
00102     FernFilter(const FernFilter & other);
00104     ~FernFilter();
00106     const std::vector<Matrix> addObjects(const Matrix & image, const std::vector<ObjectBox>& boxes);
00108     const std::vector<FernDetection> scanPatch(const Matrix & image) const;
00110     const std::vector< Matrix > learn(const Matrix& image, const std::vector< ObjectBox >& boxes, bool onlyVariance = false);
00112     static FernFilter loadFromStream(std::ifstream & inputStream);
00114     void saveToStream(std::ofstream & outputStream) const;
00116     void changeInputFormat(const int & width, const int & height);
00118     void changeScanBoxFormat(const int & width, const int & height);
00120     void changeScanSettings(const int & scaleMin, const int & scaleMax, const int & bb_min);
00122     void applyPreferences();
00124     void changeWarpSettings(const WarpSettings & initSettings, const WarpSettings & updateSettings);
00125   
00126   private:
00127     // Methods for feature extraction / fern manipulation etc.
00128     void createScaledMatrix(const Matrix& image, Matrix & scaled, float*& sat, float*& sat2, int scale) const;
00129     void createScaledMatrices(const Matrix& image, Matrix*& scaled, float**& sats, float**& sat2s) const;
00130     void varianceFilter(float * image, float * sat, float * sat2, int scale, std::vector<FernDetection> & acc) const;
00131     std::vector< Matrix > retrieveHighVarianceSamples(const Matrix& image, const std::vector< ObjectBox >& boxes);
00132     int* extractFeatures(const float * const imageOrSAT, int ** offsets) const;
00133     void extractFeatures(FernDetection & det) const;
00134     float calcMaxConfidence(int * features) const;
00135     float * calcConfidences(int * features) const;
00136     void addPatch(const int & objId, const int * const featureData, const bool & pos);
00137     void addPatch(const Matrix& scaledImage, const int& objId, const bool& pos);
00138     void addPatchWithWarps(const Matrix & image, const ObjectBox & box, const WarpSettings & ws, 
00139                            std::vector<Matrix> & op, const bool & pos, const bool & notOnlyVar = true);
00140     void addWarpedPatches(const Matrix & image, const ObjectBox & box, const WarpSettings & ws,
00141                           std::vector<Matrix> & op, const bool & pos);
00142     void clearLastDetections() const;
00143   
00144     // Methods for initialization
00145     int *** createFeatures();
00146     void initializeFerns();
00147     void computeOffsets();
00148     int ** computeOffsets(int width);
00149     void addObjectToFerns();
00150   
00151     // Helper
00152     int calcTableSize() const;
00153     void debugOutput() const;
00154     FernDetection copyFernDetection(const FernDetection & fd) const;
00155   
00156     struct Posteriors
00157     {
00158       int n;
00159       int p;
00160       float posterior;
00161     };
00162 
00163     struct Confidences
00164     { 
00165       float maxConf;
00166       std::map<int, Posteriors> posteriors;
00167     };
00168 
00169     struct ScanSettings
00170     {
00171       int width;
00172       int height;
00173       float boxw;
00174       float boxh;
00175       float pixw;
00176       float pixh;
00177       int * varianceIndizes;
00178       int ** offsets;
00179     };
00180   
00181 #if DEBUG && TIMING
00182     struct ScanTime
00183     {
00184       int time0ScaledImages;
00185       int time1Variance;
00186       int time2GenFeatures;
00187       int time3CoarseFilter;
00188       int time4FineFilter;
00189       int time5GenPatches;
00190     };
00191 #endif
00192   
00193     // changeable input image dimensions
00194     int ivWidth;
00195     int ivHeight;
00196   
00197     // hard classifier configuration
00198     int ivNumFerns;
00199     int ivFeaturesPerFern;
00200     int ivPatchSize;
00201   
00202     // helper classifier constants
00203     int ivPatchSizeMinusOne;
00204     int ivPatchSizeSquared;
00205   
00206     // changable scan settings
00207     int ivOriginalWidth;
00208     int ivOriginalHeight;
00209     int ivScaleMin;
00210     int ivScaleMax;
00211     int ivBBmin;
00212     WarpSettings ivInitWarpSettings;
00213     WarpSettings ivUpdateWarpSettings;
00214   
00215     // Fern Data
00216     int *** ivFeatures;
00217 #if USEMAP
00218     std::map<int, Confidences> * ivFernForest;
00219 #else
00220     std::vector<int**> ivNtable;
00221     std::vector<int**> ivPtable;
00222     std::vector<float**> ivTable;
00223     float **ivMaxTable;
00224 #endif
00225   
00226     // further instance variables
00227     int ivNumObjects;
00228     int ivScanNoZoom;
00229     float ivVarianceThreshold;
00230     int ** ivPatchSizeOffsets;
00231     std::vector<ScanSettings> ivScans;
00232     std::vector<float> ivMinVariances;
00233     mutable std::vector<FernDetection> ivLastDetections;
00234   
00235     // some default structures
00236     static const WarpSettings cDefaultInitWarpSettings;
00237     static const WarpSettings cDefaultUpdateWarpSettings;
00238   };
00239 
00240   const WarpSettings FernFilter::cDefaultInitWarpSettings = {10, 20, 5, 20, 0.2, 0.2};
00241   const WarpSettings FernFilter::cDefaultUpdateWarpSettings = {10, 10, 5, 20, 0.2, 0.2};
00242 
00243 
00244 /*****************************************************************************
00245  *                         public accessible stuff                            *
00246  ******************************************************************************/
00247 
00248   FernFilter::FernFilter(const int & width, const int & height, const int & numFerns,
00249                          const int & featuresPerFern, const int & patchSize, 
00250                          const int & scaleMin, const int & scaleMax, const int & bbMin)
00251     : ivWidth(width), ivHeight(height), ivNumFerns(numFerns),
00252     ivFeaturesPerFern(featuresPerFern), ivPatchSize(patchSize),
00253     ivPatchSizeMinusOne(patchSize-1), 
00254     ivPatchSizeSquared(patchSize*patchSize),
00255     ivScaleMin(scaleMin), ivScaleMax(scaleMax), ivBBmin(bbMin),
00256     ivInitWarpSettings(cDefaultInitWarpSettings),
00257     ivUpdateWarpSettings(cDefaultUpdateWarpSettings),
00258     ivFeatures(createFeatures()), ivNumObjects(0),
00259     ivVarianceThreshold(255*255)
00260     {
00261       initializeFerns();
00262     }
00263 
00264   const std::vector<Matrix> FernFilter::addObjects(const Matrix& image, const std::vector<ObjectBox>& boxes)
00265   {
00266     std::vector<Matrix> result;
00267     std::vector<Matrix> posResult; // IDEA: positive warps could also be returned
00268   
00269     if (boxes.empty())
00270       return result;
00271   
00272     if (ivNumObjects == 0)
00273     {
00274       ivOriginalHeight = boxes[0].height;
00275       ivOriginalWidth = boxes[0].width;
00276       computeOffsets();
00277       //debugOutput();
00278     }
00279   
00280     for (unsigned int i = 0; i < boxes.size(); ++i)
00281     {
00282       if (boxes[i].objectId != ivNumObjects + (int)i)
00283         std::cerr << "ERROR WRONG OBJECT ENUMERATION!" << std::endl;
00284       ivMinVariances.push_back(100000);
00285       addObjectToFerns();
00286       addPatchWithWarps(image, boxes[i], ivInitWarpSettings, posResult, true);
00287     }
00288   
00289     if (ivNumObjects == 0)
00290       result = retrieveHighVarianceSamples(image, boxes);
00291   
00292     ivNumObjects += boxes.size();
00293   
00294     return result;
00295   }
00296 
00297   const std::vector<FernDetection> FernFilter::scanPatch(const Matrix & image) const
00298   { 
00299     // Pipeline structure
00300     std::vector<FernDetection> varianceFiltered;
00301     std::vector<FernDetection> fernFiltered1;
00302     std::vector<FernDetection> result;
00303   
00304     // scaled images, summed area tables
00305     Matrix* scaled; float** sats; float** sat2s;
00306   
00307     clearLastDetections();
00308   
00309     if (ivNumObjects == 0)
00310       return result;
00311   
00312 #if DEBUG && TIMING
00313     ScanTime st;
00314 #endif
00315   
00316 #pragma omp parallel
00317     {
00318 
00319 #if DEBUG && TIMING
00320 #pragma omp master
00321       st.time0ScaledImages = getTime();
00322 #endif
00323   
00324       // Step 0 - Precalculate Scaled Images / Summed Area Tables
00325       createScaledMatrices(image, scaled, sats, sat2s); // HIER
00326   
00327 #if DEBUG && TIMING
00328 #pragma omp master
00329       st.time1Variance = getTime();
00330 #endif
00331   
00332       // STEP 1 - Scan, Filter by Variance
00333 #pragma omp barrier
00334 #pragma omp for schedule(dynamic)
00335       for (unsigned int i = 0; i < ivScans.size(); ++i)
00336         varianceFilter(scaled[i].data(), sats[i], sat2s[i], i, varianceFiltered);
00337   
00338 #if DEBUG && TIMING
00339 #pragma omp master
00340       st.time2GenFeatures = getTime();
00341 #endif
00342   
00343       // STEP 2 - Calculate Feature Data
00344 #pragma omp barrier
00345 #pragma omp for
00346       for (unsigned int i = 0; i < varianceFiltered.size(); ++i)
00347         extractFeatures(varianceFiltered[i]);
00348   
00349 #if DEBUG && TIMING
00350 #pragma omp master
00351       st.time3CoarseFilter = getTime();
00352 #endif
00353   
00354       // STEP 3 - Coarse filtering By Fern
00355 #pragma omp barrier
00356       float confidenceThreshold = CONFIDENCETHRESHOLD * ivNumFerns;
00357 #pragma omp for
00358       for (unsigned int i = 0; i < varianceFiltered.size(); ++i)
00359       {
00360         FernDetection det = varianceFiltered[i];
00361         det.confidence = calcMaxConfidence(det.featureData);
00362         if (det.confidence >= confidenceThreshold)
00363 #pragma omp critical
00364           fernFiltered1.push_back(det);
00365         else
00366           delete[] det.featureData;
00367       }
00368   
00369 #if DEBUG && TIMING
00370 #pragma omp master
00371       st.time4FineFilter = getTime();
00372 #endif
00373   
00374       // STEP 4 - Fine filtering By Fern
00375 #pragma omp barrier
00376       if (ivNumObjects == 1)
00377       {
00378 #pragma omp single
00379         result = fernFiltered1;
00380       } 
00381       else
00382       {
00383 #pragma omp for
00384         for (unsigned int i = 0; i < fernFiltered1.size(); ++i)
00385         {
00386           FernDetection det = fernFiltered1[i];
00387           float * confidences = calcConfidences(det.featureData);
00388           int n = 0;
00389           for (int nObject = 0; nObject < ivNumObjects; ++nObject)
00390           {
00391             if (confidences[nObject] > confidenceThreshold)
00392             {
00393               FernDetection nDetection = copyFernDetection(det);
00394               nDetection.box.objectId = nObject;
00395 #pragma omp critical
00396               result.push_back(nDetection);
00397               ++n;
00398             }
00399           }
00400           delete[] confidences;
00401           delete[] det.featureData;
00402         }
00403       }
00404   
00405 #if DEBUG && TIMING
00406 #pragma omp master
00407       st.time5GenPatches = getTime();
00408 #endif
00409   
00410       // STEP 5 finally add patches
00411 #pragma omp barrier
00412 #pragma omp for
00413       for (unsigned int i = 0; i < result.size(); ++i)
00414       {
00415         result[i].patch.copyFromFloatArray(result[i].imageOffset,((ScanSettings*)(result[i].ss))->width,ivPatchSize,ivPatchSize);
00416       }
00417     }
00418   
00419 
00420 #if DEBUG && TIMING
00421     int timefinished = getTime();
00422 #endif
00423   
00424 #if DEBUG && TIMING
00425     // convert absolute time to relative time
00426     st.time0ScaledImages = st.time1Variance     - st.time0ScaledImages;
00427     st.time1Variance     = st.time2GenFeatures  - st.time1Variance;
00428     st.time2GenFeatures  = st.time3CoarseFilter - st.time2GenFeatures;
00429     st.time3CoarseFilter = st.time4FineFilter   - st.time3CoarseFilter;
00430     st.time4FineFilter   = st.time5GenPatches   - st.time4FineFilter;
00431     st.time5GenPatches   = timefinished         - st.time5GenPatches;
00432 #endif
00433   
00434     delete[] scaled;
00435     for (unsigned int i = 0; i < ivScans.size(); ++i)
00436     {
00437       delete[] sats[i];
00438       delete[] sat2s[i];
00439     }
00440     delete[] sats;
00441     delete[] sat2s;
00442   
00443     ivLastDetections = result;
00444  
00445 #if DEBUG  
00446     std::cout << "Patch Filterig Pipeline: " << varianceFiltered.size() << " >> " << fernFiltered1.size() 
00447               << " >> " << result.size();
00448 #if TIMING
00449     std::cout << " | Time: " << st.time0ScaledImages << ", " << st.time1Variance << ", " << st.time2GenFeatures
00450               << ", " << st.time3CoarseFilter << ", " << st.time4FineFilter << ", " << st.time5GenPatches;
00451 #endif
00452     std::cout << std::endl;
00453 #endif
00454   
00455     return result;
00456   }
00457 
00458 // TODO: Multiprozessor
00459   const std::vector<Matrix> FernFilter::learn(const Matrix & image, const std::vector<ObjectBox>& boxes, bool onlyVariance)
00460   {
00461 #if DEBUG
00462     int tStart = getTime();
00463 #endif
00464 
00465     std::vector<Matrix> result;
00466   
00467     int del = 0;
00468   
00469     bool * valid = new bool[ivNumObjects];
00470     ObjectBox * bx = new ObjectBox[ivNumObjects];
00471     memset(valid, 0, ivNumObjects * sizeof(bool));
00472   
00473     // reinitialize varianceThreshold
00474     float lastVariance = ivVarianceThreshold;
00475     ivVarianceThreshold = 100000;
00476   
00477     // CATEGORIZE BOXES AND LEARN POSITIVE EXAMPLES
00478     for (std::vector<ObjectBox>::const_iterator bi = boxes.begin(); bi < boxes.end(); ++bi)
00479     {
00480       valid[bi->objectId] = true;
00481       bx[bi->objectId] = *bi;
00482       addPatchWithWarps(image, *bi, ivUpdateWarpSettings, result, true, !onlyVariance);
00483     }
00484   
00485     // calculate final variance value
00486     for (int nObj = 0; nObj < ivNumObjects; ++nObj)
00487     {
00488       if (!valid[nObj])
00489       {
00490         ivVarianceThreshold = MIN(ivVarianceThreshold, ivMinVariances[nObj]);
00491       }
00492     }
00493     float varThresholdSoll = MAX(VARIANCETHRESHOLDFACTOR*ivVarianceThreshold, VARIANCEMINTHRESHOLD);
00494     float diff = varThresholdSoll - lastVariance;
00495     ivVarianceThreshold = diff > 0 ? varThresholdSoll : lastVariance + diff * VARIANCETHRESHOLDDESCENDRATE;
00496   
00497     // UN-LEARN NEGATIVE EXAMPLES
00498     if (!onlyVariance)
00499     {
00500       for (std::vector<FernDetection>::iterator fd = ivLastDetections.begin();
00501            fd < ivLastDetections.end(); ++fd)
00502       {
00503         int objId = fd->box.objectId;
00504         if (valid[objId] && rectangleOverlap(fd->box, bx[objId]) < NEGOVERLAPTHRESHOLD)
00505         {
00506           addPatch(objId, fd->featureData, false);
00507           // negative patches don't have to be warped!
00508           // addPatch(image, fd->box, ivUpdateWarpSettings, false);
00509           ++del;
00510         }
00511       }
00512     }
00513     delete[] valid;
00514     delete[] bx;
00515     clearLastDetections();
00516 
00517 #if DEBUG
00518     int tEnd = getTime();
00519     std::cout << "Fern Learner: +" << boxes.size() << " , -" << del << " | Variance: " << ivVarianceThreshold
00520               << " | Time: " << tEnd - tStart << std::endl;
00521 #endif
00522   
00523     return result;
00524   }
00525 
00526   void FernFilter::saveToStream(std::ofstream & outputStream) const
00527   {
00528     // 1. simple instance variables
00529     outputStream.write((char*)&ivWidth, sizeof(int));
00530     outputStream.write((char*)&ivHeight, sizeof(int));
00531     outputStream.write((char*)&ivNumObjects, sizeof(int));
00532     outputStream.write((char*)&ivNumFerns, sizeof(int));
00533     outputStream.write((char*)&ivFeaturesPerFern, sizeof(int));
00534     outputStream.write((char*)&ivPatchSize, sizeof(int));
00535     outputStream.write((char*)&ivScaleMin, sizeof(int));
00536     outputStream.write((char*)&ivScaleMax, sizeof(int));
00537     outputStream.write((char*)&ivBBmin, sizeof(int));
00538     outputStream.write((char*)&ivOriginalWidth, sizeof(int));
00539     outputStream.write((char*)&ivOriginalHeight, sizeof(int));
00540     outputStream.write((char*)&ivInitWarpSettings, sizeof(WarpSettings));
00541     outputStream.write((char*)&ivUpdateWarpSettings, sizeof(WarpSettings));
00542     outputStream.write((char*)&ivVarianceThreshold, sizeof(float));
00543   
00544     // 2. fern features
00545     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00546       for (int nFernFeature = 0; nFernFeature < ivFeaturesPerFern; ++nFernFeature)
00547         outputStream.write((char*)(ivFeatures[nFern][nFernFeature]), 4*sizeof(int));
00548   
00549     // 3. fern structures
00550 #if USEMAP
00551     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00552     {
00553       int mapSize = ivFernForest[nFern].size();
00554       outputStream.write((char*)&mapSize, sizeof(int));
00555       for (std::map<int, Confidences>::iterator it = ivFernForest[nFern].begin(); it != ivFernForest[nFern].end(); ++it)
00556       {
00557         outputStream.write((char*)&(it->first), sizeof(int));
00558         outputStream.write((char*)&(it->second.maxConf), sizeof(float));
00559         int entrySize = it->second.posteriors.size();
00560         outputStream.write((char*)&entrySize, sizeof(int));
00561         for (std::map<int, Posteriors>::iterator it2  = it->second.posteriors.begin(); 
00562              it2 != it->second.posteriors.end(); ++it2)
00563         {
00564           outputStream.write((char*)&(it2->first), sizeof(int));
00565           outputStream.write((char*)&(it2->second), sizeof(Posteriors));
00566         }
00567       }
00568     }
00569 #else
00570     std::cerr << "Saving Not Yet implemented for Table" << std::endl;
00571 #endif
00572 
00573     // 4. minVariance
00574     outputStream.write((char*)ivMinVariances.data(), ivNumObjects*sizeof(float));
00575     
00576     /* DEBUGGING - print out instance variables
00577        std::cout << ivWidth << ", " << ivHeight << ", " << ivNumObjects << ", " << ivNumFerns
00578        << ", " << ivFeaturesPerFern << ", " << ivPatchSize << ", " << ivScaleMin
00579        << ", " << ivScaleMax << ", " << ivBBmin << ", " << ivVarianceThreshold << std::endl;
00580        std::cout << ivInitWarpSettings.angle << ", " << ivInitWarpSettings.noise << ", " 
00581        << ivInitWarpSettings.scale << ", " << ivInitWarpSettings.shift << " | "
00582        << ivInitWarpSettings.num_closest << ", " << ivInitWarpSettings.num_warps << std::endl;
00583        std::cout << ivUpdateWarpSettings.angle << ", " << ivUpdateWarpSettings.noise << ", " 
00584        << ivUpdateWarpSettings.scale << ", " << ivUpdateWarpSettings.shift << " | "
00585        << ivUpdateWarpSettings.num_closest << ", " << ivUpdateWarpSettings.num_warps << std::endl;
00586     */
00587   }
00588 
00589   FernFilter FernFilter::loadFromStream(std::ifstream & inputStream)
00590   {
00591     // 1. simple instance variables
00592     int width, height, numObjects, numFerns, featuresPerFern, patchSize, scaleMin, scaleMax,
00593       bbMin, originalWidth, originalHeight;
00594     WarpSettings initWarpSettings, updateWarpSettings;
00595     float varianceThreshold;
00596     inputStream.read((char*)&width, sizeof(int));
00597     inputStream.read((char*)&height, sizeof(int));
00598     inputStream.read((char*)&numObjects, sizeof(int));
00599     inputStream.read((char*)&numFerns, sizeof(int));
00600     inputStream.read((char*)&featuresPerFern, sizeof(int));
00601     inputStream.read((char*)&patchSize, sizeof(int));
00602     inputStream.read((char*)&scaleMin, sizeof(int));
00603     inputStream.read((char*)&scaleMax, sizeof(int));
00604     inputStream.read((char*)&bbMin, sizeof(int));
00605     inputStream.read((char*)&originalWidth, sizeof(int));
00606     inputStream.read((char*)&originalHeight, sizeof(int));
00607     inputStream.read((char*)&initWarpSettings, sizeof(WarpSettings));
00608     inputStream.read((char*)&updateWarpSettings, sizeof(WarpSettings));
00609     inputStream.read((char*)&varianceThreshold, sizeof(float));
00610   
00611     // 2. fern features
00612     int *** features = new int**[numFerns];
00613     for (int nFern = 0; nFern < numFerns; ++nFern)
00614     {
00615       features[nFern] = new int*[featuresPerFern];
00616       for (int nFernFeature = 0; nFernFeature < featuresPerFern; ++nFernFeature)
00617       {
00618         features[nFern][nFernFeature] = new int[4];
00619         inputStream.read((char*)(features[nFern][nFernFeature]), 4*sizeof(int));
00620       }
00621     }
00622   
00623     // 3. fern structures
00624 #if USEMAP
00625     std::map<int, Confidences> * fernForest = new std::map<int, Confidences>[numFerns];
00626     for (int nFern = 0; nFern < numFerns; ++nFern)
00627     {
00628       int mapSize;
00629       inputStream.read((char*)&mapSize, sizeof(int));
00630       for (int nFernLeaf = 0; nFernLeaf < mapSize; ++nFernLeaf)
00631       {
00632         int key, entrySize; float maxConf;
00633         inputStream.read((char*)&key, sizeof(int));
00634         inputStream.read((char*)&maxConf, sizeof(float));
00635         inputStream.read((char*)&entrySize, sizeof(int));
00636         std::map<int, Posteriors> posteriors;
00637         for (int nEntry = 0; nEntry < entrySize; ++nEntry)
00638         {
00639           int nObject; Posteriors posterior;
00640           inputStream.read((char*)&nObject, sizeof(int));
00641           inputStream.read((char*)&posterior, sizeof(Posteriors));
00642           posteriors[nObject] = posterior;
00643         }
00644         Confidences cf;
00645         cf.maxConf = maxConf;
00646         cf.posteriors = posteriors;
00647         fernForest[nFern][key] = cf;
00648       }
00649     }
00650 #else
00651     std::cerr << "Loading Not Yet implemented for Table" << std::endl;
00652 #endif
00653 
00654     // 4. minVariance
00655     std::vector<float> minVariances(numObjects);
00656     inputStream.read((char*)minVariances.data(), numObjects * sizeof(float));
00657   
00658     // finally generate fern filter
00659     FernFilter result(width, height, numFerns, featuresPerFern, patchSize, scaleMin, scaleMax, bbMin);
00660     result.ivNumObjects = numObjects;
00661     result.ivInitWarpSettings = initWarpSettings;
00662     result.ivUpdateWarpSettings = updateWarpSettings;
00663     result.ivVarianceThreshold = varianceThreshold;
00664     result.ivOriginalWidth = originalWidth;
00665     result.ivOriginalHeight = originalHeight;
00666     result.ivFeatures = features;
00667 #if USEMAP
00668     result.ivFernForest = fernForest;
00669 #endif
00670     result.ivMinVariances = minVariances;
00671     result.computeOffsets();
00672     // result.debugOutput();
00673   
00674     /* DEBUGGING - print out loaded instance variables
00675        std::cout << width << ", " << height << ", " << numObjects << ", " << numFerns
00676        << ", " << featuresPerFern << ", " << patchSize << ", " << scaleMin
00677        << ", " << scaleMax << ", " << bbMin << ", " << varianceThreshold << std::endl;
00678        std::cout << initWarpSettings.angle << ", " << initWarpSettings.noise << ", " 
00679        << initWarpSettings.scale << ", " << initWarpSettings.shift << " | "
00680        << initWarpSettings.num_closest << ", " << initWarpSettings.num_warps << std::endl;
00681        std::cout << updateWarpSettings.angle << ", " << updateWarpSettings.noise << ", " 
00682        << updateWarpSettings.scale << ", " << updateWarpSettings.shift << " | "
00683        << updateWarpSettings.num_closest << ", " << updateWarpSettings.num_warps << std::endl;
00684        std::cout << result.ivFernForest->size() << ", " << result.ivScans.size() << std::endl;
00685     */
00686  
00687     return result;
00688   }
00689 
00690   FernFilter::FernFilter(const FernFilter& source) :
00691   ivWidth(source.ivWidth), ivHeight(source.ivHeight), 
00692     ivNumFerns(source.ivNumFerns), ivFeaturesPerFern(source.ivFeaturesPerFern),
00693     ivPatchSize(source.ivPatchSize), ivPatchSizeMinusOne(source.ivPatchSizeMinusOne), 
00694     ivPatchSizeSquared(source.ivPatchSizeSquared),
00695     ivOriginalWidth(source.ivOriginalWidth),
00696     ivOriginalHeight(source.ivOriginalHeight),
00697     ivScaleMin(source.ivScaleMin), 
00698     ivScaleMax(source.ivScaleMax), ivBBmin(source.ivBBmin),
00699     ivInitWarpSettings(source.ivInitWarpSettings),
00700     ivUpdateWarpSettings(source.ivUpdateWarpSettings),
00701     ivNumObjects(source.ivNumObjects),
00702     ivScanNoZoom(source.ivScanNoZoom),
00703     ivVarianceThreshold(source.ivVarianceThreshold),
00704     ivMinVariances(source.ivMinVariances)
00705     {
00706       // copy ivFeatures
00707       ivFeatures = new int**[ivNumFerns];
00708       for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00709       {
00710         ivFeatures[nFern] = new int*[ivFeaturesPerFern];
00711         for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
00712         {
00713           ivFeatures[nFern][nFeature] = new int[4];
00714           memcpy(ivFeatures[nFern][nFeature], source.ivFeatures[nFern][nFeature], 4*sizeof(int));
00715         }
00716       }
00717   
00718       // copy fern data
00719 #if USEMAP
00720       ivFernForest = new std::map<int, Confidences>[ivNumFerns];
00721       for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00722       {
00723         ivFernForest[nFern] = source.ivFernForest[nFern];
00724       }
00725 #else
00726       std::cerr << "COPY CONSTRUCTOR NOT YET IMPLEMENTED FOR LOOKUP TABLE!" << std::endl;
00727 #endif
00728     
00729 #if USEMAP
00730       int offsetSize = 16*ivFeaturesPerFern;
00731 #else
00732       int offsetSize = 4*ivFeaturesPerFern;
00733 #endif
00734     
00735       // copy scan data
00736       if (source.ivNumObjects > 0)
00737       {
00738         for (std::vector<ScanSettings>::const_iterator it = source.ivScans.begin(); 
00739              it < source.ivScans.end();
00740              ++it)
00741         {
00742           ScanSettings ss = *it;
00743           ss.offsets = new int*[ivNumFerns];
00744           for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00745           {
00746             ss.offsets[nFern] = new int[offsetSize];
00747             memcpy(ss.offsets[nFern], it->offsets[nFern], offsetSize * sizeof(int));
00748           }
00749           ss.varianceIndizes = new int[4];
00750           memcpy(ss.varianceIndizes, it->varianceIndizes, 4 * sizeof(int));
00751           ivScans.push_back(ss);
00752         }
00753     
00754         //ivPatchSizeOffsets;
00755         ivPatchSizeOffsets = new int*[ivNumFerns];
00756         for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00757         {
00758           ivPatchSizeOffsets[nFern] = new int[offsetSize];
00759           memcpy(ivPatchSizeOffsets[nFern], source.ivPatchSizeOffsets[nFern], offsetSize * sizeof(int));
00760         }
00761       }
00762     }
00763 
00764   FernFilter::~FernFilter()
00765   {
00766     // Learned Data
00767 #if USEMAP
00768     delete [] ivFernForest;
00769 #else
00770     std::cerr << "Destructor not implemented for table lookup!" << std::endl;
00771 #endif
00772   
00773     if (ivNumObjects > 0)
00774     {
00775       // Scan Settings / Offsets
00776       for (std::vector<ScanSettings>::iterator it = ivScans.begin(); it < ivScans.end(); ++it)
00777       {
00778         delete[] it->varianceIndizes;
00779         for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00780           delete[] it->offsets[nFern];
00781         delete[] it->offsets;
00782       }
00783       // Patch Size Offsets
00784       for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00785       {
00786         delete[] ivPatchSizeOffsets[nFern];
00787       }
00788       delete[] ivPatchSizeOffsets;
00789     }
00790     // Features
00791     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00792     {
00793       for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
00794       {
00795         delete[] ivFeatures[nFern][nFeature];
00796       }
00797       delete[] ivFeatures[nFern];
00798     }
00799     delete[] ivFeatures;
00800     clearLastDetections();
00801   }
00802 
00803 /*****************************************************************************
00804  *                                   setters                                  *
00805  ******************************************************************************/
00806 
00807   void FernFilter::changeInputFormat(const int& width, const int& height)
00808   {
00809     ivWidth = width;
00810     ivHeight = height;
00811   }
00812 
00813   void FernFilter::changeScanBoxFormat(const int& width, const int& height)
00814   {
00815     ivOriginalWidth = width;
00816     ivOriginalHeight = height;
00817   }
00818 
00819   void FernFilter::changeScanSettings(const int& scaleMin, const int& scaleMax, const int& bb_min)
00820   {
00821     ivScaleMin = scaleMin;
00822     ivScaleMax = scaleMax;
00823     ivBBmin = bb_min;
00824   }
00825 
00826   void FernFilter::applyPreferences()
00827   {
00828     std::cout << "Applying Input and Scanning settings..." << std::endl;
00829     computeOffsets();
00830     // debugOutput();
00831   }
00832 
00833   void FernFilter::changeWarpSettings(const WarpSettings& initSettings, const WarpSettings& updateSettings)
00834   {
00835     ivInitWarpSettings = initSettings;
00836     ivUpdateWarpSettings = updateSettings;
00837   }
00838 
00839 /*****************************************************************************
00840  *                         private accessible stuff                           *
00841  ******************************************************************************/
00842 
00843   inline void FernFilter::createScaledMatrix(const Matrix& image, Matrix& scaled, float*& sat, float*& sat2, int scale) const
00844   {
00845     ScanSettings ss = ivScans[scale];
00846     scaled = image;
00847     scaled.rescale(ss.width, ss.height);
00848     float ** saTables = scaled.createSummedAreaTable2();
00849     sat  = saTables[0];
00850     sat2 = saTables[1];
00851     delete[] saTables;
00852   }
00853 
00854   inline void FernFilter::createScaledMatrices(const Matrix& image, Matrix*& scaled, float**& sats, float**& sat2s) const
00855   {
00856 #pragma omp master
00857     {
00858       const int numScans = ivScans.size();
00859       scaled = new Matrix[numScans];
00860       sats   = new float*[numScans];
00861       sat2s  = new float*[numScans];
00862     }
00863 #pragma omp barrier
00864 #pragma omp for schedule(dynamic)
00865     for (unsigned int i = 0; i < ivScans.size(); ++i)
00866     {
00867       createScaledMatrix(image, scaled[i], sats[i], sat2s[i], i);
00868     }
00869   }
00870 
00871   inline void FernFilter::varianceFilter(float * image, float * sat, float * sat2, int scale, std::vector<FernDetection> & acc) const
00872   {   
00873     ScanSettings ss = ivScans[scale];
00874     int right = ss.width - ivPatchSizeMinusOne;
00875     int bottom = ss.height - ivPatchSizeMinusOne;
00876 
00877     for (int y = 0; y < bottom; ++y)
00878     {
00879       int yDiff = y * (ss.width + 1);
00880       float * satPos = sat + yDiff;
00881       float * sat2Pos = sat2 + yDiff;
00882       float * imgPos = image + y * ss.width;
00883       
00884 #if USEFASTSCAN
00885       int fst = y % 2;
00886       if (fst == 1) { imgPos++; satPos++; sat2Pos++; }
00887       int step = 2;
00888 #else
00889       int fst = 0;
00890       int step = 1;   
00891 #endif
00892       
00893       for (int x = fst; x < right; x += step, sat2Pos += step, satPos += step, imgPos += step) //, ++start
00894       {
00895         float ex2 = summedTableArea(sat2Pos,ss.varianceIndizes)/ivPatchSizeSquared;
00896         float ex = summedTableArea(satPos,ss.varianceIndizes)/ivPatchSizeSquared;
00897         float variance = ex2 - ex*ex;
00898         
00899         if (variance >= ivVarianceThreshold)
00900         {
00901           FernDetection fd;
00902           ObjectBox box = {x*ss.pixw, y*ss.pixh, ss.boxw, ss.boxh, 0};
00903           fd.imageOffset = imgPos;
00904           fd.box = box;
00905           fd.confidence = variance;
00906           fd.ss = &(ivScans[scale]);
00907         
00908 #if USETBBP
00909           fd.featureData = (int*)satPos;
00910 #else
00911           fd.featureData = (int*)imgPos;
00912 #endif
00913 #pragma omp critical
00914           acc.push_back(fd);
00915         }
00916       }
00917     }
00918   }
00919 
00920   inline std::vector<Matrix> FernFilter::retrieveHighVarianceSamples(const Matrix& image, const std::vector<ObjectBox>& boxes)
00921   {
00922     std::vector<Matrix> result;
00923   
00924     // generate Summed Area Tables
00925     Matrix scaled; 
00926     float* sat;
00927     float* sat2;
00928     createScaledMatrix(image, scaled, sat, sat2, ivScanNoZoom);
00929   
00930     // scan and order hits
00931     std::vector<FernDetection> varianceDetections;
00932     float ivVarTTmp = ivVarianceThreshold;
00933     ivVarianceThreshold = VARIANCEMINTHRESHOLD;
00934     varianceFilter(scaled.data(), sat, sat2, ivScanNoZoom, varianceDetections);
00935     ivVarianceThreshold = ivVarTTmp;
00936     std::sort(varianceDetections.begin(), varianceDetections.end(), FernDetection::fdBetter);
00937   
00938     std::vector<ObjectBox> allBoxes = boxes;
00939     for (unsigned int i = 0; i < varianceDetections.size() && result.size() < NUMNEGTRAININGEXAMPLES; ++i)
00940     {
00941       bool good = true;
00942       for (unsigned int j = 0; good && j < allBoxes.size(); ++j)
00943         if (rectangleOverlap(varianceDetections[i].box, allBoxes[j]) > INITNEGOVERLAPTHRESHOLD)
00944           good = false;
00945       if (good)
00946       {
00947         allBoxes.push_back(varianceDetections[i].box);
00948         Matrix m;
00949         m.copyFromFloatArray(varianceDetections[i].imageOffset, ivScans[ivScanNoZoom].width, ivPatchSize, ivPatchSize);
00950         result.push_back(m);
00951       }
00952     }
00953   
00954     delete[] sat;
00955     delete[] sat2;
00956   
00957     return result;
00958   }
00959 
00960   inline int*** FernFilter::createFeatures()
00961   {
00962     int *** result = new int**[ivNumFerns];
00963     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00964     {
00965       result[nFern] = new int*[ivFeaturesPerFern];
00966       for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
00967       {
00968         result[nFern][nFeature] = new int[4];
00969         result[nFern][nFeature][2] = randInt(2, ivPatchSize); // width
00970         result[nFern][nFeature][3] = randInt(2, ivPatchSize); // height
00971         result[nFern][nFeature][0] = randInt(0, ivPatchSize - result[nFern][nFeature][2]); // x position
00972         result[nFern][nFeature][1] = randInt(0, ivPatchSize - result[nFern][nFeature][3]); // y position
00973       }
00974     }
00975     return result;
00976   }
00977 
00978   inline void FernFilter::initializeFerns()
00979   {
00980 #if USEMAP
00981     ivFernForest = new std::map<int, Confidences>[ivNumFerns];
00982   
00983 #else
00984     int tableSize = calcTableSize();
00985   
00986     ivMaxTable = new float*[ivNumFerns];
00987     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00988     {
00989       ivMaxTable[nFern] = new float[tableSize];
00990       memset(ivMaxTable[nFern], 0, tableSize * sizeof(float));
00991     }
00992 #endif
00993   }
00994 
00995   inline void FernFilter::addObjectToFerns()
00996   {
00997 #if !USEMAP
00998     int tableSize = calcTableSize();
00999     int ** nTable = new int*[ivNumFerns];
01000     int ** pTable = new int*[ivNumFerns];
01001     float ** table = new float*[ivNumFerns];
01002     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01003     {
01004       nTable[nFern] = new int[tableSize];
01005       memset(nTable[nFern], 0, tableSize*sizeof(int));
01006       pTable[nFern] = new int[tableSize];
01007       memset(pTable[nFern], 0, tableSize*sizeof(int));
01008       table[nFern] = new float[tableSize];
01009       memset(table[nFern], 0., tableSize*sizeof(int));
01010     }
01011     ivNtable.push_back(nTable);
01012     ivPtable.push_back(pTable);
01013     ivTable.push_back(table);
01014 #endif
01015   }
01016 
01017   inline void FernFilter::computeOffsets()
01018   {
01019     ivScans.clear();
01020     ivScanNoZoom  = 0;
01021   
01022     for (int scli = ivScaleMin; scli < ivScaleMax; ++scli)
01023     {
01024       ScanSettings ss;
01025     
01026       float scale = pow(1.2, scli);
01027     
01028       ss.boxw = ivOriginalWidth * scale;
01029       ss.boxh = ivOriginalHeight * scale;
01030     
01031       if (ss.boxw < ivBBmin || ss.boxh < ivBBmin || ss.boxw > ivWidth || ss.boxh > ivHeight)
01032         continue;
01033     
01034       ss.pixw = ss.boxw / ivPatchSize;
01035       ss.pixh = ss.boxh / ivPatchSize;
01036     
01037       ss.width  = round(ivWidth  / ss.pixw);
01038       ss.height = round(ivHeight / ss.pixh);
01039     
01040       ss.varianceIndizes = getSATIndices(ss.width, ivPatchSize, ivPatchSize);
01041       ss.offsets = computeOffsets(ss.width);
01042     
01043       if (scli == 0)
01044         ivScanNoZoom = ivScans.size();
01045     
01046       ivScans.push_back(ss);
01047     }
01048   
01049     ivPatchSizeOffsets = computeOffsets(ivPatchSize);
01050   }
01051 
01052   inline int ** FernFilter::computeOffsets(int width)
01053   {
01054 #if USETBBP
01055     int ** result = new int*[ivNumFerns];
01056     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01057     {
01058       int * fernOffsets = new int[ivFeaturesPerFern*16];
01059       for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
01060       {
01061         int * feature = ivFeatures[nFern][nFeature];
01062         int * currentPos = fernOffsets + 16 * nFeature;
01063         int hpix = feature[2] >> 1;
01064         int left = feature[0]; // + x = + 0
01065         int right = left + feature[2] - 1;
01066         int centerl = left + hpix - 1;
01067         int centerr = right - hpix + 1;
01068     
01069         int vpix = feature[3] >> 1;
01070         int top = feature[1]; // + y = + 0
01071         int bottom = top + feature[3] - 1;
01072         int middlet = top + vpix - 1;
01073         int middleb = bottom - vpix + 1;
01074       
01075         getSATIndices(currentPos     , width, left   ,     top,   right, middlet);
01076         getSATIndices(currentPos +  4, width, left   , middleb,   right,  bottom);
01077         getSATIndices(currentPos +  8, width, left   ,     top, centerl,  bottom);
01078         getSATIndices(currentPos + 12, width, centerr,     top,   right,  bottom);
01079       }
01080       result[nFern] = fernOffsets;
01081     }
01082     return result;
01083 #else
01084     int ** result = new int*[ivNumFerns];
01085     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01086     {
01087       int * fernOffsets = new int[ivFeaturesPerFern*2];
01088       int i = 0;
01089       for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
01090       {
01091         int* feature = ivFeatures[nFern][nFeature];
01092         int p1 = feature[1] * width + feature[0];
01093         int p2 = p1 + feature[3] * width + feature[2];
01094         fernOffsets[i++] = p1;
01095         fernOffsets[i++] = p2;
01096       }
01097       result[nFern] = fernOffsets;
01098     }
01099     return result;
01100 #endif
01101   }
01102 
01103   inline int FernFilter::calcTableSize() const
01104   {
01105     int result = 1 << ivFeaturesPerFern;
01106 #if USETBBP
01107     result *= result;
01108 #endif
01109     return result;
01110   }
01111 
01112   inline void FernFilter::debugOutput() const
01113   {
01114     // FEATURES
01115     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01116     {
01117       std::cout << "Fern " << nFern << ":" << std::endl;
01118       for (int i = -1; i < 4; ++i)
01119       {
01120         std::cout << (i == - 1 ? "feat" : i == 0 ? "posX" : i == 1 ? "posY" : i == 2 ? "lenX" : "lenY") << "\t";
01121         for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
01122         {
01123           std::cout << (i == -1 ? nFeature : ivFeatures[nFern][nFeature][i]) << "\t";
01124         }
01125         std::cout << std::endl;
01126       }
01127     }
01128  
01129     // SCAN SETTINGS
01130     std::cout << "Scan Settings\nboxw\tboxh\twdth\thght\tpixw\tpixh\tvi1\tvi2\tvi3\tvi4" << std::endl;
01131   
01132     for (std::vector<ScanSettings>::const_iterator it = ivScans.begin(); it < ivScans.end(); ++it)
01133     {
01134       std::cout << it->boxw << "\t" << it->boxh << "\t" << it->width << "\t" << it->height << "\t" 
01135                 << it->pixw << "\t" << it->pixh << "\t" << it->varianceIndizes[0] << "\t" <<
01136         it->varianceIndizes[1] << "\t" << it->varianceIndizes[2] << "\t" <<
01137         it->varianceIndizes[3] << std::endl;
01138     }
01139   
01140   }
01141 
01142   inline float FernFilter::calcMaxConfidence(int* featureData) const
01143   {
01144     float result = 0;
01145     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01146     {
01147 #if USEMAP
01148       std::map<int, Confidences>::const_iterator found =
01149         ivFernForest[nFern].find(featureData[nFern]);
01150       if (found != ivFernForest[nFern].end())
01151       {
01152         result += found->second.maxConf;
01153       }
01154 #else
01155       int f = featureData[nFern];
01156       result += ivMaxTable[nFern][f];
01157 #endif
01158     }
01159     return result;
01160   }
01161 
01162   inline float * FernFilter::calcConfidences(int* features) const
01163   {
01164     float * result = new float[ivNumObjects];
01165     memset(result, 0, ivNumObjects * sizeof(float));
01166 #if USEMAP
01167     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01168     {
01169       std::map<int, Confidences>::const_iterator found = 
01170         ivFernForest[nFern].find(features[nFern]);
01171       if (found != ivFernForest[nFern].end())
01172       {
01173         for (std::map<int, Posteriors>::const_iterator pi = found->second.posteriors.begin();
01174              pi != found->second.posteriors.end(); ++pi)
01175         {
01176           result[pi->first] += pi->second.posterior;
01177         }
01178       }
01179     }
01180 #else
01181     for (int nObject = 0; nObject < ivNumObjects; ++nObject)
01182     {
01183       float ** table = ivTable[nObject];
01184       for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01185       {
01186         result[nObject] += table[nFern][features[nFern]];
01187       }
01188     }
01189 #endif
01190     return result;
01191   }
01192 
01193   inline void FernFilter::extractFeatures(FernDetection& det) const
01194   {
01195     det.featureData = extractFeatures((float*)det.featureData, ((ScanSettings*)(det.ss))->offsets);
01196   }
01197 
01198   inline int * FernFilter::extractFeatures(const float * const imgOrSAT, int ** offsets) const
01199   {
01200     int * result = new int[ivNumFerns];
01201     for(int nFern = 0; nFern < ivNumFerns; ++nFern)
01202     {
01203       int * foffsets = offsets[nFern];
01204 #if USETBBP
01205       int fernClass = 0;
01206       for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
01207       {
01208         int * foffsets2 = foffsets + 16 * nFeature;
01209         float artop = summedTableArea(imgOrSAT, foffsets2);
01210         float arbot = summedTableArea(imgOrSAT, foffsets2+4);
01211         float arlft = summedTableArea(imgOrSAT, foffsets2+8);
01212         float arrgt = summedTableArea(imgOrSAT, foffsets2+12);
01213         int vf = artop < arbot;
01214         int hf = arlft < arrgt;
01215         fernClass <<= 2;
01216         fernClass |= (vf << 1) | hf;
01217       }
01218 #else
01219       int fernClass = 0;
01220       for (int nFeature = 0; nFeature < ivFeaturesPerFern; ++nFeature)
01221       {
01222         float px1 = imgOrSAT[*foffsets++];
01223         float px2 = imgOrSAT[*foffsets++];
01224         fernClass = (fernClass << 1) | (px1 < px2);
01225       }
01226 #endif
01227       result[nFern] = fernClass;
01228     }
01229     return result;
01230   }
01231 
01232   inline void FernFilter::addPatch(const int & objId, const int * const featureData, const bool & pos)
01233   {
01234 #if !USEMAP
01235     int ** nTable = ivNtable[objId];
01236     int ** pTable = ivPtable[objId];
01237     float ** table = ivTable[objId];
01238 #endif
01239     for (int nFern = 0; nFern < ivNumFerns; ++nFern)
01240     {
01241       // TODO: nFern ausgliedern?
01242       int feature = featureData[nFern];
01243 #if USEMAP
01244       std::map<int, Confidences>::iterator found =
01245         ivFernForest[nFern].find(feature);
01246       if (found != ivFernForest[nFern].end())
01247       {
01248         std::map<int, Posteriors>::iterator found2 =
01249           found->second.posteriors.find(objId);
01250         if (found2 != found->second.posteriors.end())
01251         {
01252           bool isPos = found2->second.p >= CONFIDENCETHRESHOLD;
01253           if (pos != isPos)
01254           {
01255             (pos ? found2->second.p : found2->second.n) += 1;
01256             int pf = found2->second.p;
01257             found2->second.posterior = (float)pf / (pf + found2->second.n);
01258             found->second.maxConf = 0;
01259             for (std::map<int, Posteriors>::const_iterator it = found->second.posteriors.begin();
01260                  it != found->second.posteriors.end(); ++it)
01261             {
01262               found->second.maxConf = MAX(found->second.maxConf, it->second.posterior);
01263             }
01264           }
01265         }
01266         else
01267         {
01268           Posteriors p = {pos ? 0 : 1, pos ? 1 : 0, pos ? 1 : 0};
01269           found->second.posteriors[objId] = p;
01270           found->second.maxConf = MAX(found->second.maxConf, p.posterior);
01271         }
01272       }
01273       else
01274       {
01275         Posteriors p = {pos ? 0 : 1, pos ? 1 : 0, pos ? 1 : 0};
01276         Confidences c;
01277         c.posteriors[objId] = p;
01278         c.maxConf = p.posterior;
01279         ivFernForest[nFern][feature] = c;
01280       }
01281 #else
01282       bool isPos = table[nFern][feature] >= CONFIDENCETHRESHOLD;
01283       if (pos != isPos)
01284       {
01285         (pos ? pTable : nTable)[nFern][feature]++;
01286         int pf = pTable[nFern][feature];
01287         table[nFern][feature] = (float)pf / (pf + nTable[nFern][feature]);
01288         ivMaxTable[nFern][feature] = 0;
01289         for (int numObj = 0; numObj < ivNumObjects; ++numObj)
01290         {
01291           ivMaxTable[nFern][feature] = MAX(ivMaxTable[nFern][feature], ivTable[numObj][nFern][feature]);
01292         }
01293       }
01294 #endif
01295     }
01296   }
01297 
01298   inline void FernFilter::addPatch(const Matrix& scaledImage, const int& objId, const bool& pos)
01299   {
01300 #if USETBBP
01301     float * sat = scaledImage.createSummedAreaTable();
01302     int * features = extractFeatures(sat, ivPatchSizeOffsets);
01303     delete[] sat;
01304 #else
01305     int * features = extractFeatures(scaledImage.data(), ivPatchSizeOffsets);
01306 #endif
01307     addPatch(objId, features, pos);
01308     delete[] features;
01309   }
01310 
01311   inline void FernFilter::addPatchWithWarps(const Matrix& image, const ObjectBox& box, const WarpSettings& ws, 
01312                                             std::vector<Matrix> & op, const bool& pos, const bool& notOnlyVar)
01313   { 
01314     float factX = box.width / ivPatchSize;
01315     float factY = box.height / ivPatchSize;
01316     float width = image.xSize() / factX;
01317     float height = image.ySize() / factY;
01318   
01319     Matrix scaled = image; scaled.rescale(round(width), round(height));  
01320     ObjectBox newB = {box.x / factX, box.y / factY, ivPatchSize, ivPatchSize, box.objectId};
01321   
01322     Matrix pt(box.width,box.height);
01323     pt.copyFromFloatArray(scaled.data(), width, height, round(newB.x), round(newB.y), round(newB.width), round(newB.height));
01324     pt.rescale(ivPatchSize,ivPatchSize);
01325   
01326     float ** sats = pt.createSummedAreaTable2();
01327     const int index = (ivPatchSize+1)*(ivPatchSize+1)-1;
01328     const int nPixels = ivPatchSize * ivPatchSize;
01329     const float ex2 = sats[1][index] / nPixels;
01330     const float ex = sats[0][index] / nPixels;
01331     const float exex = ex * ex;
01332     const float variance = ex2 - exex;
01333   
01334     ivMinVariances[box.objectId] = MIN(ivMinVariances[box.objectId], variance);
01335     ivVarianceThreshold = MIN(ivVarianceThreshold, variance);
01336   
01337     if (notOnlyVar)
01338     {
01339 #if USETBBP
01340       float * img = sats[0];
01341 #else
01342       float * img = pt.data();
01343 #endif
01344       const int * data = extractFeatures(img, ivPatchSizeOffsets);
01345       addPatch(box.objectId, data, pos);
01346       addWarpedPatches(scaled, newB, ws, op, pos);
01347       delete[] data;
01348     }
01349   
01350     delete[] sats[0];
01351     delete[] sats[1];
01352     delete[] sats;
01353   }
01354 
01355   inline void FernFilter::addWarpedPatches(const Matrix& image, const ObjectBox& box, const WarpSettings& ws, 
01356                                            std::vector<Matrix> & op, const bool& pos)
01357   {  
01358   
01359     // Default Warps!
01360     Matrix defWl = Matrix::createWarpMatrix( 0.2, 1);
01361     //Matrix defWn = createWarpMatrix(   0, 1);
01362     Matrix defWr = Matrix::createWarpMatrix(-0.2, 1);
01363   
01364     Matrix imgWarpL = image.affineWarp(defWl, box, false);
01365     //Matrix imgWarpN = image.affineWarp(defWn, box, false);
01366     Matrix imgWarpR = image.affineWarp(defWr, box, false);
01367   
01368     /* DEBUGGING - print affine warps
01369        static int x = 0;
01370        char filenameL[255];
01371        char filenameN[255];
01372        char filenameR[255];
01373        sprintf(filenameL, "output/warped_pic%03d_obj%d_l.pgm",x, box.objectId);
01374        sprintf(filenameN, "output/warped_pic%03d_obj%d_n.pgm",x, box.objectId);
01375        sprintf(filenameR, "output/warped_pic%03d_obj%d_r.pgm",x, box.objectId);
01376        imgWarpL.writeToPGM(filenameL);
01377        imgWarpN.writeToPGM(filenameN);
01378        imgWarpR.writeToPGM(filenameR);
01379        ++x;
01380     */
01381   
01382   
01383     imgWarpL.rescale(ivPatchSize, ivPatchSize);
01384     imgWarpR.rescale(ivPatchSize, ivPatchSize);
01385     addPatch(imgWarpL, box.objectId, pos);
01386     addPatch(imgWarpR, box.objectId, pos);
01387     op.push_back(imgWarpL);
01388     op.push_back(imgWarpR);
01389   
01390     for (int i = 0; i < ws.num_warps; ++i)
01391     {
01392       float angle = (PI / 180) * ws.angle * randFloat(-0.5, 0.5);
01393       float scale = 1 - ws.scale * randFloat(-0.5, 0.5);  
01394       Matrix warpMatrix = Matrix::createWarpMatrix(angle, scale);
01395     
01396       float shX = ws.shift * box.width * randFloat(-0.5, 0.5);
01397       float shY = ws.shift * box.height * randFloat(-0.5, 0.5);
01398       ObjectBox shiftedBox = {box.x + shX, box.y + shY, box.width, box.height, box.objectId};
01399     
01400       Matrix warped = image.affineWarp(warpMatrix, shiftedBox, true);
01401     
01402       /*char filename[255];
01403         sprintf(filename, "output/warped2_pic%03d_obj%d_%d.pgm", x, box.objectId, i);
01404         warped.writeToPGM(filename);*/
01405     
01406       warped.rescale(ivPatchSize,ivPatchSize);
01407       addPatch(warped, box.objectId, pos);
01408     }
01409   }
01410 
01411   inline void FernFilter::clearLastDetections() const
01412   {
01413     for (std::vector<FernDetection>::iterator it = ivLastDetections.begin(); it < ivLastDetections.end(); ++it)
01414     {
01415       delete[] it->featureData;
01416     }
01417     ivLastDetections.clear();
01418   }
01419 
01420   inline FernDetection FernFilter::copyFernDetection(const FernDetection & fd) const
01421   {
01422     FernDetection result = fd;
01423     result.featureData = new int[ivNumFerns];
01424     memcpy(result.featureData, fd.featureData, ivNumFerns*sizeof(int));
01425     return result;
01426   }
01427 
01428 }
01429 
01430 #endif //FERNCLASSIFIER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


motld
Author(s): Jost Tobias Springenberg, Jan Wuelfing
autogenerated on Wed Dec 26 2012 16:24:49