00001 #ifndef ImagePyramid_h
00002 #define ImagePyramid_h
00003
00004 #include <vector>
00005 #include "Core/Array/Arrays.h"
00006 #include "Core/Array/GaussDerivative.h"
00007 #include "Core/Array/Scale.h"
00008
00009 #include "Core/Tracking/BasicTypes.h"
00010
00011 namespace Impala
00012 {
00013 namespace Core
00014 {
00015 namespace Tracking
00016 {
00017
00018
00019 class ImagePyramid
00020 {
00021 public:
00022 ImagePyramid(Array::Array2dVec3Real64* base)
00023 {
00024
00025 mLevels.reserve(8);
00026 mLevels.push_back(base);
00027 mScratch = new Array::Array2dVec3Real64(base->CW(), base->CH(), base->BW(), base->BH(), 0);
00028 Array::Array2dScalarReal64* kernel = Array::MakeGaussian1d(1.0, 0, 1.0, 3);
00029 mGaussKernel = new Array::Array2dVec3Real64(kernel->CW(), kernel->CH(), kernel->BW(), kernel->BH(), 0);
00030 Array::Pattern::PatSet(mGaussKernel,kernel,0,0,kernel->CW(),kernel->CH(),0,0);
00031 delete kernel;
00032
00033 int w,h;
00034 w = base->CW();
00035 h = base->CH();
00036 mMaxTop = 1;
00037 while( w>2 && h>2 && w*h>100)
00038 {
00039 w/=2;
00040 h/=2;
00041 mMaxTop++;
00042 }
00043 }
00044
00045 virtual ~ImagePyramid()
00046 {
00047
00048 while(mLevels.size()>1)
00049 {
00050 delete mLevels.back();
00051 mLevels.pop_back();
00052 }
00053 delete mGaussKernel;
00054 delete mScratch;
00055 }
00056
00057 void ComputeLevels(int top)
00058 {
00059 if(top > mMaxTop)
00060 top = mMaxTop;
00061 if(top == 0)
00062 top = mMaxTop;
00063 while(top>Levels())
00064 ComputeNextLevel();
00065 }
00066
00067 Array::Array2dVec3Real64* GetLevel(int level)
00068 {
00069 if(level>=Levels())
00070 throw std::invalid_argument("[ImagePyramid::GetLevel] invalid level");
00071 return mLevels[level];
00072 }
00073
00074 void PropagateBaseChanges()
00075 {
00076 int i;
00077 for(i=0 ; i<Levels()-1 ; i++)
00078 {
00079 ScaleAndCopy(i);
00080 }
00081 }
00082
00083 int Levels()
00084 {
00085 return mLevels.size();
00086 }
00087
00088 Point GetSize(int level)
00089 {
00090 Array::Array2dVec3Real64* img;
00091 img = GetLevel(level);
00092 return Point(img->CW(), img->CH());
00093 }
00094
00095 private:
00096 std::vector<Array::Array2dVec3Real64*> mLevels;
00097 Array::Array2dVec3Real64* mScratch;
00098 Array::Array2dVec3Real64* mGaussKernel;
00099 int mMaxTop;
00100
00101 void ComputeNextLevel()
00102 {
00103 int w,h;
00104 w = mLevels[Levels()-1]->CW() / 2;
00105 h = mLevels[Levels()-1]->CH() / 2;
00106 int bw,bh;
00107 bw = mLevels[Levels()-1]->BW() / 2;
00108 bh = mLevels[Levels()-1]->BH() / 2;
00109 mLevels.push_back(new Array::Array2dVec3Real64(w,h,bw,bh));
00110 ScaleAndCopy(Levels()-2);
00111 }
00112
00113 void ScaleAndCopy(int srcLevel)
00114 {
00115 int w,h;
00116 w = mLevels[srcLevel]->CW();
00117 h = mLevels[srcLevel]->CH();
00118 FakeResizeScratch(w,h);
00119
00120
00121
00122
00123
00124
00125 Array::GaussDerivative(mScratch, mLevels[srcLevel], 1.0, 0, 0, 2.0);
00126
00127
00128 mScratch->mData += 1;
00129 mLevels[srcLevel]->mData += 1;
00130 Array::GaussDerivative<Array::Array2dVec3Real64,Array::Array2dVec3Real64>
00131 (mScratch, mLevels[srcLevel], 1.0, 0, 0, 2.0);
00132
00133
00134 mScratch->mData += 1;
00135 mLevels[srcLevel]->mData += 1;
00136 Array::GaussDerivative(mScratch, mLevels[srcLevel], 1.0, 0, 0, 2.0);
00137
00138
00139 mScratch->mData -= 2;
00140 mLevels[srcLevel]->mData -= 2;
00141
00142 Array::Scale(mLevels[srcLevel+1], mScratch, 0.5, 0.5, Geometry::NEAREST);
00143 }
00144
00145 void FakeResizeScratch(int w, int h)
00146 {
00147 if(w>mLevels[0]->CW() || h>mLevels[0]->CH())
00148 throw std::logic_error("[ImagePyramid::FakeResizeScratch] too big");
00149 mScratch->mCW = w;
00150 mScratch->mCH = h;
00151 }
00152
00153
00154 ImagePyramid(const ImagePyramid& copy);
00155 ImagePyramid& operator=(const ImagePyramid& copy);
00156 };
00157
00158 }
00159 }
00160 }
00161
00162 #endif ImagePyramid_h