RansacShapeDetector.cpp
Go to the documentation of this file.
1 #ifdef WIN32
2 #include <windows.h>
3 #endif
4 #include <algorithm>
5 #include <ctime>
6 #include <deque>
7 #include <functional>
8 #include <iostream>
9 
10 #include "Candidate.h"
12 #include "Octree.h"
13 #include "RansacShapeDetector.h"
15 #include <MiscLib/Performance.h>
16 #include <MiscLib/Random.h>
17 #ifdef DOPARALLEL
18 #include <omp.h>
19 #endif
20 #undef max
21 #undef min
22 
23 using namespace MiscLib;
24 
26  m_maxCandTries(20), m_reqSamples(0), m_autoAcceptSize(0)
27 {
28 }
29 
31  m_options(options), m_maxCandTries(20), m_reqSamples(0), m_autoAcceptSize(0)
32 {
33 }
34 
36 {
37  for (ConstructorsType::iterator i = m_constructors.begin(), iend = m_constructors.end();
38  i != iend;
39  ++i)
40  {
41  (*i)->Release();
42  }
43 }
44 
45 void
47 {
48  c->AddRef();
49  m_constructors.push_back(c);
50  if (c->RequiredSamples() > m_reqSamples)
51  {
52  m_reqSamples = c->RequiredSamples();
53  }
54 }
55 
56 size_t
57 RansacShapeDetector::StatBucket(float score) const
58 {
59  return (size_t)std::max(
60  0.f,
61  std::floor((std::log(score) - std::log((float)m_options.m_minSupport)) / std::log(1.21f)) +
62  1);
63 }
64 
65 /*
66  * Function Detect !!!!
67  */
68 
69 void
70 RansacShapeDetector::UpdateLevelWeights(
71  float factor,
72  const MiscLib::Vector<std::pair<float, size_t>>& levelScores,
73  MiscLib::Vector<double>* sampleLevelProbability) const
74 {
75  MiscLib::Vector<double> newSampleLevelProbability(sampleLevelProbability->size());
76  double newSampleLevelProbabilitySum = 0;
77  for (size_t i = 0; i < newSampleLevelProbability.size(); ++i)
78  {
79  if ((*sampleLevelProbability)[i] > 0)
80  {
81  newSampleLevelProbability[i] = (levelScores[i].first / (*sampleLevelProbability)[i]);
82  }
83  else
84  {
85  newSampleLevelProbability[i] = 0;
86  }
87  newSampleLevelProbabilitySum += newSampleLevelProbability[i];
88  }
89  double newSum = 0;
90  for (size_t i = 0; i < newSampleLevelProbability.size(); ++i)
91  {
92  newSampleLevelProbability[i] = .9f * newSampleLevelProbability[i] +
93  .1f * newSampleLevelProbabilitySum / levelScores.size();
94  newSum += newSampleLevelProbability[i];
95  }
96  for (size_t i = 0; i < sampleLevelProbability->size(); ++i)
97  {
98  (*sampleLevelProbability)[i] = (1.f - factor) * (*sampleLevelProbability)[i] +
99  factor * (newSampleLevelProbability[i] / newSum);
100  }
101 }
102 
103 template <class ScoreVisitorT>
104 void
105 RansacShapeDetector::GenerateCandidates(
106  const IndexedOctreeType& globalOctree,
108  const PointCloud& pc,
109  ScoreVisitorT& scoreVisitor,
110  size_t currentSize,
111  size_t numInvalid,
112  const MiscLib::Vector<double>& sampleLevelProbSum,
113  size_t* drawnCandidates,
114  MiscLib::Vector<std::pair<float, size_t>>* sampleLevelScores,
115  float* bestExpectedValue,
116  CandidatesType* candidates) const
117 {
118  size_t genCands = 0;
119 
120 #pragma omp parallel
121  {
122  ScoreVisitorT scoreVisitorCopy(scoreVisitor);
123 #pragma omp for schedule(dynamic, 10) reduction(+ : genCands)
124  for (int candIter = 0; candIter < 200; ++candIter)
125  {
126  // pick a sample level
127  double s = ((double)rand()) / (double)RAND_MAX;
128  size_t sampleLevel = 0;
129  for (; sampleLevel < sampleLevelProbSum.size() - 1; ++sampleLevel)
130  if (sampleLevelProbSum[sampleLevel] >= s)
131  {
132  break;
133  }
134  // draw samples on current sample level in octree
135  MiscLib::Vector<size_t> samples;
136  const IndexedOctreeType::CellType* node;
137  if (!DrawSamplesStratified(globalOctree,
138  m_reqSamples,
139  sampleLevel,
140  scoreVisitorCopy.GetShapeIndex(),
141  &samples,
142  &node))
143  {
144  continue;
145  }
146  ++genCands;
147  // construct the candidates
148  size_t c = samples.size();
149  MiscLib::Vector<Vec3f> samplePoints(samples.size() << 1);
150  for (size_t i = 0; i < samples.size(); ++i)
151  {
152  samplePoints[i] = globalOctree.at(samples[i]).pos;
153  samplePoints[i + c] = globalOctree.at(samples[i]).normal;
154  }
155  // construct the different primitive shapes
156  PrimitiveShape* shape;
157  for (ConstructorsType::const_iterator i = m_constructors.begin(),
158  iend = m_constructors.end();
159  i != iend;
160  ++i)
161  {
162  if ((*i)->RequiredSamples() > samples.size() ||
163  !(shape = (*i)->Construct(samplePoints)))
164  {
165  continue;
166  }
167  // verify shape
168  std::pair<float, float> dn;
169  bool verified = true;
170  for (size_t i = 0; i < c; ++i)
171  {
172  shape->DistanceAndNormalDeviation(samplePoints[i], samplePoints[i + c], &dn);
173  if (!scoreVisitorCopy.PointCompFunc()(dn.first, dn.second))
174  {
175  verified = false;
176  break;
177  }
178  }
179  if (!verified)
180  {
181  shape->Release();
182  continue;
183  }
184  Candidate cand(shape, node->Level());
185  cand.Indices(new MiscLib::RefCounted<MiscLib::Vector<size_t>>);
186  cand.Indices()->Release();
187  shape->Release();
188  cand.ImproveBounds(
189  octrees, pc, scoreVisitorCopy, currentSize, m_options.m_bitmapEpsilon, 1);
190  if (cand.UpperBound() < m_options.m_minSupport)
191  {
192 #pragma omp critical
193  {
194  (*sampleLevelScores)[node->Level()].first += cand.ExpectedValue();
195  ++(*sampleLevelScores)[node->Level()].second;
196  }
197  continue;
198  }
199 
200 #pragma omp critical
201  {
202  (*sampleLevelScores)[node->Level()].first += cand.ExpectedValue();
203  ++(*sampleLevelScores)[node->Level()].second;
204  candidates->push_back(cand);
205  if (cand.ExpectedValue() > *bestExpectedValue)
206  {
207  *bestExpectedValue = cand.ExpectedValue();
208  }
209  }
210  }
211  }
212  }
213  *drawnCandidates += genCands;
214 }
215 
217 {
218  bool
219  operator()(const Candidate* a, const Candidate* b) const
220  {
221  return *a < *b;
222  }
223 };
224 
225 template <class ScoreVisitorT>
226 bool
227 RansacShapeDetector::FindBestCandidate(CandidatesType& candidates,
229  const PointCloud& pc,
230  ScoreVisitorT& scoreVisitor,
231  size_t currentSize,
232  size_t drawnCandidates,
233  size_t numInvalid,
234  size_t minSize,
235  float numLevels,
236  float* maxForgottenCandidate,
237  float* candidateFailProb) const
238 {
239  if (!candidates.size())
240  {
241  return false;
242  }
243  size_t maxImproveSubsetDuringMaxSearch = octrees.size();
244  // sort by expected value
245  std::sort(candidates.begin(), candidates.end());
246  // check if max is smaller than forgotten candidate
247  if (candidates.size() && candidates.back().ExpectedValue() < *maxForgottenCandidate)
248  {
249  // drawn candidates is wrong!
250  // need to correct the value
251  drawnCandidates = std::max(candidates.size(), (size_t)1);
252  *maxForgottenCandidate = 0;
253  }
254 
256  for (size_t i = candidates.size() - 1; i != -1; --i)
257  {
258  if (CandidateFailureProbability(candidates[i].ExpectedValue(),
259  currentSize - numInvalid,
260  drawnCandidates,
261  numLevels) > m_options.m_probability)
262  {
263  break;
264  }
265  candHeap.push_back(&candidates[i]);
266  }
267 
268  if (!candHeap.size())
269  {
270  return false;
271  }
272 
273  std::make_heap(candHeap.begin(), candHeap.end(), CandidateHeapPred());
274 
275  MiscLib::Vector<Candidate*> beatenCands;
276  Candidate* trial = candHeap.front();
277  std::pop_heap(candHeap.begin(), candHeap.end(), CandidateHeapPred());
278  candHeap.pop_back();
279  float bestCandidateFailureProbability;
280  while (candHeap.size())
281  {
282  if (trial->IsEquivalent(
283  *candHeap.front(), pc, m_options.m_epsilon, m_options.m_normalThresh))
284  {
285  std::pop_heap(candHeap.begin(), candHeap.end(), CandidateHeapPred());
286  candHeap.pop_back();
287  continue;
288  }
289  bool isEquivalent = false;
290  for (size_t j = 0; j < beatenCands.size(); ++j)
291  {
292  if (beatenCands[j]->IsEquivalent(
293  *candHeap.front(), pc, m_options.m_epsilon, m_options.m_normalThresh))
294  {
295  isEquivalent = true;
296  break;
297  }
298  }
299  if (isEquivalent)
300  {
301  std::pop_heap(candHeap.begin(), candHeap.end(), CandidateHeapPred());
302  candHeap.pop_back();
303  continue;
304  }
305  bestCandidateFailureProbability = CandidateFailureProbability(
306  trial->ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
307  while (
308  (bestCandidateFailureProbability <= m_options.m_probability) &&
309  (*trial >= *candHeap.front()) && (trial->UpperBound() >= minSize) &&
310  trial->ImproveBounds(
311  octrees, pc, scoreVisitor, currentSize, m_options.m_bitmapEpsilon, octrees.size()))
312  {
313  bestCandidateFailureProbability = CandidateFailureProbability(
314  trial->ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
315  }
316  if (bestCandidateFailureProbability <= m_options.m_probability &&
317  trial->UpperBound() >= minSize && trial->ComputedSubsets() >= octrees.size() &&
318  *trial >= *candHeap.front())
319  {
320  break;
321  }
322  if (bestCandidateFailureProbability <= m_options.m_probability &&
323  trial->UpperBound() >= minSize)
324  {
325  candHeap.push_back(trial);
326  std::push_heap(candHeap.begin(), candHeap.end(), CandidateHeapPred());
327  }
328  else if ((int)trial->ComputedSubsets() > std::max(2, ((int)octrees.size()) - 2))
329  {
330  beatenCands.push_back(trial);
331  }
332  trial = candHeap.front();
333  std::pop_heap(candHeap.begin(), candHeap.end(), CandidateHeapPred());
334  candHeap.pop_back();
335  }
336  bestCandidateFailureProbability = CandidateFailureProbability(
337  trial->ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
338  while (bestCandidateFailureProbability <= m_options.m_probability &&
339  trial->UpperBound() >= minSize &&
340  trial->ImproveBounds(
341  octrees, pc, scoreVisitor, currentSize, m_options.m_bitmapEpsilon, octrees.size()))
342  {
343  bestCandidateFailureProbability = CandidateFailureProbability(
344  trial->ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
345  }
346  if ((bestCandidateFailureProbability > m_options.m_probability ||
347  trial->UpperBound() < minSize) &&
348  (!m_autoAcceptSize || trial->UpperBound() < m_autoAcceptSize))
349  {
350  return false;
351  }
352  std::sort(candidates.begin(), candidates.end());
353 
354  size_t bestCandidate = candidates.size() - 1;
355  bestCandidateFailureProbability = CandidateFailureProbability(
356  candidates.back().ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
357 
358  for (size_t i = bestCandidate - 1; i != -1; --i)
359  {
360  float iFailProb = CandidateFailureProbability(
361  candidates[i].ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
362  if (iFailProb > m_options.m_probability || candidates[i].UpperBound() < minSize ||
363  candidates[i].UpperBound() < candidates[bestCandidate].LowerBound())
364  {
365  break;
366  }
367  // check if this is an identical candidate
368  if (candidates[bestCandidate].IsEquivalent(
369  candidates[i], pc, m_options.m_epsilon, m_options.m_normalThresh))
370  {
371  continue;
372  }
373  bool isEquivalent = false;
374  for (size_t j = 0; j < beatenCands.size(); ++j)
375  {
376  if (beatenCands[j]->IsEquivalent(
377  candidates[i], pc, m_options.m_epsilon, m_options.m_normalThresh))
378  {
379  isEquivalent = true;
380  break;
381  }
382  }
383  if (isEquivalent)
384  {
385  continue;
386  }
387  do
388  {
389  if (candidates[i].UpperBound() > candidates[bestCandidate].UpperBound() &&
390  candidates[i].LowerBound() < candidates[bestCandidate].LowerBound())
391  {
392  bool dontBreak = candidates[i].ImproveBounds(octrees,
393  pc,
394  scoreVisitor,
395  currentSize,
396  m_options.m_bitmapEpsilon,
397  maxImproveSubsetDuringMaxSearch);
398  iFailProb = CandidateFailureProbability(candidates[i].ExpectedValue(),
399  currentSize - numInvalid,
400  drawnCandidates,
401  numLevels);
402  if (!dontBreak)
403  {
404  break;
405  }
406  }
407  else if (candidates[bestCandidate].UpperBound() > candidates[i].UpperBound() &&
408  candidates[bestCandidate].LowerBound() < candidates[i].LowerBound())
409  {
410  bool dontBreak =
411  candidates[bestCandidate].ImproveBounds(octrees,
412  pc,
413  scoreVisitor,
414  currentSize,
415  m_options.m_bitmapEpsilon,
416  maxImproveSubsetDuringMaxSearch);
417  bestCandidateFailureProbability =
418  CandidateFailureProbability(candidates[bestCandidate].ExpectedValue(),
419  currentSize - numInvalid,
420  drawnCandidates,
421  numLevels);
422  if (!dontBreak)
423  {
424  break;
425  }
426  }
427  else
428  {
429  bool dontBreak =
430  candidates[bestCandidate].ImproveBounds(octrees,
431  pc,
432  scoreVisitor,
433  currentSize,
434  m_options.m_bitmapEpsilon,
435  maxImproveSubsetDuringMaxSearch);
436  dontBreak = candidates[i].ImproveBounds(octrees,
437  pc,
438  scoreVisitor,
439  currentSize,
440  m_options.m_bitmapEpsilon,
441  maxImproveSubsetDuringMaxSearch) ||
442  dontBreak;
443  iFailProb = CandidateFailureProbability(candidates[i].ExpectedValue(),
444  currentSize - numInvalid,
445  drawnCandidates,
446  numLevels);
447  bestCandidateFailureProbability =
448  CandidateFailureProbability(candidates[bestCandidate].ExpectedValue(),
449  currentSize - numInvalid,
450  drawnCandidates,
451  numLevels);
452  if (!dontBreak)
453  {
454  break;
455  }
456  }
457  } while (bestCandidateFailureProbability <= m_options.m_probability &&
458  iFailProb <= m_options.m_probability && candidates[i].UpperBound() >= minSize &&
459  candidates[bestCandidate].UpperBound() >= minSize &&
460  candidates[i].UpperBound() > candidates[bestCandidate].LowerBound() &&
461  candidates[i].LowerBound() < candidates[bestCandidate].UpperBound());
462  if ((candidates[i] > candidates[bestCandidate] ||
463  bestCandidateFailureProbability > m_options.m_probability ||
464  candidates[bestCandidate].UpperBound() < minSize) &&
465  (iFailProb <= m_options.m_probability && candidates[i].UpperBound() >= minSize))
466  {
467  while (iFailProb <= m_options.m_probability && candidates[i].UpperBound() >= minSize &&
468  candidates[i] > candidates[bestCandidate] &&
469  candidates[i].ImproveBounds(octrees,
470  pc,
471  scoreVisitor,
472  currentSize,
473  m_options.m_bitmapEpsilon,
474  octrees.size()))
475  {
476  iFailProb = CandidateFailureProbability(candidates[i].ExpectedValue(),
477  currentSize - numInvalid,
478  drawnCandidates,
479  numLevels);
480  }
481  if (candidates[i] > candidates[bestCandidate])
482  {
483  beatenCands.push_back(&candidates[bestCandidate]);
484  bestCandidate = i;
485  bestCandidateFailureProbability = iFailProb;
486  }
487  else
488  {
489  beatenCands.push_back(&candidates[i]);
490  }
491  }
492  else
493  {
494  beatenCands.push_back(&candidates[i]);
495  }
496  if (bestCandidateFailureProbability > m_options.m_probability ||
497  candidates[bestCandidate].UpperBound() < minSize)
498  {
499  break;
500  }
501  } // end for
502 
503  while (candidates[bestCandidate].ImproveBounds(
504  octrees, pc, scoreVisitor, currentSize, m_options.m_bitmapEpsilon, octrees.size()))
505  ;
506 
507  bestCandidateFailureProbability =
508  CandidateFailureProbability(candidates[bestCandidate].ExpectedValue(),
509  currentSize - numInvalid,
510  drawnCandidates,
511  numLevels);
512 
513  if ((bestCandidateFailureProbability <= m_options.m_probability &&
514  candidates[bestCandidate].UpperBound() >= minSize) ||
515  (m_autoAcceptSize && candidates[bestCandidate].UpperBound() >= m_autoAcceptSize))
516  {
517  std::swap(candidates.back(), candidates[bestCandidate]);
518  *candidateFailProb = bestCandidateFailureProbability;
519  return true;
520  }
521  std::sort(candidates.begin(), candidates.end() /*, std::greater< Candidate >()*/);
522  return false;
523 }
524 
525 size_t
527  size_t beginIdx,
528  size_t endIdx,
530 {
531  const auto endtime = std::chrono::steady_clock::now() + m_options.m_maxruntime;
532  const auto timeout = [&]
533  {
534  return m_options.m_maxruntime.count() != Options::invalidRuntime &&
535  endtime <= std::chrono::steady_clock::now();
536  };
537  size_t pcSize = endIdx - beginIdx;
538  /*
539  * Initialization part
540  */
541  srand((unsigned int)time(NULL));
542  rn_setseed((size_t)time(NULL));
543 
544  CandidatesType candidates;
545 
547  subsetScoreVisitor(m_options.m_epsilon, m_options.m_normalThresh);
549  globalScoreVisitor(3 * m_options.m_epsilon, m_options.m_normalThresh);
550 
551  // construct random subsets
552  size_t subsets = std::max(int(std::floor(std::log((float)pcSize) / std::log(2.f))) - 9, 2);
554  bcube.Bound(pc.begin() + beginIdx, pc.begin() + endIdx);
555 
556  // construct stratified subsets
557  MiscLib::Vector<ImmediateOctreeType*> octrees(subsets);
558  for (size_t i = octrees.size(); i;)
559  {
560  --i;
561  size_t subsetSize = pcSize;
562  if (i)
563  {
564  subsetSize = subsetSize >> 1;
565  MiscLib::Vector<size_t> subsetIndices(subsetSize);
566  size_t bucketSize = pcSize / subsetSize;
567  for (size_t j = 0; j < subsetSize; ++j)
568  {
569  size_t index = rn_rand() % bucketSize;
570  index += j * bucketSize;
571  if (index >= pcSize)
572  {
573  index = pcSize - 1;
574  }
575  subsetIndices[j] = index + beginIdx;
576  }
577  // move all the indices to the end
578  std::sort(subsetIndices.begin(), subsetIndices.end(), std::greater<size_t>());
579  for (size_t j = pcSize - 1, i = 0; i < subsetIndices.size(); --j, ++i)
580  {
581  std::swap(pc[j + beginIdx], pc[subsetIndices[i]]);
582  }
583  }
584  octrees[i] = new ImmediateOctreeType;
585  octrees[i]->ContainedData(&pc);
586  octrees[i]->DataRange(pcSize - subsetSize + beginIdx, pcSize + beginIdx);
587  octrees[i]->MaxBucketSize() = 20;
588  octrees[i]->MaxSubdivisionLevel() = 10;
589  octrees[i]->Build(bcube);
590  pcSize -= subsetSize;
591  }
592 
593  pcSize = endIdx - beginIdx;
594 
595  // construct one global octree
596  MiscLib::Vector<size_t> globalOctreeIndices(pcSize);
597  for (size_t i = 0; i < pcSize; ++i)
598  {
599  globalOctreeIndices[i] = i + beginIdx;
600  }
601  IndexedOctreeType globalOctree;
602  globalOctree.MaxBucketSize() = 20;
603  globalOctree.MaxSubdivisionLevel() = 10;
604  globalOctree.IndexedData(globalOctreeIndices.begin(), globalOctreeIndices.end(), pc.begin());
605  globalOctree.Build(bcube);
606  size_t globalOctTreeMaxNodeDepth = globalOctree.MaxDepth();
607 
608  MiscLib::Vector<double> sampleLevelProbability(globalOctTreeMaxNodeDepth + 1);
609  for (size_t i = 0; i < sampleLevelProbability.size(); ++i)
610  {
611  sampleLevelProbability[i] = 1.0 / sampleLevelProbability.size();
612  }
613  size_t drawnCandidates = 0; // keep track of number of candidates
614  // that have been generated
615  float maxForgottenCandidate = 0; // the maximum size of a canidate
616  // that has been forgotten
617  size_t numTries = 0; // number of loops since last successful candidate
618  size_t numShapes = 0; // number of shapes found since the
619  // last housekeeping
620  size_t numInvalid = 0; // number of points that have been assigned
621  // to a shape since the last housekeeping
622  MiscLib::Vector<int> shapeIndex(pc.size(), -1); // maintains for every
623  // point the index of the shape it has been assigned to or
624  // -1 if the point is not assigned yet
625  subsetScoreVisitor.SetShapeIndex(shapeIndex);
626  globalScoreVisitor.SetShapeIndex(shapeIndex);
627  size_t currentSize = pcSize;
628  do
629  {
630  MiscLib::Vector<std::pair<float, size_t>> sampleLevelScores(sampleLevelProbability.size());
631  for (size_t i = 0; i < sampleLevelScores.size(); ++i)
632  {
633  sampleLevelScores[i] = std::make_pair(0.f, 0u);
634  }
635  MiscLib::Vector<double> sampleLevelProbSum(sampleLevelProbability.size());
636  sampleLevelProbSum[0] = sampleLevelProbability[0];
637  for (size_t i = 1; i < sampleLevelProbSum.size() - 1; ++i)
638  sampleLevelProbSum[i] = sampleLevelProbability[i] + sampleLevelProbSum[i - 1];
639  sampleLevelProbSum[sampleLevelProbSum.size() - 1] = 1;
640  // generate candidates
641  float bestExpectedValue = 0;
642  if (candidates.size())
643  {
644  bestExpectedValue = candidates.back().ExpectedValue();
645  }
646  bestExpectedValue = std::min((float)(currentSize - numInvalid), bestExpectedValue);
647  do
648  {
649  GenerateCandidates(globalOctree,
650  octrees,
651  pc,
652  subsetScoreVisitor,
653  currentSize,
654  numInvalid,
655  sampleLevelProbSum,
656  &drawnCandidates,
657  &sampleLevelScores,
658  &bestExpectedValue,
659  &candidates);
660  } while (CandidateFailureProbability(bestExpectedValue,
661  currentSize - numInvalid,
662  drawnCandidates,
663  globalOctTreeMaxNodeDepth) > m_options.m_probability &&
664  CandidateFailureProbability(m_options.m_minSupport,
665  currentSize - numInvalid,
666  drawnCandidates,
667  globalOctTreeMaxNodeDepth) > m_options.m_probability &&
668  !timeout());
669  // find the best candidate:
670  float bestCandidateFailureProbability;
671  float failureProbability = std::numeric_limits<float>::infinity();
672  bool foundCandidate = false;
673  size_t firstCandidateSize = 0;
674  while (FindBestCandidate(
675  candidates,
676  octrees,
677  pc,
678  subsetScoreVisitor,
679  currentSize,
680  drawnCandidates,
681  numInvalid,
682  std::max((size_t)m_options.m_minSupport, (size_t)(0.8f * firstCandidateSize)),
683  globalOctTreeMaxNodeDepth,
684  &maxForgottenCandidate,
685  &bestCandidateFailureProbability))
686  {
687  if (!foundCandidate)
688  {
689  // this is the first candidate
690  firstCandidateSize = (size_t)candidates.back().LowerBound();
691  // rescore levels
692  for (size_t i = 0; i < sampleLevelScores.size(); ++i)
693  {
694  sampleLevelScores[i] = std::make_pair(0.f, 0u);
695  }
696  for (size_t i = 0; i < candidates.size(); ++i)
697  {
698  if (candidates[i].ExpectedValue() * 1.4f > candidates.back().ExpectedValue())
699  {
700  size_t candLevel =
701  std::min(sampleLevelScores.size() - 1, candidates[i].Level());
702  ++sampleLevelScores[candLevel].first;
703  ++sampleLevelScores[candLevel].second;
704  }
705  }
706  UpdateLevelWeights(0.5f, sampleLevelScores, &sampleLevelProbability);
707  }
708  foundCandidate = true;
709  if (bestCandidateFailureProbability < failureProbability)
710  {
711  failureProbability = bestCandidateFailureProbability;
712  }
713  std::string candidateDescription;
714  candidates.back().Shape()->Description(&candidateDescription);
715  // do fitting
716  if (m_options.m_fitting != Options::NO_FITTING)
717  {
718  candidates.back().GlobalScore(globalScoreVisitor, globalOctree);
719  candidates.back().ConnectedComponent(pc, m_options.m_bitmapEpsilon);
720  Candidate clone;
721  candidates.back().Clone(&clone);
722  float oldScore, newScore;
723  size_t oldSize, newSize;
724  // get the weight once
725  newScore = clone.GlobalWeightedScore(globalScoreVisitor,
726  globalOctree,
727  pc,
728  3 * m_options.m_epsilon,
729  m_options.m_normalThresh,
730  m_options.m_bitmapEpsilon);
731  newSize = std::max(clone.Size(), candidates.back().Size());
732  bool allowDifferentShapes = false;
733  size_t fittingIter = 0;
734  do
735  {
736  ++fittingIter;
737  oldScore = newScore;
738  oldSize = newSize;
739  std::pair<size_t, float> score;
740  PrimitiveShape* shape = Fit(allowDifferentShapes,
741  *clone.Shape(),
742  pc,
743  clone.Indices()->begin(),
744  clone.Indices()->end(),
745  &score);
746  if (shape)
747  {
748  clone.Shape(shape);
749  newScore = clone.GlobalWeightedScore(globalScoreVisitor,
750  globalOctree,
751  pc,
752  3 * m_options.m_epsilon,
753  m_options.m_normalThresh,
754  m_options.m_bitmapEpsilon);
755  newSize = clone.Size();
756  shape->Release();
757  if (newScore > oldScore && newSize > m_options.m_minSupport)
758  {
759  clone.Clone(&candidates.back());
760  }
761  }
762  allowDifferentShapes = false;
763  } while (newScore > oldScore && fittingIter < 3);
764  }
765  else
766  {
767  candidates.back().GlobalScore(globalScoreVisitor, globalOctree);
768  candidates.back().ConnectedComponent(pc, m_options.m_bitmapEpsilon);
769  }
770  if (candidates.back().Size() == 0)
771  {
772  std::cout << "ERROR: candidate size == 0 after fitting" << std::endl;
773  }
774  // best candidate is ok!
775  // remove the points
776  shapes->push_back(std::make_pair(RefCountPtr<PrimitiveShape>(candidates.back().Shape()),
777  candidates.back().Indices()->size()));
778  for (size_t i = 0; i < candidates.back().Indices()->size(); ++i)
779  {
780  shapeIndex[(*(candidates.back().Indices()))[i]] = numShapes;
781  }
782  ++numShapes;
783  // update drawn candidates to reflect removal of points
784  // get the percentage of candidates that are invalid
785  drawnCandidates = std::pow(1.f - (candidates.back().Indices()->size() /
786  float(currentSize - numInvalid)),
787  3.f) *
788  drawnCandidates;
789  numInvalid += candidates.back().Indices()->size();
790  candidates.pop_back();
791  if (numInvalid > currentSize / 4) // more than half of the points assigned?
792  {
793  // do a housekeeping step
794  //this is a two stage procedure:
795  // 1) determine the new address of each Point and store it in the shapeIndex array
796  // 2) swap Points according to new addresses
797  size_t begin = beginIdx, end = beginIdx + currentSize;
798 
799  // these hold the address ranges for the lately detected shapes
800  MiscLib::Vector<size_t> shapeIterators(numShapes);
801  int shapeIt = shapes->size() - numShapes;
802  for (size_t i = 0; i < numShapes; ++i, ++shapeIt)
803  {
804  shapeIterators[i] = end -= ((*shapes)[shapeIt]).second;
805  }
806 
807  MiscLib::Vector<size_t> subsetSizes(octrees.size(), 0);
808  for (size_t i = beginIdx, j = 0; i < beginIdx + currentSize; ++i)
809  if (shapeIndex[i] < 0)
810  {
811  if (i >= octrees[j]->end() - pc.begin() + beginIdx &&
812  j < octrees.size() - 1)
813  {
814  ++j;
815  }
816  shapeIndex[i] = begin++;
817  ++subsetSizes[j];
818  }
819  else
820  {
821  shapeIndex[i] = shapeIterators[shapeIndex[i]]++;
822  }
823 
824  // check if small subsets should be merged
825  size_t mergedSubsets = 0;
826  if (subsetSizes[0] < 500 && subsetSizes.size() > 1)
827  {
828  // should be merged
829  while (subsetSizes[0] < 500 && subsetSizes.size() > 1)
830  {
831  subsetSizes[1] += subsetSizes[0];
832  subsetSizes.erase(subsetSizes.begin());
833  delete octrees[0];
834  octrees.erase(octrees.begin());
835  ++mergedSubsets;
836  }
837  }
838 
839  // reindex global octree
840  size_t minInvalidIndex = currentSize - numInvalid + beginIdx;
841 #pragma parallel for schedule(static)
842  for (intptr_t i = 0, j = 0; i < globalOctreeIndices.size(); ++i)
843  if (shapeIndex[globalOctreeIndices[i]] < minInvalidIndex)
844  {
845  globalOctreeIndices[j++] = shapeIndex[globalOctreeIndices[i]];
846  }
847  globalOctreeIndices.resize(currentSize - numInvalid);
848 
849  // reindex candidates (this also recomputes the bounds)
850 #pragma parallel for schedule(static)
851  for (intptr_t i = 0; i < candidates.size(); ++i)
852  candidates[i].Reindex(shapeIndex,
853  minInvalidIndex,
854  mergedSubsets,
855  subsetSizes,
856  pc,
857  currentSize - numInvalid,
858  m_options.m_epsilon,
859  m_options.m_normalThresh,
860  m_options.m_bitmapEpsilon);
861 
862  //regarding swapping it is best to swap both the addresses and the data
863  for (size_t i = beginIdx; i < beginIdx + currentSize; ++i)
864  while (i != shapeIndex[i])
865  {
866  pc.swapPoints(i, shapeIndex[i]);
867  std::swap(shapeIndex[i], shapeIndex[shapeIndex[i]]);
868  }
869 
870  numInvalid = 0;
871 
872  // rebuild subset octrees
873  if (mergedSubsets) // the octree for the first subset has to be constructed
874  {
875  //std::cout << "Attention: Merged " << mergedSubsets << " subsets!" << std::endl;
876  MiscLib::Vector<size_t> shuffleIndices(beginIdx + subsetSizes[0]),
877  reindex(beginIdx + subsetSizes[0]);
878  for (size_t i = 0; i < shuffleIndices.size(); ++i)
879  {
880  shuffleIndices[i] = i;
881  }
882  delete octrees[0];
883  octrees[0] = new ImmediateOctreeType();
884  octrees[0]->ContainedData(&pc);
885  octrees[0]->DataRange(beginIdx, beginIdx + subsetSizes[0]);
886  octrees[0]->MaxBucketSize() = 20;
887  octrees[0]->MaxSubdivisionLevel() = 10;
888  octrees[0]->ShuffleIndices(&shuffleIndices);
889  octrees[0]->Build(bcube);
890  octrees[0]->ShuffleIndices(NULL);
891  for (size_t i = 0; i < shuffleIndices.size(); ++i)
892  {
893  reindex[shuffleIndices[i]] = i;
894  }
895 // reindex global octree
896 #pragma omp parallel for schedule(static)
897  for (intptr_t i = 0; i < globalOctreeIndices.size(); ++i)
898  if (globalOctreeIndices[i] < reindex.size())
899  {
900  globalOctreeIndices[i] = reindex[globalOctreeIndices[i]];
901  }
902 // reindex candidates
903 #pragma omp parallel for schedule(static, 100)
904  for (intptr_t i = 0; i < candidates.size(); ++i)
905  {
906  candidates[i].Reindex(reindex);
907  }
908  for (size_t i = 1, begin = subsetSizes[0] + beginIdx; i < octrees.size();
909  begin += subsetSizes[i], ++i)
910  {
911  octrees[i]->DataRange(begin, begin + subsetSizes[i]);
912  octrees[i]->Rebuild();
913  if (octrees[i]->Root()->Size() != subsetSizes[i])
914  {
915  std::cout << "ERROR IN REBUILD!!!!" << std::endl;
916  }
917  }
918  }
919  else
920  for (size_t i = 0, begin = beginIdx; i < octrees.size();
921  begin += subsetSizes[i], ++i)
922  {
923  octrees[i]->DataRange(begin, begin + subsetSizes[i]);
924  octrees[i]->Rebuild();
925  }
926 
927  //so everything is in its correct place, but we need to update the global octree ranges
928  currentSize = globalOctreeIndices.size();
929 
930  globalOctree.IndexedRange(globalOctreeIndices.begin(), globalOctreeIndices.end());
931  globalOctTreeMaxNodeDepth = globalOctree.Rebuild();
932  if (globalOctree.Root()->Size() != globalOctreeIndices.size())
933  {
934  std::cout << "ERROR IN GLOBAL REBUILD!" << std::endl;
935  }
936  sampleLevelProbability.resize(globalOctTreeMaxNodeDepth + 1);
937 
938  //shapeIndex.resize(globalOctreeIndices.size());
939  std::fill(
940  shapeIndex.begin() + beginIdx, shapeIndex.begin() + beginIdx + currentSize, -1);
941  numShapes = 0;
942  }
943  else
944  {
945  // the bounds of the candidates have become invalid and have to be
946  // recomputed
947 #pragma parallel for schedule(static, 100)
948  for (size_t i = 0; i < candidates.size(); ++i)
949  candidates[i].RecomputeBounds(octrees,
950  pc,
951  subsetScoreVisitor,
952  currentSize - numInvalid,
953  m_options.m_epsilon,
954  m_options.m_normalThresh,
955  m_options.m_bitmapEpsilon);
956  }
957  // remove all candidates that have become obsolete
958  std::sort(candidates.begin(), candidates.end(), std::greater<Candidate>());
959  size_t remainingCandidates = 0;
960  for (size_t i = 0; i < candidates.size(); ++i)
961  if (candidates[i].ExpectedValue() >= m_options.m_minSupport &&
962  candidates[i].Size() > 0)
963  {
964  candidates[remainingCandidates++] = candidates[i];
965  }
966  candidates.resize(remainingCandidates);
967  } // Ende abgrasen
968  if (foundCandidate)
969  {
970  std::sort(candidates.begin(), candidates.end(), std::greater<Candidate>());
971  size_t remainingCandidates = 0;
972  size_t nonConnectedCount = 0;
973  for (size_t i = 0; i < candidates.size(); ++i)
974  if (candidates[i].ExpectedValue() >= m_options.m_minSupport &&
975  (candidates[i].ComputedSubsets() > octrees.size() - 3 ||
976  nonConnectedCount++ < 500))
977  {
978  candidates[remainingCandidates++] = candidates[i];
979  }
980  else if (candidates[i].ExpectedValue() > maxForgottenCandidate)
981  {
982  maxForgottenCandidate = candidates[i].ExpectedValue();
983  }
984  candidates.resize(remainingCandidates);
985 
986  numTries = 0;
987  }
988  else
989  {
990  numTries++;
991  }
992  } while (CandidateFailureProbability(m_options.m_minSupport,
993  currentSize - numInvalid,
994  drawnCandidates,
995  globalOctTreeMaxNodeDepth) > m_options.m_probability &&
996  (currentSize - numInvalid) >= m_options.m_minSupport && !timeout());
997 
998  if (numInvalid)
999  {
1000  // rearrange the last shapes
1001  //this is a two stage procedure:
1002  // 1) determine the new address of each Point and store it in the shapeIndex array
1003  // 2) swap Points according to new addresses
1004  size_t begin = beginIdx, end = beginIdx + currentSize;
1005  // these hold the address ranges for the lately detected shapes
1006  MiscLib::Vector<size_t> shapeIterators(numShapes);
1007  int shapeIt = shapes->size() - numShapes;
1008  for (size_t i = 0; i < numShapes; ++i, ++shapeIt)
1009  {
1010  shapeIterators[i] = end -= ((*shapes)[shapeIt]).second;
1011  }
1012 
1013  for (size_t i = beginIdx; i < beginIdx + currentSize; ++i)
1014  if (shapeIndex[i] < 0)
1015  {
1016  shapeIndex[i] = begin++;
1017  }
1018  else
1019  {
1020  shapeIndex[i] = shapeIterators[shapeIndex[i]]++;
1021  }
1022 
1023  //regarding swapping it is best to swap both the addresses and the data
1024  for (size_t i = beginIdx; i < beginIdx + currentSize; ++i)
1025  while (i != shapeIndex[i])
1026  {
1027  pc.swapPoints(i, shapeIndex[i]);
1028  std::swap(shapeIndex[i], shapeIndex[shapeIndex[i]]);
1029  }
1030  }
1031  // clean up subset octrees
1032  for (size_t i = 0; i < octrees.size(); ++i)
1033  {
1034  delete octrees[i];
1035  }
1036  // optimize parametrizations
1037  size_t eidx = endIdx;
1038  for (size_t i = 0; i < shapes->size(); ++i)
1039  {
1040  size_t bidx = eidx - (*shapes)[i].second;
1041  (*shapes)[i].first->OptimizeParametrization(pc, bidx, eidx, m_options.m_bitmapEpsilon);
1042  eidx = bidx;
1043  }
1044 
1045  // prune nonsense shapes
1046  for (size_t i = shapes->size(); i != 0; --i)
1047  {
1048  if (shapes->at(i - 1).second == 0)
1049  {
1050  shapes->erase(shapes->begin() + i - 1);
1051  }
1052  }
1053  return currentSize - numInvalid;
1054 }
1055 
1056 bool
1057 RansacShapeDetector::DrawSamplesStratified(const IndexedOctreeType& oct,
1058  size_t numSamples,
1059  size_t depth,
1060  const MiscLib::Vector<int>& shapeIndex,
1061  MiscLib::Vector<size_t>* samples,
1062  const IndexedOctreeType::CellType** node) const
1063 {
1064  for (size_t tries = 0; tries < m_maxCandTries; tries++)
1065  {
1066  samples->clear();
1067  //get first point, which also determines octree cell
1068  size_t first;
1069  do
1070  {
1071  first = oct.Dereference(rn_rand() % oct.size());
1072  } while (shapeIndex[first] != -1);
1073  samples->push_back(first);
1074 
1075  std::pair<size_t, size_t> nodeRange;
1076  *node = oct.NodeContainingPoint(oct.at(first), depth, numSamples, &nodeRange);
1077 
1078  if ((*node)->Size() < numSamples)
1079  {
1080  continue;
1081  }
1082 
1083  while (samples->size() < numSamples)
1084  {
1085  size_t i, iter = 0;
1086  do
1087  {
1088  i = oct.Dereference(rn_rand() % (*node)->Size() + nodeRange.first);
1089  } while ((shapeIndex[i] != -1 ||
1090  std::find(samples->begin(), samples->end(), i) != samples->end()) &&
1091  iter++ < 40);
1092  if (iter >= 40)
1093  {
1094  break;
1095  }
1096  samples->push_back(i);
1097  }
1098 
1099  if (samples->size() == numSamples)
1100  {
1101  return true;
1102  }
1103  }
1104  return false;
1105 }
1106 
1108 RansacShapeDetector::Fit(bool allowDifferentShapes,
1109  const PrimitiveShape& initialShape,
1110  const PointCloud& pc,
1113  std::pair<size_t, float>* score) const
1114 {
1115  if (!m_constructors.size())
1116  {
1117  return NULL;
1118  }
1119  PrimitiveShape* bestShape = NULL;
1120  if (m_options.m_fitting == Options::LS_FITTING)
1121  bestShape = initialShape.LSFit(
1122  pc, m_options.m_epsilon, m_options.m_normalThresh, begin, end, score);
1123  return bestShape;
1124 }
MiscLib::Vector::front
T & front()
Definition: Vector.h:532
FlatNormalThreshPointCompatibilityFunc.h
GfxTL::AACube
Definition: AACube.h:11
RansacShapeDetector::Detect
size_t Detect(PointCloud &pc, size_t begin, size_t end, MiscLib::Vector< std::pair< MiscLib::RefCountPtr< PrimitiveShape >, size_t >> *shapes)
Definition: RansacShapeDetector.cpp:526
GfxTL::AACubeTree::NodeContainingPoint
const CellType * NodeContainingPoint(const PointT &point, size_t maxLevel, size_t minSize, CellRange *range) const
Definition: AACubeTree.h:442
MiscLib::Vector::begin
T * begin()
Definition: Vector.h:472
MiscLib::RefCounted
Definition: RefCounted.h:10
MiscLib::RefCount::Release
unsigned int Release() const
Definition: RefCount.h:43
MiscLib::NoShrinkVector::pop_back
void pop_back()
Definition: NoShrinkVector.h:393
RansacShapeDetector::Options::invalidRuntime
static constexpr auto invalidRuntime
Definition: RansacShapeDetector.h:25
MiscLib::Vector::push_back
void push_back(const T &v)
Definition: Vector.h:354
Performance.h
index
uint8_t index
Definition: EtherCATFrame.h:59
ScorePrimitiveShapeVisitor.h
RansacShapeDetector.h
ScorePrimitiveShapeVisitorImpl::SetShapeIndex
void SetShapeIndex(const MiscLib::Vector< int > &shapeIndex)
Definition: ScorePrimitiveShapeVisitor.h:51
Candidate::Clone
void Clone(Candidate *c) const
Definition: Candidate.h:193
MiscLib::Vector::resize
void resize(size_type s, const value_type &v)
Definition: Vector.h:227
Candidate::ImproveBounds
bool ImproveBounds(const MiscLib::Vector< ImmediateOctreeType * > &octrees, const PointCloud &pc, ScoreVisitorT &scoreVisitor, size_t currentSize, float bitmapEpsilon, size_t maxSubset, size_t minPoints=500)
Definition: Candidate.h:245
Candidate::UpperBound
float UpperBound() const
Definition: Candidate.h:44
GfxTL::AACube::Bound
void Bound(const Points &points, size_t size)
Definition: AACube.h:86
MiscLib::Vector::erase
void erase(T *where)
Definition: Vector.h:426
PrimitiveShape
PrimtiveShape is a shape primitive in conjunction with a parametrization.
Definition: PrimitiveShape.h:34
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
RansacShapeDetector::Options::m_bitmapEpsilon
float m_bitmapEpsilon
Definition: RansacShapeDetector.h:42
Candidate::Size
size_t Size() const
Definition: Candidate.h:132
MiscLib::NoShrinkVector::end
T * end()
Definition: NoShrinkVector.h:412
PrimitiveShape::LSFit
virtual PrimitiveShape * LSFit(const PointCloud &pc, float epsilon, float normalThresh, MiscLib::Vector< size_t >::const_iterator begin, MiscLib::Vector< size_t >::const_iterator end, std::pair< size_t, float > *score) const =0
CandidateHeapPred
Definition: RansacShapeDetector.cpp:216
MiscLib::Vector
Definition: Vector.h:19
MiscLib::rn_setseed
void rn_setseed(size_t)
Definition: Random.cpp:27
Candidate::Shape
PrimitiveShape * Shape()
Definition: Candidate.h:26
MiscLib::Vector< PrimitiveShapeConstructor * >::const_iterator
const typedef PrimitiveShapeConstructor * * const_iterator
Definition: Vector.h:25
PrimitiveShapeConstructor
Definition: PrimitiveShapeConstructor.h:24
Candidate
Definition: Candidate.h:19
RansacShapeDetector::Options::m_normalThresh
float m_normalThresh
Definition: RansacShapeDetector.h:40
RansacShapeDetector::RansacShapeDetector
RansacShapeDetector()
Definition: RansacShapeDetector.cpp:25
MiscLib::NoShrinkVector
Definition: NoShrinkVector.h:17
armarx::armem::client::util::swap
void swap(SubscriptionHandle &first, SubscriptionHandle &second)
Definition: SubscriptionHandle.cpp:66
MiscLib::Vector::size
size_type size() const
Definition: Vector.h:215
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
Candidate::ExpectedValue
float ExpectedValue() const
Definition: Candidate.h:68
PrimitiveShape::DistanceAndNormalDeviation
virtual void DistanceAndNormalDeviation(const Vec3f &p, const Vec3f &n, std::pair< float, float > *dn) const =0
MiscLib::rn_rand
size_t rn_rand()
Definition: Random.h:22
MiscLib::Vector::pop_back
void pop_back()
Definition: Vector.h:451
Candidate::ComputedSubsets
size_t ComputedSubsets() const
Definition: Candidate.h:62
Candidate::GlobalWeightedScore
float GlobalWeightedScore(ScoreVisitorT &scoreVisitor, const IndexedOctreeType &oct, const PointCloud &pc, float epsilon, float normalThresh, float bitmapEpsilon)
Definition: Candidate.h:403
RansacShapeDetector::~RansacShapeDetector
virtual ~RansacShapeDetector()
Definition: RansacShapeDetector.cpp:35
RansacShapeDetector::Options
Definition: RansacShapeDetector.h:23
RansacShapeDetector::Options::NO_FITTING
@ NO_FITTING
Definition: RansacShapeDetector.h:46
MiscLib::NoShrinkVector::resize
void resize(size_type s, const value_type &v)
Definition: NoShrinkVector.h:235
MiscLib
Definition: AlignedAllocator.h:12
Candidate::IsEquivalent
bool IsEquivalent(const Candidate &c, const PointCloud &pc, float epsilon, float normalThresh) const
Definition: Candidate.cpp:110
MiscLib::Vector::end
T * end()
Definition: Vector.h:484
max
T max(T t1, T t2)
Definition: gdiam.h:51
RansacShapeDetector::Options::m_fitting
enum RansacShapeDetector::Options::@43 m_fitting
CandidateHeapPred::operator()
bool operator()(const Candidate *a, const Candidate *b) const
Definition: RansacShapeDetector.cpp:219
MiscLib::RefCountPtr< PrimitiveShape >
Candidate::Indices
MiscLib::RefCounted< MiscLib::Vector< size_t > > * Indices()
Definition: Candidate.h:50
RansacShapeDetector::Options::m_probability
float m_probability
Definition: RansacShapeDetector.h:50
PointCloud
Definition: PointCloud.h:85
RansacShapeDetector::Options::m_minSupport
unsigned int m_minSupport
Definition: RansacShapeDetector.h:41
GfxTL::AACubeTreeCell
Definition: AACubeTree.h:15
ImmediateOctreeType
GfxTL::AACubeTree< 3, ScoreAACubeTreeStrategy< 3, RebuildAACubeTreeStrategy< GfxTL::BucketSizeMaxLevelSubdivisionTreeStrategy< GfxTL::CellLevelTreeStrategy< GfxTL::CellCenterAACubeTreeStrategy< 3, GfxTL::BaseAACubeTreeStrategy< GfxTL::CellRangeDataTreeStrategy< GfxTL::NullTreeStrategy, GfxTL::ShuffleIndicesTreeDataKernelStrategy< GfxTL::ImmediateRangeTreeDataKernel< PointCloud >, MiscLib::Vector< size_t > > > > > > > > > > ImmediateOctreeType
Definition: Octree.h:31
RansacShapeDetector::Options::m_maxruntime
std::chrono::milliseconds m_maxruntime
Definition: RansacShapeDetector.h:51
Random.h
RansacShapeDetector::Options::m_epsilon
float m_epsilon
Definition: RansacShapeDetector.h:39
magic_enum::detail::find
constexpr std::size_t find(string_view str, char_type c) noexcept
Definition: magic_enum.hpp:309
RansacShapeDetector::Options::LS_FITTING
@ LS_FITTING
Definition: RansacShapeDetector.h:47
MiscLib::NoShrinkVector::begin
T * begin()
Definition: NoShrinkVector.h:400
ScorePrimitiveShapeVisitor
Definition: ScorePrimitiveShapeVisitor.h:111
MiscLib::NoShrinkVector::back
T & back()
Definition: NoShrinkVector.h:448
Octree.h
pc
Introduction Thank you for taking interest in our work and downloading this software This library implements the algorithm described in the paper R R R Klein Efficient RANSAC for Point Cloud Shape in Computer Graphics Blackwell June If you use this software you should cite the aforementioned paper in any resulting publication Please send comments or bug reports to Ruwen Roland BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE Example usage This section shows how to use the library to detect the shapes in a point cloud PointCloud pc
Definition: ReadMe.txt:68
MiscLib::NoShrinkVector::size
size_type size() const
Definition: NoShrinkVector.h:223
min
T min(T t1, T t2)
Definition: gdiam.h:44
Candidate.h
shapes
MiscLib::Vector< std::pair< MiscLib::RefCountPtr< PrimitiveShape >, size_t > > shapes
Definition: ReadMe.txt:92
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
GfxTL::AACubeTree::Build
void Build()
Definition: AACubeTree.h:356
MiscLib::Vector::clear
void clear()
Definition: Vector.h:175
GfxTL::AACubeTree
Definition: AACubeTree.h:338
RansacShapeDetector::Add
void Add(PrimitiveShapeConstructor *c)
Definition: RansacShapeDetector.cpp:46