Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
simuRawProcessors.hpp
Go to the documentation of this file.
00001 
00013 #ifndef SIMURAWPROCESSORS_HPP_
00014 #define SIMURAWPROCESSORS_HPP_
00015 
00016 #include "jmath/random.hpp"
00017 #include "rtslam/landmarkAbstract.hpp"
00018 #include "rtslam/simuData.hpp"
00019 
00020 namespace jafar {
00021 namespace rtslam {
00022 namespace simu {
00023 
00024   template<class RoiSpec>
00025   bool segmentInRect(const RoiSpec& roi, jblas::vec& measure)
00026   {
00027     // Compute line parameters (y = ax + b)
00028     float a = (measure[3]-measure[1])/(measure[2]-measure[0]);
00029     float b = measure[1]-(a*measure[0]);
00030 
00031     float rect_left = roi.x();
00032     float rect_top = roi.y();
00033     float rect_right = rect_left + roi.w();
00034     float rect_bottom = rect_top + roi.h();
00035 
00036     if(a!=a || fabs(a) > 10000)
00037     {
00038       if(measure[0] < rect_left || measure[0] > rect_right ||
00039         min(measure[1],measure[3]) > rect_bottom || 
00040         max(measure[1],measure[3]) < rect_top) {
00041         return false;
00042       }
00043 
00044       if(max(measure[1],measure[3]) == measure[1]) {
00045         if(measure[1] > rect_bottom)
00046           measure[1] = rect_bottom;
00047         if(measure[3] < rect_top)
00048           measure[3] = rect_top;
00049       } else {
00050         if(measure[3] > rect_bottom)
00051           measure[3] = rect_bottom;
00052         if(measure[1] < rect_top)
00053           measure[1] = rect_top;
00054       }
00055 
00056       return true;
00057     }
00058 /*
00059     float minx = min(measure[0],measure[2]);
00060     float miny = min(measure[1],measure[3]);
00061     float maxx = max(measure[0],measure[2]);
00062     float maxy = max(measure[1],measure[3]);
00063 */
00064     // Compute y on the left and right border of the roi
00065     float lefty = a*rect_left + b;
00066     float righty = a*rect_right + b;
00067 
00068     // Reduce 
00069     float bar1,bar2;
00070     vec4 intersect;
00071     if(lefty < rect_top)
00072     {
00073       if(righty < rect_top) // no edge crossed
00074       {
00075         return false;
00076       }
00077       else // top edge crossed
00078       {
00079         // compute top edge intersection
00080         float topx = (rect_top-b)/a;
00081         intersect[0] = topx;
00082         intersect[1] = rect_top;
00083 
00084         if(righty <= rect_bottom) // right edge crossed
00085         {
00086           intersect[2] = rect_right;
00087           intersect[3] = righty;
00088           bar1 = (topx - measure[0]) / (measure[2]-measure[0]);
00089           bar2 = (righty - measure[1]) / (measure[3]-measure[1]);
00090 
00091         }
00092         else // bottom edge crossed
00093         {
00094           // compute bottom edge intersection
00095           float bottomx = (rect_bottom-b)/a;
00096 
00097           intersect[2] = bottomx;
00098           intersect[3] = rect_bottom;
00099           bar1 = (topx - measure[0]) / (measure[2]-measure[0]);
00100           bar2 = (bottomx - measure[0]) / (measure[2]-measure[0]);
00101         }
00102       }
00103     }
00104     else if(lefty <= rect_bottom)
00105     {
00106       intersect[0] = rect_left;
00107       intersect[1] = lefty;
00108 
00109       if(righty < rect_top) // left and top edges crossed
00110       {
00111         // compute top edge intersection
00112         float topx = (rect_top-b)/a;
00113         intersect[2] = topx;
00114         intersect[3] = rect_top;
00115         bar1 = (lefty - measure[1]) / (measure[3]-measure[1]);
00116         bar2 = (topx - measure[0]) / (measure[2]-measure[0]);
00117       }
00118       else if(righty <= rect_bottom) // left and right edges crossed
00119       {
00120         intersect[2] = rect_right;
00121         intersect[3] = righty;
00122         bar1 = (lefty - measure[1]) / (measure[3]-measure[1]);
00123         bar2 = (righty - measure[1]) / (measure[3]-measure[1]);
00124       }
00125       else // left and bottom edges crossed
00126       {
00127         // compute bottom edge intersection
00128         float bottomx = (rect_bottom-b)/a;
00129         intersect[2] = bottomx;
00130         intersect[3] = rect_right;
00131         bar1 = (lefty - measure[1]) / (measure[3]-measure[1]);
00132         bar2 = (bottomx - measure[0]) / (measure[2]-measure[0]);
00133       }
00134     }
00135     else
00136     {
00137       if(righty > rect_bottom) // no edge crossed
00138       {
00139           return false;
00140       }
00141       else // bottom edge crossed
00142       {
00143         // compute bottom edge intersection
00144         float bottomx = (rect_bottom-b)/a;
00145         intersect[0] = bottomx;
00146         intersect[1] = rect_left;
00147 
00148         if(righty >= rect_top) // right edge crossed
00149         {
00150           intersect[2] = rect_right;
00151           intersect[3] = righty;
00152           bar1 = (bottomx - measure[0]) / (measure[2]-measure[0]);
00153           bar2 = (righty - measure[1]) / (measure[3]-measure[1]);
00154         }
00155         else // top edge crossed 
00156         {
00157           // compute top edge intersection
00158           float topx = (rect_top-b)/a;
00159           intersect[2] = topx;
00160           intersect[3] = rect_right;
00161           bar1 = (bottomx - measure[0]) / (measure[2]-measure[0]);
00162           bar2 = (topx - measure[0]) / (measure[2]-measure[0]);
00163         }
00164       }
00165     }
00166 
00167     if((bar1 < 0 && bar2 < 0) || (bar1 > 1 && bar2 > 1))
00168     {
00169       return false;
00170     }
00171     else
00172     {
00173       vec2 meas1, meas2;
00174       meas1[0] = measure[0];
00175       meas1[1] = measure[1];
00176       meas2[0] = measure[2];
00177       meas2[1] = measure[3];
00178 
00179       if(bar1 > 0 && bar1 < 1) {
00180         measure[0] = intersect[0];
00181         measure[1] = intersect[1];
00182       }
00183       if(bar2 > 0 && bar2 < 1) {
00184         measure[2] = intersect[2];
00185         measure[3] = intersect[3];
00186       }
00187     }
00188 
00189     return true;
00190   }
00191 
00192   void randomizeSegment(jblas::vec4& segment)
00193   {
00194     float ran1 = 0;
00195     float ran2 = 0;
00196 
00197     while(fabs(ran1 - ran2) < 0.5 || 
00198       ran1 < 0 || ran1 > 1 ||
00199       ran2 < 0 || ran2 > 1)
00200     {
00201       // choose 2 random values between 0 and 1
00202       ran1 = double(rand()) / RAND_MAX;
00203       ran2 = double(rand()) / RAND_MAX;
00204     }
00205 
00206     if(ran1 < ran2)
00207     {
00208       float tmp = ran1;
00209       ran1 = ran2;
00210       ran2 = tmp;
00211     }
00212 
00213     // compute new extremities
00214     vec modified(4);
00215     modified[0] = ran1*segment[0] + (1-ran1)*segment[2];
00216     modified[1] = ran1*segment[1] + (1-ran1)*segment[3];
00217     modified[2] = ran2*segment[0] + (1-ran2)*segment[2];
00218     modified[3] = ran2*segment[1] + (1-ran2)*segment[3];
00219     segment = modified;
00220   }
00221 
00222   void projectOnPrediction(const jblas::vec4& meas, const jblas::vec4& exp, jblas::vec4& newMeas, float* stdRatio)
00223   {
00224     // extract predicted points
00225     jblas::vec2 P1 = subrange(exp,0,2);
00226     jblas::vec2 P2 = subrange(exp,2,4);
00227     double P12_2 = (P2(0) - P1(0))*(P2(0) - P1(0)) // Square(distance(P1,P2))
00228             +   (P2(1) - P1(1))*(P2(1) - P1(1));
00229     double P12 = sqrt(P12_2);
00230     // extract measured line
00231     jblas::vec2 L1 = subrange(meas,0,2);
00232     jblas::vec2 L2 = subrange(meas,2,4);
00233     double L12_2 = (L2(0) - L1(0))*(L2(0) - L1(0)) // Square(distance(L1,L2))
00234           +   (L2(1) - L1(1))*(L2(1) - L1(1));
00235     double L12 = sqrt(L12_2);
00236 
00237     // compute predicted center
00238     jblas::vec2 Pc = (P1 + P2) / 2;
00239     // project on measured line
00240     double u = (((Pc(0) - L1(0))*(L2(0) - L1(0)))
00241             +((Pc(1) - L1(1))*(L2(1) - L1(1))))
00242             /(L12_2);
00243     jblas::vec2 Lc = L1 + u*(L2 - L1);
00244 
00245     // compute measured orientation
00246     double angle = atan2(L2(1) - L1(1), L2(0) - L1(0));
00247 
00248     // compute extremities
00249     newMeas[0] = Lc[0] - P12 * cos(angle) / 2;
00250     newMeas[1] = Lc[1] - P12 * sin(angle) / 2;
00251     newMeas[2] = Lc[0] + P12 * cos(angle) / 2;
00252     newMeas[3] = Lc[1] + P12 * sin(angle) / 2;
00253 
00254     *stdRatio = P12 / L12;
00255   }
00256 
00257 
00258 
00259   template<class RoiSpec>
00260   class MatcherSimu
00261   {
00262     public:
00263       struct matcher_params_t {
00264         int patchSize;
00265         int maxSearchSize;
00266         double lowInnov;      
00267         double threshold;     
00268         double hi_threshold;  
00269         double hi_limit;      
00270         double mahalanobisTh; 
00271         double relevanceTh; 
00272         double measStd;       
00273         double measVar;       
00274         double simuMeasStd;
00275       } params;
00276       LandmarkAbstract::geometry_t type;
00277       size_t size;
00278       MultiDimNormalDistribution *noise;
00279 
00280     public:
00281       MatcherSimu(LandmarkAbstract::geometry_t type, size_t size, int patchSize, int maxSearchSize, double lowInnov, double threshold, double hi_threshold, double hi_limit, double mahalanobisTh, double relevanceTh, double measStd, double simuMeasStd):
00282         type(type), size(size), noise(NULL)
00283       {
00284         JFR_ASSERT(patchSize%2, "patchSize must be an odd number!");
00285         params.patchSize = patchSize;
00286         params.maxSearchSize = maxSearchSize;
00287         params.lowInnov = lowInnov;
00288         params.threshold = threshold;
00289         params.hi_threshold = hi_threshold;
00290         params.hi_limit = hi_limit;
00291         params.mahalanobisTh = mahalanobisTh;
00292         params.relevanceTh = relevanceTh;
00293         params.measStd = measStd;
00294         params.measVar = measStd * measStd;
00295         params.simuMeasStd = simuMeasStd;
00296       }
00297       ~MatcherSimu()
00298       {
00299         delete noise;
00300       }
00301 
00302       bool match(const boost::shared_ptr<RawSimu> & rawPtr, const appearance_ptr_t & targetApp, const RoiSpec & roi, Measurement & measure, appearance_ptr_t & app)
00303       {
00304         if (noise == NULL)
00305         {
00306           jblas::vec x = jblas::zero_vec(size);
00307           jblas::scalar_vec P(size, params.simuMeasStd*params.simuMeasStd);
00308           noise = new MultiDimNormalDistribution(x, P, rtslam::rand());
00309         }
00310         
00311         boost::shared_ptr<simu::AppearanceSimu> targetAppSpec = SPTR_CAST<simu::AppearanceSimu>(targetApp);
00312         boost::shared_ptr<simu::AppearanceSimu> appSpec = SPTR_CAST<simu::AppearanceSimu>(app);
00313         *appSpec = *targetAppSpec;
00314         
00315         measure.std(params.measStd);
00316         RawSimu::ObsList::iterator it = rawPtr->obs.find(targetAppSpec->id);
00317         if (it != rawPtr->obs.end())
00318         {
00319           measure.matchScore = 1.0;
00320           measure.x() = it->second->measurement.x() + noise->get(); // simulation noise
00321 
00322           bool matched = false;
00323           vec2 meas1, meas2;
00324 
00325           switch(type)
00326           {
00327             case LandmarkAbstract::POINT :
00328               matched = roi.isIn(measure.x());
00329               break;
00330             case LandmarkAbstract::LINE :
00331             {
00332               /*
00333               meas1[0] = measure.x()[0] ; meas1[1] = measure.x()[1];
00334               meas2[0] = measure.x()[2] ; meas2[1] = measure.x()[3];
00335               matched = roi.isIn(meas1) || roi.isIn(meas2);
00336               */
00337               vec meas(4);
00338               for(int i=0 ; i<4 ; i++)
00339                 meas[i] = measure.x()[i];
00340               matched = segmentInRect(roi, meas);
00341               vec4 pred;
00342               vec4 obs;
00343               vec4 projected;
00344               float ratio;
00345 
00346               for(int i=0 ; i<4 ; i++)
00347                 obs[i] = measure.x()[i];
00348                 //obs[i] = meas[i];
00349               for(int i=0 ; i<4 ; i++)
00350                 pred[i] = targetAppSpec->exp[i];
00351               //randomizeSegment(obs);
00352               appSpec->obs = obs;
00353               projectOnPrediction(obs,pred,projected,&ratio);
00354 
00355 /*
00356               JFR_DEBUG("\n"
00357                 << "measure   " << measure.x() << "\n"
00358                 << "corrected " << meas << "\n"
00359                 << "projected " << projected << "\n"
00360                 << "for rect " << roi << "\n"
00361               );
00362 */
00363 
00364               // Debug, if not the same we do it again
00365               bool equal = true;
00366               for(int i=0 ;i<4 ; i++)
00367                 if(fabs(obs[i] - projected[i]) > 0.001)
00368                   equal = false;
00369               if(!equal)
00370               {
00371                 projectOnPrediction(obs,pred,projected,&ratio);
00372               }
00373 
00374               for(int i=0 ; i<4 ; i++)
00375                 measure.x()[i] = projected[i];
00376               measure.std(params.measStd * ratio);
00377             }
00378               break;
00379             default :
00380               break;
00381           }
00382 
00383           return matched;
00384         } else
00385         {
00386           measure.matchScore = 0.0;
00387           return false;
00388         }
00389       }
00390   };
00391 
00392   /*
00393   */
00394 
00395   template<class RoiSpec>
00396   class DetectorSimu
00397   {
00398     public:
00399       struct detector_params_t {
00400         int patchSize;  
00401         double measStd; 
00402         double measVar; 
00403         double simuMeasStd;
00404       } params;
00405       LandmarkAbstract::geometry_t type;
00406       size_t size;
00407       MultiDimNormalDistribution *noise;
00408       
00409     public:
00410       DetectorSimu(LandmarkAbstract::geometry_t type, size_t size, int patchSize, double measStd, double simuMeasStd):
00411         type(type), size(size), noise(NULL)
00412       {
00413         JFR_ASSERT(patchSize%2, "patchSize must be an odd number!");
00414         params.patchSize = patchSize;
00415         params.measStd = measStd;
00416         params.measVar = measStd * measStd;
00417         params.simuMeasStd = simuMeasStd;
00418       }
00419 
00420       bool detect(const boost::shared_ptr<RawSimu> & rawData, const RoiSpec &roi, boost::shared_ptr<FeatureSimu> & featPtr)
00421       {
00422         if (noise == NULL)
00423         {
00424           jblas::vec x = jblas::zero_vec(size);
00425           jblas::scalar_vec P(size, params.simuMeasStd*params.simuMeasStd);
00426           noise = new MultiDimNormalDistribution(x, P, rtslam::rand());
00427         }
00428         
00429         std::vector<featuresimu_ptr_t> roiObs;
00430         
00431         for (RawSimu::ObsList::iterator it = rawData->obs.begin(); it != rawData->obs.end(); ++it)
00432         {
00433           boost::shared_ptr<AppearanceSimu> app = SPTR_CAST<AppearanceSimu>(it->second->appearancePtr);
00434           vec measurement = it->second->measurement.x();
00435           if (app->type == type)
00436           {
00437             bool push = false;
00438             vec2 meas1, meas2;
00439 
00440             switch(type)
00441             {
00442               case LandmarkAbstract::POINT :
00443                 push = roi.isIn(measurement);
00444                 break;
00445               case LandmarkAbstract::LINE :
00446                 /*
00447                 meas1[0] = measurement[0] ; meas1[1] = measurement[1];
00448                 meas2[0] = measurement[2] ; meas2[1] = measurement[3];
00449                 push = roi.isIn(meas1) || roi.isIn(meas2);
00450                 */
00451                 app->obs = measurement;
00452                 push = segmentInRect(roi, measurement);
00453 //                app->obs = measurement;
00454 //                it->second->measurement.x() = measurement;
00455                 break;
00456               default :
00457                 break;
00458             }
00459 
00460             if(push)
00461               roiObs.push_back(it->second);
00462           }
00463         }
00464         
00465         if (roiObs.size() > 0)
00466         {
00467           int n = rtslam::rand()%roiObs.size();
00468           featPtr = roiObs[n];
00469 // JFR_DEBUG("detecting feature " << SPTR_CAST<AppearanceSimu>(featPtr->appearancePtr)->id << " in " << roi.x() << " " << roi.y() << " " << roi.w() << " " << roi.h());
00470           featPtr->measurement.matchScore = 1.0;
00471 // JFR_DEBUG_BEGIN(); JFR_DEBUG_SEND("simu detected feat at " << featPtr->measurement.x());
00472           featPtr->measurement.x() += noise->get(); // simulation noise
00473 // JFR_DEBUG_SEND(" and with noise at " << featPtr->measurement.x()); JFR_DEBUG_END();
00474           featPtr->measurement.std(params.measStd);
00475           return true;
00476         } else
00477         {
00478           featPtr.reset(new FeatureSimu(size));
00479           featPtr->measurement.matchScore = 0.0;
00480           return false;
00481         }
00482       }
00483       
00484       void fillDataObs(const boost::shared_ptr<FeatureSimu> & featPtr, boost::shared_ptr<ObservationAbstract> & obsPtr)
00485       {
00486         // extract observed appearance
00487         boost::shared_ptr<AppearanceSimu> app_src = SPTR_CAST<AppearanceSimu>(featPtr->appearancePtr);
00488         boost::shared_ptr<AppearanceSimu> app_dst = SPTR_CAST<AppearanceSimu>(obsPtr->observedAppearance);
00489         *app_dst = *app_src;
00490         
00491         // create descriptor
00492         boost::shared_ptr<simu::DescriptorSimu> descPtr(new simu::DescriptorSimu());
00493         //descPtr->addObservation(obsPtr);
00494         obsPtr->landmarkPtr()->setDescriptor(descPtr);
00495       }
00496 
00497   };
00498   
00499   
00500   
00501   
00502   
00503   
00504   
00505   
00506   
00507   
00508 }}}
00509 
00510 #endif
00511 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

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