Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
qdImgCensus.hpp
00001 #ifndef QD_IMGCENSUS_HPP
00002 #define QD_IMGCENSUS_HPP
00003 
00004 #include <iostream>
00005 #include <fstream>
00006 #include <sstream>
00007 #include <string>
00008 #include <vector>
00009 #include <bitset>
00010 
00011 #include <math.h>
00012 
00013 #include "kernel/jafarMacro.hpp"
00014 #include "jmath/jblas.hpp"
00015 #include "image/Image.hpp"
00016 #include "boost/timer.hpp"
00017 
00018 namespace jafar {
00019 
00020   namespace quasidense {
00021 
00022     
00023     // Census on 9x9 window / one bit by pixel
00024     typedef std::bitset<80> bitset80;
00025     
00026     
00035     struct imgDataCensus {
00036       
00038       //boost::numeric::ublas::matrix<bitset80> censusData;
00039       bitset80 *censusData;
00040 
00042       unsigned int width;
00043       unsigned int height;
00044       unsigned int widthstep;
00045       
00047       boost::numeric::ublas::matrix<bool> vMask;      
00048       
00052       imgDataCensus (jafar::image::Image &img , unsigned int rCensus=2, unsigned int rExclu=2, double cmThreshold=0.01) :
00053   vMask(img.height(),img.width())
00054       {
00055   JFR_PRECOND(img.depth() == IPL_DEPTH_8U , "quasidense::imgDataCensus::imgDataCensus : Constructor don't tolerate float images");
00056   JFR_PRECOND( rCensus<=4, "quasidense::ingDataCensus::imgDataCensus : 4 is the maximal radius tolarated by Census Transform");
00057   
00058   unsigned int pos, posIma;
00059   unsigned int nbrow = img.height(), nbcol = img.width();;
00060   double vmax1, vmax2, cstnormal;
00061   double *diffv, *diffh;
00062 
00063   diffv = new double [nbrow*nbcol];
00064   diffh = new double [nbrow*nbcol];
00065     
00066   width = img.width();
00067   height = img.height();
00068   widthstep = img.step(); 
00069   censusData = new bitset80[nbrow*widthstep];
00070 
00071   unsigned char *rawData = reinterpret_cast<unsigned char*>(img.data());
00072   unsigned char current_gl;
00073   cstnormal = 1.0/255.0;
00074   
00075   boost::timer chrono;
00076   // ******************************************************************
00077   //
00078   //                       PART I : MASK GENERATION
00079   //  
00080   // ******************************************************************
00081 
00082 
00083         // ******************************************************************
00084   //  vMask initialization and optimized diffmap computation 
00085   //  4 steps : upper left corner / first row / first line / the rest
00086   //
00087   
00088   vMask(0,0) = false;
00089   diffv[0] = 0.0;
00090   diffh[0] = 0.0;
00091   
00092   pos = nbcol;
00093   for (unsigned int cptr=1; cptr<nbrow ; ++cptr,pos+=nbcol)
00094     {  
00095       vMask(cptr,0) = false;
00096       diffv[pos] = cstnormal*fabs((double)rawData[cptr*widthstep]-(double)rawData[(cptr-1)*widthstep]);
00097       diffh[pos] = 0.0;
00098     }
00099   
00100   for (unsigned int cptc=1; cptc<nbcol;cptc++)
00101     {  
00102       vMask(0,cptc) = false;
00103       diffv[cptc] = 0.0;
00104       diffh[cptc] = cstnormal*fabs((double)rawData[cptc]-(double)rawData[cptc-1]);
00105     }
00106   
00107   pos = nbcol;
00108   for (unsigned int cptr = 1; cptr<nbrow; ++cptr)   
00109     {
00110       pos++;
00111       posIma = cptr*widthstep;
00112       for (unsigned int cptc = 1; cptc<nbcol; ++cptc, ++pos)
00113         {
00114     vMask(cptr,cptc) = false;
00115     diffv[pos] = cstnormal*fabs((double)rawData[posIma+cptc]-(double)rawData[posIma+cptc-widthstep]);
00116     diffh[pos] = cstnormal*fabs((double)rawData[posIma+cptc]-(double)rawData[posIma+cptc-1]);
00117         }
00118     } 
00119   
00120 
00121   // *******************************************
00122         //  Mask Generation
00123   //  We exclude points too near of image sides
00124   //
00125 
00126   for (unsigned int cptr=rExclu;cptr<(nbrow-rExclu);++cptr)
00127     {
00128       pos = cptr*nbcol+rExclu;
00129       for (unsigned int cptc=rExclu;cptc<(nbcol-rExclu);++pos,++cptc)
00130         {
00131     vmax1 = (diffv[pos]<diffh[pos])?diffh[pos]:diffv[pos];
00132     vmax2 = (diffv[pos+nbcol]<diffh[pos+1])?diffh[pos+1]:diffv[pos+nbcol];
00133     if ((vmax1>=cmThreshold)||(vmax2>=cmThreshold))
00134       vMask(cptr,cptc) = true;        
00135         }  
00136     }       
00137 
00138   // ******************************************************************
00139   //
00140   //                 PART II : CENSUS TRANSFORMATION
00141   //  
00142   // ******************************************************************
00143 
00144     
00145   // Variables for rank Transform
00146   unsigned int R = rCensus, N = (rCensus*2+1);
00147   unsigned int maxMissingTestNumber = R*(R+1);
00148   unsigned int effectiveMTN;
00149   unsigned int testNumber = (N*N-1)/2;
00150 
00151   unsigned int *bitIndexTabular, *missingBitIndexTabular;
00152   long int *shiftsTabular, *missingShiftsTabular;
00153   
00154   // Memory Allocation
00155   bitIndexTabular = new unsigned int [N*N];
00156   shiftsTabular = new long int [testNumber];
00157   missingBitIndexTabular = new unsigned int [maxMissingTestNumber];
00158   missingShiftsTabular = new long int [maxMissingTestNumber];
00159   
00160   //
00161   // STEP #1 - Some pre-caclulations
00162   // 
00163   
00164   // bitIndexFilling filling
00165   unsigned int R_int=0, perim = 0, halfperim = 0, firstindex = 0, index = 0;
00166   unsigned int icol = 0, irow = 0;
00167   
00168   for (unsigned int iorbit=0;iorbit<R;iorbit++)
00169     {
00170       R_int = R-iorbit;
00171       perim = 8*R_int;
00172       halfperim = 4*R_int;
00173       
00174       index = firstindex;
00175       
00176       for (icol=iorbit;icol<(N-iorbit);++icol)
00177         {
00178     bitIndexTabular[iorbit*N+icol] = index;
00179     bitIndexTabular[(2*R-iorbit)*N+2*R-icol] = index + halfperim;
00180     index++;
00181         }      
00182       --icol;
00183       
00184       for (irow=iorbit+1;irow<(N-iorbit-1);irow++)
00185         {
00186     bitIndexTabular[irow*N+icol] = index;
00187     bitIndexTabular[(2*R-irow)*N+2*R-icol] = index + halfperim;
00188     index++;
00189         }
00190       
00191       firstindex += perim;
00192       
00193     }
00194 
00195   bitIndexTabular[testNumber] = 0;
00196   
00197   // shiftsTabularFilling      
00198   for (pos = 0, irow = 0; irow<R ; ++irow)
00199     for (icol = 0; icol<N; ++icol, ++pos)     
00200       shiftsTabular[pos] = (irow-R)*widthstep+(icol-R);     
00201   
00202   for (icol = 0; icol<R; ++icol, ++pos)
00203     shiftsTabular[pos] = icol-R;
00204   
00205   
00206   //
00207   // STEP #2 - Census Transform
00208   //   
00209   
00210   unsigned int current_pos, tested_pos;
00211   
00212   for (pos=0;pos<widthstep*nbrow;++pos)
00213     censusData[pos].reset();
00214   
00215   // 1st Block
00216   for (irow = R; irow<nbrow ; ++irow)
00217     {
00218       pos = irow*widthstep;
00219       for ( icol = R; icol<(nbcol-R) ; ++icol)
00220         {
00221     current_pos = pos+icol;
00222     current_gl = rawData[current_pos];
00223     for (unsigned int cpt_test=0;cpt_test<testNumber;++cpt_test)
00224       {
00225         tested_pos = current_pos+shiftsTabular[cpt_test];
00226         if (current_gl!=rawData[tested_pos])
00227           if (current_gl<rawData[tested_pos])
00228       censusData[current_pos].set(bitIndexTabular[cpt_test],1);
00229           else
00230       censusData[tested_pos].set(bitIndexTabular[N*N-1-cpt_test],1);
00231       }
00232         }
00233     }
00234 
00235 
00236   // R-first effective columns 
00237   for (icol=R;icol<2*R;icol++)
00238     {      
00239       // Find missing tests
00240       effectiveMTN = R*(2*R-icol);
00241       for (unsigned int ccol = 0, pos = 0; ccol<(2*R-icol); ++ccol)
00242         for(irow = 1; irow<=R;++irow,++pos)
00243     {
00244       missingShiftsTabular[pos] = irow*widthstep-R+ccol;
00245       missingBitIndexTabular[pos] = bitIndexTabular[(irow+R)*N+ccol];
00246     }
00247       
00248       // Make tests
00249       for (irow=R;irow<(nbrow-R);++irow)
00250         {
00251     current_pos = irow*widthstep+icol;
00252     current_gl = rawData[current_pos];
00253     for (unsigned int cpt_test=0;cpt_test<effectiveMTN;++cpt_test)
00254       {
00255         tested_pos = current_pos+missingShiftsTabular[cpt_test];
00256         if (current_gl<rawData[tested_pos])
00257           censusData[current_pos].set(missingBitIndexTabular[cpt_test],1);
00258       }
00259         }
00260     }
00261   
00262   // R-last effective colums
00263   
00264   for (icol=(nbcol-2*R);icol<(nbcol-R);++icol)
00265     {
00266       // Find missing tests
00267       effectiveMTN = (R+1)*(icol-nbcol+2*R+1);
00268       
00269       for (unsigned int ccol = R, pos = 0; ccol>(R-icol+nbcol-2*R-1); --ccol)
00270         for(irow = 0; irow<=R;++irow,++pos)
00271     {
00272       missingShiftsTabular[pos] = irow*widthstep+ccol;
00273       missingBitIndexTabular[pos] = bitIndexTabular[(irow+R)*N+ccol+R];
00274     }
00275       
00276       // Make tests
00277       for (irow=R;irow<(nbrow-R);++irow)
00278         {
00279     current_pos = irow*widthstep+icol;
00280     current_gl = rawData[current_pos];
00281     for (unsigned int cpt_test=0;cpt_test<effectiveMTN;++cpt_test)
00282       {
00283         tested_pos = current_pos+missingShiftsTabular[cpt_test];
00284         if (current_gl<rawData[tested_pos])
00285           censusData[current_pos].set(missingBitIndexTabular[cpt_test],1);      
00286       }
00287         }
00288     }
00289         std::cout << " Census Transform accomplished in " << chrono.elapsed() << "sec." << std::endl;
00290   // ******************************************************************
00291   // 
00292   //                 PART III : SOME CLEANING
00293   //
00294   // ******************************************************************
00295 
00296   delete[] diffv;
00297   delete[] diffh;
00298   delete[] bitIndexTabular;
00299   delete[] missingBitIndexTabular;
00300   delete[] shiftsTabular; 
00301   delete[] missingShiftsTabular;
00302 
00303       }; // end of constructor
00304 
00305       ~imgDataCensus(void)
00306       {
00307   delete[] censusData;
00308       };
00309       
00310     }; // end of struct imgDataCensus
00311     
00312 
00313         
00322     class imgPairCensus {
00323 
00324       imgDataCensus img1;
00325       
00326       imgDataCensus img2;
00327       
00328       unsigned int rCensus;
00329       
00330       unsigned int winwidth;
00331       
00332     public :
00336       imgPairCensus (jafar::image::Image &img1_, jafar::image::Image &img2_, unsigned int rCensus_=2, 
00337          unsigned int rExclu_=2, double cmThreshold_=0.01) : 
00338   img1(img1_, rCensus_, rExclu_, cmThreshold_),
00339   img2(img2_, rCensus_, rExclu_, cmThreshold_),
00340   rCensus(rCensus_),        
00341   winwidth(2*rCensus_+1)       
00342       {  };      
00343       
00347       bool isPointValidinIma1 (int u, int v);
00348       bool isPointValidinIma2 (int u, int v);
00349 
00353       bool isMatchValid (int u1, int v1, int u2, int v2);
00354       bool isMatchValid (int u1, int v1, int u2, int v2, unsigned int radius);
00355       
00359       double matchEval (int u1, int v1, int u2, int v2);
00360       double matchEval (int u1, int v1, int u2, int v2, unsigned int radius);
00361 
00365       void confirmedMatch (int u1, int v1, int u2, int v2)
00366       {
00367   img1.vMask(v1,u1) = false;
00368   img2.vMask(v2,u2) = false;
00369       };
00370       
00371     }; // end of class imgPairRank
00372           
00373              
00374   } // end namespace quasidense
00375 
00376 }// end namespace jafar
00377 
00378 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:25 for Jafar by doxygen 1.7.6.1
LAAS-CNRS