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
00024 typedef std::bitset<80> bitset80;
00025
00026
00035 struct imgDataCensus {
00036
00038
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
00079
00080
00081
00082
00083
00084
00085
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
00123
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
00141
00142
00143
00144
00145
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
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
00162
00163
00164
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
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
00208
00209
00210 unsigned int current_pos, tested_pos;
00211
00212 for (pos=0;pos<widthstep*nbrow;++pos)
00213 censusData[pos].reset();
00214
00215
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
00237 for (icol=R;icol<2*R;icol++)
00238 {
00239
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
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
00263
00264 for (icol=(nbcol-2*R);icol<(nbcol-R);++icol)
00265 {
00266
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
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
00293
00294
00295
00296 delete[] diffv;
00297 delete[] diffh;
00298 delete[] bitIndexTabular;
00299 delete[] missingBitIndexTabular;
00300 delete[] shiftsTabular;
00301 delete[] missingShiftsTabular;
00302
00303 };
00304
00305 ~imgDataCensus(void)
00306 {
00307 delete[] censusData;
00308 };
00309
00310 };
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 };
00372
00373
00374 }
00375
00376 }
00377
00378 #endif