00001
00002 #ifndef Impala_Core_Array_DoG_h
00003 #define Impala_Core_Array_DoG_h
00004
00005 #include "Core/Keypoint/Detector.h"
00006 #include "Core/Array/Octaves.h"
00007
00008
00009 namespace Impala{
00010 namespace Core{
00011 namespace KeyPoint{
00012
00013
00014
00015 class DoG:public Detector{
00016
00017 private:
00018 ILOG_VAR_DEC;
00019 Array::Octaves* mOctaves;
00020 Array2dScalarReal64** mDoG;
00021 Array2dScalarReal64** mLevelExtrema;
00022 Array2dScalarReal64** mOctaveExtrema;
00023
00024 int mOctaveCnt;
00025 int mLevelCnt;
00026 int mScaleCnt;
00027 int mCancelled;
00028
00029 public:
00030 DoG(Array::Octaves* o)
00031 {
00032 mOctaves=o;
00033 mOctaveCnt=o->GetOctaveCount();
00034 mLevelCnt=o->GetLevelCount();
00035 mScaleCnt=o->GetScaleCount();
00036 Init();
00037
00038 }
00039 ~DoG(){
00040 for(int i=0; i<mOctaveCnt*(mScaleCnt-1);i++)
00041 {
00042 delete mDoG[i];
00043 }
00044 delete [] mDoG;
00045 for(int i=0; i<mOctaveCnt*mLevelCnt;i++)
00046 {
00047 delete mLevelExtrema[i];
00048 }
00049 delete [] mLevelExtrema;
00050 for(int i=0; i<mOctaveCnt;i++)
00051 {
00052 delete mOctaveExtrema[i];
00053 }
00054 delete [] mOctaveExtrema;
00055 }
00056 void Init(){
00057 mCancelled=0;
00058
00060
00061 mDoG = new Array2dScalarReal64*[mOctaveCnt*(mScaleCnt-1)];
00062 for(int i=0;i<mOctaveCnt*(mScaleCnt-1);i++)
00063 mDoG[i]=0;
00064
00065
00067
00068
00069
00070 mLevelExtrema= new Array2dScalarReal64*[mOctaveCnt*mLevelCnt];
00071
00072 for(int i=0;i<mOctaveCnt*mLevelCnt;i++){
00073 mLevelExtrema[i] = 0;
00074 }
00075
00076 mOctaveExtrema = new Array2dScalarReal64*[mOctaveCnt];
00077 for(int i=0;i<mOctaveCnt;i++)
00078 mOctaveExtrema[i]=0;
00080 mKeyPoints=new KeyPointTableType(0);
00081
00082 }
00083 KeyPointTableType* GetKeyPoints(){
00084 return mKeyPoints;
00085 }
00086
00087 Array2dScalarReal64* GetDoG(int o,int l)
00088 {
00089 if(l>mScaleCnt-2){
00090 ILOG_INFO("Clipping, only "<<mScaleCnt-1<< " DoG at each octave!");
00091 l=mScaleCnt-2;
00092 }
00093 return mDoG[o*(mScaleCnt-1)+l];
00094 }
00095
00096 Array2dScalarReal64* GetLevelExtrema(int o,int l)
00097 {
00098 if(l>mLevelCnt-1){
00099 ILOG_INFO("Clipping, only "<<mLevelCnt<< " extrema at each octave!");
00100 l=mLevelCnt-1;
00101 }
00102 return mLevelExtrema[o*mLevelCnt+l];
00103 }
00104 Array2dScalarReal64* GetOctaveExtrema(int o)
00105 {
00106 if(o>mOctaveCnt){
00107 ILOG_INFO("Clipping, only "<<mOctaveCnt<< " octaves!");
00108 o=mOctaveCnt;
00109 }
00110 return mOctaveExtrema[o];
00111 }
00112
00113 void FindKeyPoints()
00114 {
00115 CalculateDoG();
00116
00117 CalculateOctaveExtrema();
00118 RejectLowContrast();
00119 RejectEdgeResponse();
00120 AcquireKeypoints();
00121
00122 LocalizeKeypoints();
00123
00124
00125 }
00126 void CalculateDoG(){
00127 ILOG_INFO("Calculating DoG ...");
00128 for(int o=0;o<mOctaveCnt;o++){
00129 for(int l=0;l<mScaleCnt-1;l++){
00130 Sub(mDoG[o*(mScaleCnt-1)+l],
00131 mOctaves->GetOctave(o,l),
00132 mOctaves->GetOctave(o,l+1));
00133 }
00134 }
00135 }
00136
00137 void CalculateOctaveExtrema()
00138 {
00139 ILOG_INFO("Calculating Octave Extrema ...");
00140 for(int o=0;o<mOctaveCnt;o++)
00141 {
00142 mOctaveExtrema[o] = 0;
00143 for(int l=0;l<mLevelCnt;l++)
00144 {
00145
00146 mLevelExtrema[o*mLevelCnt+l]=
00147 GetLSSE(mDoG[o*(mScaleCnt-1)+l],
00148 mDoG[o*(mScaleCnt-1)+l+1],
00149 mDoG[o*(mScaleCnt-1)+l+2]);
00150 if(l==0)
00151 Set(mOctaveExtrema[o],mLevelExtrema[o*mLevelCnt+l]);
00152 else
00153 Add(mOctaveExtrema[o],mOctaveExtrema[o],
00154 mLevelExtrema[o*mLevelCnt+l]);
00155 }
00156 }
00157 }
00158 Array2dScalarReal64* GetLSSE(Array2dScalarReal64* u,
00159 Array2dScalarReal64* c,
00160 Array2dScalarReal64* l)
00161 {
00162 Array2dScalarReal64* res = 0 ;
00163 Array2dScalarReal64* arrays[3];
00164
00165 arrays[0]=u;
00166 arrays[1]=c;
00167 arrays[2]=l;
00168
00169 Set(res,c);
00170 SetVal(res,0);
00171
00172
00173
00174
00175
00176 Real64 max;
00177 int i,j,m,n,a;
00178 bool is_max;
00179 for(i=1;i<c->CW()-1;i++){
00180 for(j=1;j<c->CH()-1;j++)
00181 {
00182 max = arrays[1]->Value(i,j);
00183 is_max = true;
00184 for(a=0;a<3;a++)
00185 {
00186 for(m=-1;m<2;m++)
00187 {
00188 for(n=-1;n<2;n++)
00189 {
00190 if(max <= arrays[a]->Value(i+m,j+n))
00191 {
00192 if((a==1)&&(m==0)&&(n==0))
00193 continue;
00194
00195 is_max=false;
00196 break;
00197 }
00198 }
00199 if(!is_max)
00200 break;
00201 }
00202 if(!is_max)
00203 break;
00204 }
00205 if(is_max)
00206 res->SetValue(1,i,j);
00207 }
00208 }
00209 return res;
00210
00211 }
00212
00213 void RejectLowContrast()
00214 {
00215 ILOG_WARN("Reject low contrast not implemented yet!");
00216 }
00217 void RejectEdgeResponse()
00218 {
00219 ILOG_WARN("Reject edge response not implemented!");
00220 return;
00221 }
00222 void AcquireKeypoints()
00223 {
00224 ILOG_INFO("Acquiring Keypoints");
00225 for(int o=0;o<mOctaveCnt;o++)
00226 {
00227 for(int l=0;l<mLevelCnt;l++)
00228 {
00229 Array2dScalarReal64* arr = mLevelExtrema[o*mLevelCnt+l];
00230 for(int i=0;i<arr->CW();i++){
00231 for(int j=0;j<arr->CH();j++)
00232 {
00233 if(arr->Value(i,j)!=0)
00234 {
00235 mKeyPoints->Add(mOctaves->GetSigma(o,l+2),i,j,o,l,0);
00236 }
00237 }
00238 }
00239 }
00240 }
00241 ILOG_INFO("Total "<<mKeyPoints->Size()<<" keypoints!");
00242
00243 }
00244
00245 void LocalizeKeypoints()
00246 {
00247 int k = 0 ;
00248 int OrigSize=mKeyPoints->Size();
00249 ILOG_INFO("Localizing "<<OrigSize<<" Keypoints");
00250 int new_i;
00251 int new_j;
00252 int last=0;
00253 int count=0;
00254 mCancelled=0;
00255 double H[4];
00256 double G[2];
00257 double S[2];
00258 Real64 Dx=0;
00259 Array2dScalarReal64* Octave;
00261
00262
00263
00264 while(k<OrigSize)
00265 {
00266 Real64 sigma=mKeyPoints->Get1(k);
00267 int i = mKeyPoints->Get2(k);
00268 int j = mKeyPoints->Get3(k);
00269 int o = mKeyPoints->Get4(k);
00270 int l = mKeyPoints->Get5(k);
00271
00272
00273 Octave=mOctaves->GetOctave(o,l);
00274
00275 int Width=mOctaves->GetOctave(o,l)->CW();
00276 int Height=mOctaves->GetOctave(o,l)->CH();
00277
00278
00279
00280 int dd;
00281
00283
00284
00285
00286
00287
00288
00289 if(mOctaves->IsResamplingEnabled())
00290 dd=1;
00291 else
00292 dd=sigma;
00293
00294
00295 if((i+2*dd>=Width)||(j+2*dd>=Height)||(i-2*dd<0)||(j-2*dd<0))
00296 {
00297
00298 mCancelled++;
00299 mKeyPoints->Set2(k,0);
00300 mKeyPoints->Set3(k,0);
00301 count=0;
00302 k++;
00303 last=k;
00304 continue;
00305 }
00306
00307
00308
00309
00310
00311
00312 G[0] = Octave->Value(i+dd,j) - Octave->Value(i-dd,j);
00313
00314
00315
00316
00317 H[0]= -2*Octave->Value(i,j) +
00318 Octave->Value(i-2*dd,j) +
00319 Octave->Value(i+2*dd,j) ;
00320
00321
00322
00323
00324
00325 H[1]= Octave->Value(i-dd,j-dd) +
00326 Octave->Value(i+dd,j+dd) -
00327 Octave->Value(i-dd,j+dd) -
00328 Octave->Value(i+dd,j-dd) ;
00329
00330
00331
00332 G[1] = Octave->Value(i,j+dd) - Octave->Value(i,j-dd);
00333
00334
00335
00336 H[2]= -2*Octave->Value(i,j) +
00337 Octave->Value(i,j-2*dd) +
00338 Octave->Value(i,j+2*dd) ;
00339
00340
00341
00342
00343
00344
00345 H[3]= Octave->Value(i-dd,j-dd) + Octave->Value(i+dd,j+dd) -
00346 Octave->Value(i-dd,j+dd) - Octave->Value(i+dd,j-dd) ;
00347
00348 Real64 div = H[0]*H[3]-H[1]*H[2];
00349 S[0]=(-H[3]*G[0]+H[1]*G[1])/div;
00350 S[1]=(H[2]*G[0]-H[0]*G[1])/div;
00351
00352 Dx= Octave->Value(i,j)+.5*(S[0]*G[0]+S[1]+G[1]);
00353 if(Dx<.03){
00354
00355 mCancelled++;
00356 mKeyPoints->Set2(k,0);
00357 mKeyPoints->Set3(k,0);
00358 count=0;
00359 k++;
00360 last=k;
00361 continue;
00362 }
00363
00364 if(!((S[0]> 0.5)||(S[1]> 0.5)||(S[0]<-.5)||(S[1]<-.5))){
00365 k++;
00366 last=k;
00367 count=0;
00368 }else{
00369 new_i=i+S[0];
00370 new_j=j+S[1];
00371 if((new_i>0)&&(new_i<Width)){
00372 mKeyPoints->Set2(k,new_i);
00373 }else{
00374
00375 count=0;
00376 k++;
00377 last=k;
00378 continue;
00379 }
00380
00381
00382 if((new_j>0)&&(new_j<Height)){
00383 mKeyPoints->Set3(k,new_j);
00384 }else{
00385
00386 count=0;
00387 k++;
00388 last=k;
00389 continue;
00390 }
00391
00392 if(last==k)
00393 count++;
00394
00395
00396
00397
00398
00399 if(count>10){
00400 k++;
00401 last=k;
00402 count=0;
00403 }
00404 }
00405
00406 }
00407 ILOG_INFO("Cancel count:"<<mCancelled<<"/"<<OrigSize);
00408
00409 }
00410
00411
00412
00413
00414 };
00415 ILOG_VAR_INIT(DoG, Impala.Core.Array);
00416
00417 }}}
00418 #endif