Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "OctreeGrid.h"
00036
00037 #include <limits>
00038
00039
00040 template<typename T>
00041 OctreeGridDataPointsFilter<T>::FirstPtsSampler::FirstPtsSampler(DataPoints& dp)
00042 : idx{0}, pts(dp)
00043 {
00044 }
00045
00046 template <typename T>
00047 template<std::size_t dim>
00048 bool OctreeGridDataPointsFilter<T>::FirstPtsSampler::operator()(Octree_<T,dim>& oc)
00049 {
00050 if(oc.isLeaf() and not oc.isEmpty())
00051 {
00052 auto* data = oc.getData();
00053 const auto& d = (*data)[0];
00054
00055 std::size_t j = d;
00056
00057
00058 if(std::size_t(d)<idx)
00059 j = mapidx[d];
00060
00061
00062 pts.swapCols(idx, j);
00063
00064
00065 mapidx[idx] = j;
00066
00067 ++idx;
00068 }
00069
00070 return true;
00071 }
00072
00073 template <typename T>
00074 bool OctreeGridDataPointsFilter<T>::FirstPtsSampler::finalize()
00075 {
00076
00077 pts.conservativeResize(idx);
00078
00079 idx=0;
00080 return true;
00081 }
00082
00083
00084 template<typename T>
00085 OctreeGridDataPointsFilter<T>::RandomPtsSampler::RandomPtsSampler(DataPoints& dp)
00086 : OctreeGridDataPointsFilter<T>::FirstPtsSampler{dp}, seed{1}
00087 {
00088 std::srand(seed);
00089 }
00090 template<typename T>
00091 OctreeGridDataPointsFilter<T>::RandomPtsSampler::RandomPtsSampler(
00092 DataPoints& dp, const std::size_t seed_
00093 ): OctreeGridDataPointsFilter<T>::FirstPtsSampler{dp}, seed{seed_}
00094 {
00095 std::srand(seed);
00096 }
00097 template<typename T>
00098 template<std::size_t dim>
00099 bool OctreeGridDataPointsFilter<T>::RandomPtsSampler::operator()(Octree_<T,dim>& oc)
00100 {
00101 if(oc.isLeaf() and not oc.isEmpty())
00102 {
00103 auto* data = oc.getData();
00104 const std::size_t nbData = (*data).size() - 1;
00105 const std::size_t randId =
00106 static_cast<std::size_t>( nbData *
00107 (static_cast<float>(std::rand()/static_cast<float>(RAND_MAX))));
00108
00109 const auto& d = (*data)[randId];
00110
00111 std::size_t j = d;
00112
00113
00114 if(std::size_t(d)<idx)
00115 j = mapidx[d];
00116
00117
00118 pts.swapCols(idx, j);
00119
00120
00121 mapidx[idx] = j;
00122
00123 ++idx;
00124 }
00125
00126 return true;
00127 }
00128
00129 template<typename T>
00130 bool OctreeGridDataPointsFilter<T>::RandomPtsSampler::finalize()
00131 {
00132 bool ret = FirstPtsSampler::finalize();
00133
00134 std::srand(seed);
00135
00136 return ret;
00137 }
00138
00139 template<typename T>
00140 OctreeGridDataPointsFilter<T>::CentroidSampler::CentroidSampler(DataPoints& dp)
00141 : OctreeGridDataPointsFilter<T>::FirstPtsSampler{dp}
00142 {
00143 }
00144
00145 template<typename T>
00146 template<std::size_t dim>
00147 bool OctreeGridDataPointsFilter<T>::CentroidSampler::operator()(Octree_<T,dim>& oc)
00148 {
00149 if(oc.isLeaf() and not oc.isEmpty())
00150 {
00151 const int featDim(pts.features.rows());
00152 const int descDim(pts.descriptors.rows());
00153 const int timeDim(pts.times.rows());
00154
00155 auto* data = oc.getData();
00156 const std::size_t nbData = (*data).size();
00157
00158 const auto& d = (*data)[0];
00159 std::size_t j = d;
00160
00161
00162 if(std::size_t(d)<idx)
00163 j = mapidx[d];
00164
00165
00166 for(std::size_t id=1;id<nbData;++id)
00167 {
00168
00169 const auto& curId = (*data)[id];
00170 std::size_t i = curId;
00171
00172
00173 if(std::size_t(curId)<idx)
00174 i = mapidx[curId];
00175
00176 for (int f = 0; f < (featDim - 1); ++f)
00177 pts.features(f,j) += pts.features(f,i);
00178
00179 if (pts.descriptors.cols() > 0)
00180 for (int d = 0; d < descDim; ++d)
00181 pts.descriptors(d,j) += pts.descriptors(d,i);
00182
00183 if (pts.times.cols() > 0)
00184 for (int t = 0; t < timeDim; ++t)
00185 pts.times(t,j) += pts.times(t,i);
00186 }
00187
00188
00189 for (int f = 0; f < (featDim - 1); ++f)
00190 pts.features(f,j) /= T(nbData);
00191
00192 if (pts.descriptors.cols() > 0)
00193 for (int d = 0; d < descDim; ++d)
00194 pts.descriptors(d,j) /= T(nbData);
00195
00196 if (pts.times.cols() > 0)
00197 for (int t = 0; t < timeDim; ++t)
00198 pts.times(t,j) /= T(nbData);
00199
00200
00201 pts.swapCols(idx, j);
00202
00203
00204 mapidx[idx] = j;
00205
00206 ++idx;
00207 }
00208
00209 return true;
00210 }
00211 template<typename T>
00212 OctreeGridDataPointsFilter<T>::MedoidSampler::MedoidSampler(DataPoints& dp)
00213 : OctreeGridDataPointsFilter<T>::FirstPtsSampler{dp}
00214 {
00215 }
00216
00217 template<typename T>
00218 template<std::size_t dim>
00219 bool OctreeGridDataPointsFilter<T>::MedoidSampler::operator()(Octree_<T,dim>& oc)
00220 {
00221 if(oc.isLeaf() and not oc.isEmpty())
00222 {
00223 auto* data = oc.getData();
00224 const std::size_t nbData = (*data).size();
00225
00226 auto dist = [](const typename Octree_<T,dim>::Point& p1, const typename Octree_<T,dim>::Point& p2) -> T {
00227 return (p1 - p2).norm();
00228 };
00229
00230
00231 typename Octree_<T,dim>::Point center;
00232 for(std::size_t i=0;i<dim;++i) center(i)=T(0.);
00233
00234 for(std::size_t id=0;id<nbData;++id)
00235 {
00236
00237 const auto& curId = (*data)[id];
00238 std::size_t i = curId;
00239
00240
00241 if(std::size_t(curId)<idx)
00242 i = mapidx[curId];
00243
00244 for (std::size_t f = 0; f < dim; ++f)
00245 center(f) += pts.features(f,i);
00246 }
00247 for(std::size_t i=0;i<dim;++i) center(i)/=T(nbData);
00248
00249
00250 T minDist = std::numeric_limits<T>::max();
00251 std::size_t medId = 0;
00252
00253 for(std::size_t id=0;id<nbData;++id)
00254 {
00255
00256 const auto curId = (*data)[id];
00257 std::size_t i = curId;
00258
00259
00260 if(std::size_t(curId)<idx)
00261 i = mapidx[curId];
00262
00263 const T curDist = dist(pts.features.col(i).head(dim), center);
00264 if(curDist<minDist)
00265 {
00266 minDist = curDist;
00267 medId=i;
00268 }
00269 }
00270
00271
00272 pts.swapCols(idx, medId);
00273
00274
00275 mapidx[idx] = medId;
00276
00277
00278 ++idx;
00279 }
00280
00281 return true;
00282 }
00283
00284
00285 template <typename T>
00286 OctreeGridDataPointsFilter<T>::OctreeGridDataPointsFilter(const Parameters& params) :
00287 PointMatcher<T>::DataPointsFilter("OctreeGridDataPointsFilter",
00288 OctreeGridDataPointsFilter::availableParameters(), params),
00289 buildParallel{Parametrizable::get<bool>("buildParallel")},
00290 maxPointByNode{Parametrizable::get<std::size_t>("maxPointByNode")},
00291 maxSizeByNode{Parametrizable::get<T>("maxSizeByNode")}
00292 {
00293 try
00294 {
00295 const int sm = this->template get<int>("samplingMethod");
00296 samplingMethod = SamplingMethod(sm);
00297 }
00298 catch (const InvalidParameter& e)
00299 {
00300 samplingMethod = SamplingMethod::FIRST_PTS;
00301 }
00302 }
00303
00304 template <typename T>
00305 typename PointMatcher<T>::DataPoints
00306 OctreeGridDataPointsFilter<T>::filter(const DataPoints& input)
00307 {
00308 DataPoints output(input);
00309 inPlaceFilter(output);
00310 return output;
00311 }
00312
00313 template <typename T>
00314 void OctreeGridDataPointsFilter<T>::inPlaceFilter(DataPoints& cloud)
00315 {
00316 const std::size_t featDim = cloud.features.rows();
00317
00318 assert(featDim == 4 or featDim == 3);
00319
00320 if(featDim==3)
00321 this->sample<2>(cloud);
00322
00323 else if(featDim==4)
00324 this->sample<3>(cloud);
00325 }
00326
00327 template<typename T>
00328 template<std::size_t dim>
00329 void OctreeGridDataPointsFilter<T>::sample(DataPoints& cloud)
00330 {
00331 Octree_<T,dim> oc;
00332
00333 oc.build(cloud, maxPointByNode, maxSizeByNode, buildParallel);
00334
00335 switch(samplingMethod)
00336 {
00337 case SamplingMethod::FIRST_PTS:
00338 {
00339 FirstPtsSampler sampler(cloud);
00340 oc.visit(sampler);
00341 sampler.finalize();
00342 break;
00343 }
00344 case SamplingMethod::RAND_PTS:
00345 {
00346 RandomPtsSampler sampler(cloud);
00347 oc.visit(sampler);
00348 sampler.finalize();
00349 break;
00350 }
00351 case SamplingMethod::CENTROID:
00352 {
00353 CentroidSampler sampler(cloud);
00354 oc.visit(sampler);
00355 sampler.finalize();
00356 break;
00357 }
00358 case SamplingMethod::MEDOID:
00359 {
00360 MedoidSampler sampler(cloud);
00361 oc.visit(sampler);
00362 sampler.finalize();
00363 break;
00364 }
00365 }
00366 }
00367
00368
00369 template struct OctreeGridDataPointsFilter<float>;
00370 template struct OctreeGridDataPointsFilter<double>;