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