00001 #ifndef QD_OMNICENSUS_HPP
00002 #define QD_OMNICENSUS_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 "quasidense/qdOmniMask.hpp"
00017 #include "quasidense/qdImgCensus.hpp"
00018
00019 #include "boost/timer.hpp"
00020
00021 namespace jafar {
00022
00023 namespace quasidense {
00024
00025
00034 struct omniDataCensus {
00035
00037 jafar::quasidense::bitset80 *censusData;
00038
00040 unsigned int width;
00041
00043 unsigned int height;
00044
00046 unsigned int widthstep;
00047
00049 boost::numeric::ublas::matrix<bool> vMask;
00050
00061 omniDataCensus (jafar::image::Image &img , jafar::camera::CameraBarreto &omniCam,
00062 jafar::quasidense::omniMask &geomMask, double oasCensus=0.0079,
00063 unsigned int rCensus=2, double hrdThreshold=0.01) :
00064 width(img.width()),
00065 height(img.height()),
00066 widthstep(img.step()),
00067 vMask(img.height(),img.width())
00068 {
00069 JFR_PRECOND(img.depth() == IPL_DEPTH_8U , "quasidense::omniDataCensus::omniDataCensus : Constructor don't tolerate float images");
00070 JFR_PRECOND( rCensus<=4, "quasidense::ingDataCensus::imgDataCensus : 4 is the maximal radius tolarated by Census Transform");
00071
00072 boost::timer chrono;
00073
00074 unsigned int pos, posIma;
00075 unsigned int nbrow = img.height(), nbcol = img.width();
00076 double vmax1, vmax2, vmaxS1, vmaxS2, cstnormal;
00077 double *diffu, *diffl, *difful, *diffur;
00078
00079 diffu = new double [nbrow*nbcol];
00080 diffl = new double [nbrow*nbcol];
00081 difful = new double [nbrow*nbcol];
00082 diffur = new double [nbrow*nbcol];
00083
00084 censusData = new bitset80[nbrow*widthstep];
00085
00086 unsigned char *rawData = reinterpret_cast<unsigned char*>(img.data());
00087 cstnormal = 1.0/255.0;
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 chrono.restart();
00104
00105
00106 for (unsigned int cptc=0, cptr=0; cptc<nbcol; ++cptc)
00107 {
00108 vMask(cptr,cptc) = false;
00109 diffu[cptc] = 0.0;
00110 diffl[cptc] = 0.0;
00111 difful[cptc] = 0.0;
00112 diffur[cptc] = 0.0;
00113 }
00114
00115
00116 pos = nbcol*(nbrow-1);
00117 posIma = (nbrow-1)*widthstep;
00118 for (unsigned int cptc=1, cptr=nbrow-1; cptc<=(nbcol-2); ++cptc)
00119 {
00120 vMask(cptr,cptc) = false;
00121
00122 diffl[pos+cptc] = 0.0;
00123 diffu[pos+cptc] = cstnormal*fabs( (double)rawData[posIma+cptc] -
00124 (double)rawData[posIma-widthstep+cptc] );
00125
00126 difful[pos+cptc] = cstnormal*fabs( (double)rawData[posIma+cptc] -
00127 (double)rawData[posIma-widthstep+cptc-1] );
00128
00129 diffur[pos+cptc] = cstnormal*fabs( (double)rawData[posIma+cptc] -
00130 (double)rawData[posIma-widthstep+cptc+1] );
00131 }
00132
00133
00134 for (unsigned int cptc=0, cptr=1; cptr<nbrow; ++cptr)
00135 {
00136 vMask(cptr,cptc) = false;
00137
00138 diffl[cptr*nbcol] = 0.0;
00139 diffu[cptr*nbcol] = cstnormal*fabs( (double)rawData[cptr*widthstep+cptc] -
00140 (double)rawData[(cptr-1)*widthstep+cptc] );
00141
00142 difful[cptr*nbcol] = 0.0;
00143 diffur[cptr*nbcol] = cstnormal*fabs( (double)rawData[cptr*widthstep+cptc] -
00144 (double)rawData[(cptr-1)*widthstep+cptc+1] );
00145 }
00146
00147
00148 for (unsigned int cptc=nbcol-1, cptr=1; cptr<nbrow; ++cptr)
00149 {
00150 vMask(cptr,cptc) = false;
00151
00152 diffl[(cptr+1)*nbcol-1] = cstnormal*fabs( (double)rawData[cptr*widthstep+cptc] -
00153 (double)rawData[cptr*widthstep+cptc-1] );
00154 diffu[(cptr+1)*nbcol-1] = cstnormal*fabs( (double)rawData[cptr*widthstep+cptc] -
00155 (double)rawData[(cptr-1)*widthstep+cptc] );
00156
00157 diffur[(cptr+1)*nbcol-1] = 0.0;
00158 difful[(cptr+1)*nbcol-1] = cstnormal*fabs( (double)rawData[cptr*widthstep+cptc] -
00159 (double)rawData[(cptr-1)*widthstep+cptc-1] );
00160 }
00161
00162
00163 for (unsigned int cptr=1;cptr<=(nbrow-2);++cptr)
00164 {
00165 pos = cptr*nbcol;
00166 posIma = cptr*widthstep;
00167
00168 for (unsigned int cptc=1;cptc<=(nbcol-2);++cptc)
00169 {
00170 vMask(cptr,cptc) = false;
00171 diffl[pos+cptc] = cstnormal*fabs( (double)rawData[posIma+cptc] -
00172 (double)rawData[posIma+cptc-1] );
00173 diffu[pos+cptc] = cstnormal*fabs( (double)rawData[posIma+cptc] -
00174 (double)rawData[posIma-widthstep+cptc] );
00175
00176 diffur[pos+cptc] = cstnormal*fabs( (double)rawData[posIma+cptc] -
00177 (double)rawData[posIma-widthstep+cptc+1] );
00178 difful[pos+cptc] = cstnormal*fabs( (double)rawData[posIma+cptc] -
00179 (double)rawData[posIma-widthstep+cptc-1] );
00180 }
00181 }
00182
00183 std::cout << " First step of Homogeneous area detection accomplished in " << chrono.elapsed() << "sec." << std::endl;
00184
00185
00186
00187
00188
00189
00190
00191 chrono.restart();
00192
00193 for (unsigned int cptr=1; cptr<=(nbrow-2); ++cptr)
00194 {
00195 pos = cptr*nbcol;
00196 for (unsigned int cptc=1; cptc<=(nbcol-2); ++pos, ++cptc)
00197 if (geomMask.isPixelValid(cptc,cptr))
00198 {
00199 vmaxS1 = (diffl[pos]>diffu[pos])?diffl[pos]:diffu[pos];
00200 vmaxS2 = (difful[pos]>diffur[pos])?difful[pos]:diffur[pos];
00201 vmax1 = (vmaxS1>vmaxS2)?vmaxS1:vmaxS2;
00202
00203 vmaxS1 = (diffl[pos+1]>diffu[pos+nbcol])?diffl[pos+1]:diffu[pos+nbcol];
00204 vmaxS2 = (difful[pos+nbcol+1]>diffur[pos+nbcol-1])?difful[pos+nbcol+1]:diffur[pos+nbcol-1];
00205 vmax2 = (vmaxS1>vmaxS2)?vmaxS1:vmaxS2;
00206
00207 if ((vmax1>=hrdThreshold)||(vmax2>=hrdThreshold))
00208 vMask(cptr,cptc) = true;
00209 }
00210 }
00211
00212 std::cout << " Second step of Homogeneous area detection accomplished in " << chrono.elapsed() << "sec." << std::endl;
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 jblas::vec2 targetPix, onePixTest;
00238 jblas::vec3 pt3D, pt3DTest;
00239
00240 unsigned char currentGL;
00241 unsigned int currentPOS;
00242
00243 int winWcpt=0, winHcpt=0;
00244
00245 double elev, elev0, azim, azim0, norm3D, targetGL;
00246
00247 chrono.restart();
00248
00249 for (unsigned int cptr=1; cptr<=(nbrow-2); ++cptr)
00250 {
00251
00252 targetPix[1] = cptr;
00253 currentPOS = cptr*widthstep;
00254
00255 for (unsigned int cptc=1; cptc<=(nbcol-2); ++cptc)
00256 {
00257
00258 targetPix[0] = cptc;
00259 if (vMask(cptr,cptc))
00260 {
00261
00262 currentGL = rawData[currentPOS+cptc];
00263
00264
00265 omniCam.imageToCameraFrame<jblas::vec2,jblas::vec3>(targetPix,pt3D);
00266 norm3D = ublas::norm_2(pt3D);
00267 elev0 = M_PI_2 - asin(pt3D[2]/norm3D);
00268 azim0 = atan2(pt3D[1],pt3D[0]);
00269
00270 censusData[currentPOS+cptc].reset();
00271
00272
00273
00274
00275
00276
00277
00278
00279 for (pos = 0, winWcpt=-rCensus; winWcpt<=(int)rCensus; ++winWcpt)
00280 {
00281 azim = azim0 + winWcpt*oasCensus/(double)rCensus;
00282 for (winHcpt=-rCensus; winHcpt<=(int)rCensus; ++winHcpt, ++pos)
00283 {
00284 if ( (winWcpt==0) && (winHcpt==0) )
00285 {
00286 --pos;
00287 continue;
00288 }
00289 elev = elev0 + winHcpt*oasCensus/(double)rCensus;
00290
00291
00292 pt3DTest[0] = sin(elev)*cos(azim);
00293 pt3DTest[1] = sin(elev)*sin(azim);
00294 pt3DTest[2] = cos(elev);
00295
00296
00297 omniCam.project<jblas::vec3,jblas::vec2>(pt3DTest,onePixTest);
00298
00299
00300 targetGL = img.getSubPixelValue<unsigned char>(onePixTest[0],onePixTest[1]);
00301
00302
00303
00304
00305 if ((double)currentGL>=targetGL)
00306 censusData[currentPOS+cptc].set(pos,1);
00307
00308 }
00309
00310 }
00311
00312
00313
00314
00315
00316
00317
00318 }
00319
00320 }
00321
00322 }
00323
00324 std::cout << " Census Transform accomplished in " << chrono.elapsed() << "sec." << std::endl;
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 delete[] diffl;
00335 delete[] diffu;
00336 delete[] difful;
00337 delete[] diffur;
00338
00339 };
00340
00341 ~omniDataCensus(void)
00342 {
00343 delete[] censusData;
00344 };
00345
00346 };
00347
00348 class omniPairCensus {
00349
00350 omniDataCensus img1;
00351
00352 omniDataCensus img2;
00353
00354 unsigned int rCensus;
00355
00356 unsigned int winWidth;
00357
00358 public :
00359
00363 omniPairCensus (jafar::image::Image &img1_, jafar::image::Image &img2_,
00364 jafar::camera::CameraBarreto &omnicam_,
00365 jafar::quasidense::omniMask &geomMask_,
00366 double oasCensus_=0.0079,
00367 unsigned int rCensus_=2,
00368 double hrdThreshold_=0.01) :
00369
00370 img1(img1_, omnicam_, geomMask_, oasCensus_, rCensus_, hrdThreshold_),
00371 img2(img2_, omnicam_, geomMask_, oasCensus_, rCensus_, hrdThreshold_),
00372 rCensus(rCensus_),
00373 winWidth(2*rCensus_+1)
00374 { };
00375
00379 bool isPointValidinIma1 (int u, int v);
00380 bool isPointValidinIma2 (int u, int v);
00381
00385 bool isMatchValid (int u1, int v1, int u2, int v2);
00386 bool isMatchValid (int u1, int v1, int u2, int v2, unsigned int radius);
00387
00391 double matchEval (int u1, int v1, int u2, int v2);
00392 double matchEval (int u1, int v1, int u2, int v2, unsigned int radius);
00393
00397 void confirmedMatch (int u1, int v1, int u2, int v2)
00398 {
00399 img1.vMask(v1,u1) = false;
00400 img2.vMask(v2,u2) = false;
00401 };
00402
00403 };
00404
00405 }
00406
00407 }
00408
00409 #endif