00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00087 const void * ss;
00088 float * imageOffset;
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
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
00145 int *** createFeatures();
00146 void initializeFerns();
00147 void computeOffsets();
00148 int ** computeOffsets(int width);
00149 void addObjectToFerns();
00150
00151
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
00194 int ivWidth;
00195 int ivHeight;
00196
00197
00198 int ivNumFerns;
00199 int ivFeaturesPerFern;
00200 int ivPatchSize;
00201
00202
00203 int ivPatchSizeMinusOne;
00204 int ivPatchSizeSquared;
00205
00206
00207 int ivOriginalWidth;
00208 int ivOriginalHeight;
00209 int ivScaleMin;
00210 int ivScaleMax;
00211 int ivBBmin;
00212 WarpSettings ivInitWarpSettings;
00213 WarpSettings ivUpdateWarpSettings;
00214
00215
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
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
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
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;
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
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
00300 std::vector<FernDetection> varianceFiltered;
00301 std::vector<FernDetection> fernFiltered1;
00302 std::vector<FernDetection> result;
00303
00304
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
00325 createScaledMatrices(image, scaled, sats, sat2s);
00326
00327 #if DEBUG && TIMING
00328 #pragma omp master
00329 st.time1Variance = getTime();
00330 #endif
00331
00332
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
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
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
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
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
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
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
00474 float lastVariance = ivVarianceThreshold;
00475 ivVarianceThreshold = 100000;
00476
00477
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
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
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
00508
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
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
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
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
00574 outputStream.write((char*)ivMinVariances.data(), ivNumObjects*sizeof(float));
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 }
00588
00589 FernFilter FernFilter::loadFromStream(std::ifstream & inputStream)
00590 {
00591
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
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
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
00655 std::vector<float> minVariances(numObjects);
00656 inputStream.read((char*)minVariances.data(), numObjects * sizeof(float));
00657
00658
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
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
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
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
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
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
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
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
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
00784 for (int nFern = 0; nFern < ivNumFerns; ++nFern)
00785 {
00786 delete[] ivPatchSizeOffsets[nFern];
00787 }
00788 delete[] ivPatchSizeOffsets;
00789 }
00790
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
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
00831 }
00832
00833 void FernFilter::changeWarpSettings(const WarpSettings& initSettings, const WarpSettings& updateSettings)
00834 {
00835 ivInitWarpSettings = initSettings;
00836 ivUpdateWarpSettings = updateSettings;
00837 }
00838
00839
00840
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)
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
00925 Matrix scaled;
00926 float* sat;
00927 float* sat2;
00928 createScaledMatrix(image, scaled, sat, sat2, ivScanNoZoom);
00929
00930
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);
00970 result[nFern][nFeature][3] = randInt(2, ivPatchSize);
00971 result[nFern][nFeature][0] = randInt(0, ivPatchSize - result[nFern][nFeature][2]);
00972 result[nFern][nFeature][1] = randInt(0, ivPatchSize - result[nFern][nFeature][3]);
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];
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];
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
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
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
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
01360 Matrix defWl = Matrix::createWarpMatrix( 0.2, 1);
01361
01362 Matrix defWr = Matrix::createWarpMatrix(-0.2, 1);
01363
01364 Matrix imgWarpL = image.affineWarp(defWl, box, false);
01365
01366 Matrix imgWarpR = image.affineWarp(defWr, box, false);
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
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
01403
01404
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