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
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
00060
00061
00062
00063
00064
00065 float lefty = a*rect_left + b;
00066 float righty = a*rect_right + b;
00067
00068
00069 float bar1,bar2;
00070 vec4 intersect;
00071 if(lefty < rect_top)
00072 {
00073 if(righty < rect_top)
00074 {
00075 return false;
00076 }
00077 else
00078 {
00079
00080 float topx = (rect_top-b)/a;
00081 intersect[0] = topx;
00082 intersect[1] = rect_top;
00083
00084 if(righty <= rect_bottom)
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
00093 {
00094
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)
00110 {
00111
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)
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
00126 {
00127
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)
00138 {
00139 return false;
00140 }
00141 else
00142 {
00143
00144 float bottomx = (rect_bottom-b)/a;
00145 intersect[0] = bottomx;
00146 intersect[1] = rect_left;
00147
00148 if(righty >= rect_top)
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
00156 {
00157
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
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
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
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))
00228 + (P2(1) - P1(1))*(P2(1) - P1(1));
00229 double P12 = sqrt(P12_2);
00230
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))
00234 + (L2(1) - L1(1))*(L2(1) - L1(1));
00235 double L12 = sqrt(L12_2);
00236
00237
00238 jblas::vec2 Pc = (P1 + P2) / 2;
00239
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
00246 double angle = atan2(L2(1) - L1(1), L2(0) - L1(0));
00247
00248
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();
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
00334
00335
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
00349 for(int i=0 ; i<4 ; i++)
00350 pred[i] = targetAppSpec->exp[i];
00351
00352 appSpec->obs = obs;
00353 projectOnPrediction(obs,pred,projected,&ratio);
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
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
00448
00449
00450
00451 app->obs = measurement;
00452 push = segmentInRect(roi, measurement);
00453
00454
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
00470 featPtr->measurement.matchScore = 1.0;
00471
00472 featPtr->measurement.x() += noise->get();
00473
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
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
00492 boost::shared_ptr<simu::DescriptorSimu> descPtr(new simu::DescriptorSimu());
00493
00494 obsPtr->landmarkPtr()->setDescriptor(descPtr);
00495 }
00496
00497 };
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 }}}
00509
00510 #endif
00511