26 m_maxCandTries(20), m_reqSamples(0), m_autoAcceptSize(0)
31 m_options(options), m_maxCandTries(20), m_reqSamples(0), m_autoAcceptSize(0)
50 if (
c->RequiredSamples() > m_reqSamples)
52 m_reqSamples =
c->RequiredSamples();
57 RansacShapeDetector::StatBucket(
float score)
const
61 std::floor((std::log(score) - std::log((
float)m_options.
m_minSupport)) / std::log(1.21f)) +
70 RansacShapeDetector::UpdateLevelWeights(
76 double newSampleLevelProbabilitySum = 0;
77 for (
size_t i = 0; i < newSampleLevelProbability.size(); ++i)
79 if ((*sampleLevelProbability)[i] > 0)
81 newSampleLevelProbability[i] = (levelScores[i].first / (*sampleLevelProbability)[i]);
85 newSampleLevelProbability[i] = 0;
87 newSampleLevelProbabilitySum += newSampleLevelProbability[i];
90 for (
size_t i = 0; i < newSampleLevelProbability.size(); ++i)
92 newSampleLevelProbability[i] = .9f * newSampleLevelProbability[i] +
93 .1f * newSampleLevelProbabilitySum / levelScores.size();
94 newSum += newSampleLevelProbability[i];
96 for (
size_t i = 0; i < sampleLevelProbability->
size(); ++i)
98 (*sampleLevelProbability)[i] = (1.f - factor) * (*sampleLevelProbability)[i] +
99 factor * (newSampleLevelProbability[i] / newSum);
103 template <
class ScoreVisitorT>
105 RansacShapeDetector::GenerateCandidates(
109 ScoreVisitorT& scoreVisitor,
113 size_t* drawnCandidates,
115 float* bestExpectedValue,
116 CandidatesType* candidates)
const
122 ScoreVisitorT scoreVisitorCopy(scoreVisitor);
123 #pragma omp for schedule(dynamic, 10) reduction(+ : genCands)
124 for (
int candIter = 0; candIter < 200; ++candIter)
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)
137 if (!DrawSamplesStratified(globalOctree,
140 scoreVisitorCopy.GetShapeIndex(),
148 size_t c = samples.
size();
150 for (
size_t i = 0; i < samples.
size(); ++i)
152 samplePoints[i] = globalOctree.at(samples[i]).pos;
153 samplePoints[i +
c] = globalOctree.at(samples[i]).normal;
158 iend = m_constructors.
end();
162 if ((*i)->RequiredSamples() > samples.
size() ||
163 !(shape = (*i)->Construct(samplePoints)))
168 std::pair<float, float> dn;
169 bool verified =
true;
170 for (
size_t i = 0; i <
c; ++i)
173 if (!scoreVisitorCopy.PointCompFunc()(dn.first, dn.second))
186 cand.Indices()->Release();
194 (*sampleLevelScores)[node->Level()].first += cand.ExpectedValue();
195 ++(*sampleLevelScores)[node->Level()].second;
202 (*sampleLevelScores)[node->Level()].first += cand.ExpectedValue();
203 ++(*sampleLevelScores)[node->Level()].second;
204 candidates->push_back(cand);
205 if (cand.ExpectedValue() > *bestExpectedValue)
207 *bestExpectedValue = cand.ExpectedValue();
213 *drawnCandidates += genCands;
225 template <
class ScoreVisitorT>
227 RansacShapeDetector::FindBestCandidate(CandidatesType& candidates,
230 ScoreVisitorT& scoreVisitor,
232 size_t drawnCandidates,
236 float* maxForgottenCandidate,
237 float* candidateFailProb)
const
239 if (!candidates.size())
243 size_t maxImproveSubsetDuringMaxSearch = octrees.
size();
245 std::sort(candidates.begin(), candidates.end());
247 if (candidates.size() && candidates.back().ExpectedValue() < *maxForgottenCandidate)
251 drawnCandidates =
std::max(candidates.size(), (
size_t)1);
252 *maxForgottenCandidate = 0;
256 for (
size_t i = candidates.size() - 1; i != -1; --i)
258 if (CandidateFailureProbability(candidates[i].ExpectedValue(),
259 currentSize - numInvalid,
268 if (!candHeap.
size())
279 float bestCandidateFailureProbability;
280 while (candHeap.
size())
289 bool isEquivalent =
false;
290 for (
size_t j = 0; j < beatenCands.
size(); ++j)
292 if (beatenCands[j]->IsEquivalent(
305 bestCandidateFailureProbability = CandidateFailureProbability(
306 trial->
ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
308 (bestCandidateFailureProbability <= m_options.
m_probability) &&
313 bestCandidateFailureProbability = CandidateFailureProbability(
314 trial->
ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
316 if (bestCandidateFailureProbability <= m_options.
m_probability &&
318 *trial >= *candHeap.
front())
322 if (bestCandidateFailureProbability <= m_options.
m_probability &&
332 trial = candHeap.
front();
336 bestCandidateFailureProbability = CandidateFailureProbability(
337 trial->
ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
338 while (bestCandidateFailureProbability <= m_options.
m_probability &&
343 bestCandidateFailureProbability = CandidateFailureProbability(
344 trial->
ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
346 if ((bestCandidateFailureProbability > m_options.
m_probability ||
348 (!m_autoAcceptSize || trial->
UpperBound() < m_autoAcceptSize))
352 std::sort(candidates.begin(), candidates.end());
354 size_t bestCandidate = candidates.size() - 1;
355 bestCandidateFailureProbability = CandidateFailureProbability(
356 candidates.back().ExpectedValue(), currentSize - numInvalid, drawnCandidates, numLevels);
358 for (
size_t i = bestCandidate - 1; i != -1; --i)
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())
368 if (candidates[bestCandidate].IsEquivalent(
373 bool isEquivalent =
false;
374 for (
size_t j = 0; j < beatenCands.
size(); ++j)
376 if (beatenCands[j]->IsEquivalent(
389 if (candidates[i].UpperBound() > candidates[bestCandidate].UpperBound() &&
390 candidates[i].LowerBound() < candidates[bestCandidate].LowerBound())
392 bool dontBreak = candidates[i].ImproveBounds(octrees,
397 maxImproveSubsetDuringMaxSearch);
398 iFailProb = CandidateFailureProbability(candidates[i].ExpectedValue(),
399 currentSize - numInvalid,
407 else if (candidates[bestCandidate].UpperBound() > candidates[i].UpperBound() &&
408 candidates[bestCandidate].LowerBound() < candidates[i].LowerBound())
411 candidates[bestCandidate].ImproveBounds(octrees,
416 maxImproveSubsetDuringMaxSearch);
417 bestCandidateFailureProbability =
418 CandidateFailureProbability(candidates[bestCandidate].ExpectedValue(),
419 currentSize - numInvalid,
430 candidates[bestCandidate].ImproveBounds(octrees,
435 maxImproveSubsetDuringMaxSearch);
436 dontBreak = candidates[i].ImproveBounds(octrees,
441 maxImproveSubsetDuringMaxSearch) ||
443 iFailProb = CandidateFailureProbability(candidates[i].ExpectedValue(),
444 currentSize - numInvalid,
447 bestCandidateFailureProbability =
448 CandidateFailureProbability(candidates[bestCandidate].ExpectedValue(),
449 currentSize - numInvalid,
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] ||
464 candidates[bestCandidate].UpperBound() < minSize) &&
465 (iFailProb <= m_options.
m_probability && candidates[i].UpperBound() >= minSize))
467 while (iFailProb <= m_options.
m_probability && candidates[i].UpperBound() >= minSize &&
468 candidates[i] > candidates[bestCandidate] &&
469 candidates[i].ImproveBounds(octrees,
476 iFailProb = CandidateFailureProbability(candidates[i].ExpectedValue(),
477 currentSize - numInvalid,
481 if (candidates[i] > candidates[bestCandidate])
483 beatenCands.
push_back(&candidates[bestCandidate]);
485 bestCandidateFailureProbability = iFailProb;
496 if (bestCandidateFailureProbability > m_options.
m_probability ||
497 candidates[bestCandidate].UpperBound() < minSize)
503 while (candidates[bestCandidate].ImproveBounds(
507 bestCandidateFailureProbability =
508 CandidateFailureProbability(candidates[bestCandidate].ExpectedValue(),
509 currentSize - numInvalid,
513 if ((bestCandidateFailureProbability <= m_options.
m_probability &&
514 candidates[bestCandidate].UpperBound() >= minSize) ||
515 (m_autoAcceptSize && candidates[bestCandidate].UpperBound() >= m_autoAcceptSize))
517 std::swap(candidates.back(), candidates[bestCandidate]);
518 *candidateFailProb = bestCandidateFailureProbability;
521 std::sort(candidates.begin(), candidates.end() );
531 const auto endtime = std::chrono::steady_clock::now() + m_options.
m_maxruntime;
532 const auto timeout = [&]
535 endtime <= std::chrono::steady_clock::now();
537 size_t pcSize = endIdx - beginIdx;
541 srand((
unsigned int)time(NULL));
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);
558 for (
size_t i = octrees.
size(); i;)
561 size_t subsetSize = pcSize;
564 subsetSize = subsetSize >> 1;
566 size_t bucketSize = pcSize / subsetSize;
567 for (
size_t j = 0; j < subsetSize; ++j)
570 index += j * bucketSize;
575 subsetIndices[j] =
index + beginIdx;
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)
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;
593 pcSize = endIdx - beginIdx;
597 for (
size_t i = 0; i < pcSize; ++i)
599 globalOctreeIndices[i] = i + beginIdx;
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();
609 for (
size_t i = 0; i < sampleLevelProbability.
size(); ++i)
611 sampleLevelProbability[i] = 1.0 / sampleLevelProbability.
size();
613 size_t drawnCandidates = 0;
615 float maxForgottenCandidate = 0;
618 size_t numShapes = 0;
620 size_t numInvalid = 0;
627 size_t currentSize = pcSize;
631 for (
size_t i = 0; i < sampleLevelScores.
size(); ++i)
633 sampleLevelScores[i] = std::make_pair(0.f, 0u);
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;
641 float bestExpectedValue = 0;
642 if (candidates.
size())
644 bestExpectedValue = candidates.
back().ExpectedValue();
646 bestExpectedValue =
std::min((
float)(currentSize - numInvalid), bestExpectedValue);
649 GenerateCandidates(globalOctree,
660 }
while (CandidateFailureProbability(bestExpectedValue,
661 currentSize - numInvalid,
665 currentSize - numInvalid,
670 float bestCandidateFailureProbability;
671 float failureProbability = std::numeric_limits<float>::infinity();
672 bool foundCandidate =
false;
673 size_t firstCandidateSize = 0;
674 while (FindBestCandidate(
683 globalOctTreeMaxNodeDepth,
684 &maxForgottenCandidate,
685 &bestCandidateFailureProbability))
690 firstCandidateSize = (size_t)candidates.
back().LowerBound();
692 for (
size_t i = 0; i < sampleLevelScores.
size(); ++i)
694 sampleLevelScores[i] = std::make_pair(0.f, 0u);
696 for (
size_t i = 0; i < candidates.
size(); ++i)
698 if (candidates[i].ExpectedValue() * 1.4f > candidates.
back().ExpectedValue())
701 std::min(sampleLevelScores.
size() - 1, candidates[i].Level());
702 ++sampleLevelScores[candLevel].first;
703 ++sampleLevelScores[candLevel].second;
706 UpdateLevelWeights(0.5f, sampleLevelScores, &sampleLevelProbability);
708 foundCandidate =
true;
709 if (bestCandidateFailureProbability < failureProbability)
711 failureProbability = bestCandidateFailureProbability;
713 std::string candidateDescription;
714 candidates.
back().Shape()->Description(&candidateDescription);
718 candidates.
back().GlobalScore(globalScoreVisitor, globalOctree);
721 candidates.
back().Clone(&clone);
722 float oldScore, newScore;
723 size_t oldSize, newSize;
732 bool allowDifferentShapes =
false;
733 size_t fittingIter = 0;
739 std::pair<size_t, float> score;
755 newSize = clone.
Size();
757 if (newScore > oldScore && newSize > m_options.
m_minSupport)
762 allowDifferentShapes =
false;
763 }
while (newScore > oldScore && fittingIter < 3);
767 candidates.
back().GlobalScore(globalScoreVisitor, globalOctree);
770 if (candidates.
back().Size() == 0)
772 std::cout <<
"ERROR: candidate size == 0 after fitting" << std::endl;
777 candidates.
back().Indices()->size()));
778 for (
size_t i = 0; i < candidates.
back().Indices()->size(); ++i)
780 shapeIndex[(*(candidates.
back().Indices()))[i]] = numShapes;
785 drawnCandidates = std::pow(1.f - (candidates.
back().Indices()->size() /
786 float(currentSize - numInvalid)),
789 numInvalid += candidates.
back().Indices()->size();
791 if (numInvalid > currentSize / 4)
797 size_t begin = beginIdx, end = beginIdx + currentSize;
801 int shapeIt =
shapes->size() - numShapes;
802 for (
size_t i = 0; i < numShapes; ++i, ++shapeIt)
804 shapeIterators[i] = end -= ((*shapes)[shapeIt]).second;
808 for (
size_t i = beginIdx, j = 0; i < beginIdx + currentSize; ++i)
809 if (shapeIndex[i] < 0)
811 if (i >= octrees[j]->end() -
pc.begin() + beginIdx &&
812 j < octrees.
size() - 1)
816 shapeIndex[i] = begin++;
821 shapeIndex[i] = shapeIterators[shapeIndex[i]]++;
825 size_t mergedSubsets = 0;
826 if (subsetSizes[0] < 500 && subsetSizes.
size() > 1)
829 while (subsetSizes[0] < 500 && subsetSizes.
size() > 1)
831 subsetSizes[1] += subsetSizes[0];
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)
845 globalOctreeIndices[j++] = shapeIndex[globalOctreeIndices[i]];
847 globalOctreeIndices.
resize(currentSize - numInvalid);
850 #pragma parallel for schedule(static)
851 for (intptr_t i = 0; i < candidates.
size(); ++i)
852 candidates[i].Reindex(shapeIndex,
857 currentSize - numInvalid,
863 for (
size_t i = beginIdx; i < beginIdx + currentSize; ++i)
864 while (i != shapeIndex[i])
866 pc.swapPoints(i, shapeIndex[i]);
867 std::swap(shapeIndex[i], shapeIndex[shapeIndex[i]]);
877 reindex(beginIdx + subsetSizes[0]);
878 for (
size_t i = 0; i < shuffleIndices.size(); ++i)
880 shuffleIndices[i] = i;
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)
893 reindex[shuffleIndices[i]] = i;
896 #pragma omp parallel for schedule(static)
897 for (intptr_t i = 0; i < globalOctreeIndices.
size(); ++i)
898 if (globalOctreeIndices[i] < reindex.
size())
900 globalOctreeIndices[i] = reindex[globalOctreeIndices[i]];
903 #pragma omp parallel for schedule(static, 100)
904 for (intptr_t i = 0; i < candidates.
size(); ++i)
906 candidates[i].Reindex(reindex);
908 for (
size_t i = 1, begin = subsetSizes[0] + beginIdx; i < octrees.
size();
909 begin += subsetSizes[i], ++i)
911 octrees[i]->DataRange(begin, begin + subsetSizes[i]);
912 octrees[i]->Rebuild();
913 if (octrees[i]->Root()->Size() != subsetSizes[i])
915 std::cout <<
"ERROR IN REBUILD!!!!" << std::endl;
920 for (
size_t i = 0, begin = beginIdx; i < octrees.
size();
921 begin += subsetSizes[i], ++i)
923 octrees[i]->DataRange(begin, begin + subsetSizes[i]);
924 octrees[i]->Rebuild();
928 currentSize = globalOctreeIndices.
size();
930 globalOctree.IndexedRange(globalOctreeIndices.
begin(), globalOctreeIndices.
end());
931 globalOctTreeMaxNodeDepth = globalOctree.Rebuild();
932 if (globalOctree.Root()->Size() != globalOctreeIndices.
size())
934 std::cout <<
"ERROR IN GLOBAL REBUILD!" << std::endl;
936 sampleLevelProbability.
resize(globalOctTreeMaxNodeDepth + 1);
940 shapeIndex.
begin() + beginIdx, shapeIndex.
begin() + beginIdx + currentSize, -1);
947 #pragma parallel for schedule(static, 100)
948 for (
size_t i = 0; i < candidates.
size(); ++i)
949 candidates[i].RecomputeBounds(octrees,
952 currentSize - numInvalid,
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)
964 candidates[remainingCandidates++] = candidates[i];
966 candidates.
resize(remainingCandidates);
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))
978 candidates[remainingCandidates++] = candidates[i];
980 else if (candidates[i].ExpectedValue() > maxForgottenCandidate)
982 maxForgottenCandidate = candidates[i].ExpectedValue();
984 candidates.
resize(remainingCandidates);
992 }
while (CandidateFailureProbability(m_options.
m_minSupport,
993 currentSize - numInvalid,
996 (currentSize - numInvalid) >= m_options.
m_minSupport && !timeout());
1004 size_t begin = beginIdx, end = beginIdx + currentSize;
1007 int shapeIt =
shapes->size() - numShapes;
1008 for (
size_t i = 0; i < numShapes; ++i, ++shapeIt)
1010 shapeIterators[i] = end -= ((*shapes)[shapeIt]).second;
1013 for (
size_t i = beginIdx; i < beginIdx + currentSize; ++i)
1014 if (shapeIndex[i] < 0)
1016 shapeIndex[i] = begin++;
1020 shapeIndex[i] = shapeIterators[shapeIndex[i]]++;
1024 for (
size_t i = beginIdx; i < beginIdx + currentSize; ++i)
1025 while (i != shapeIndex[i])
1027 pc.swapPoints(i, shapeIndex[i]);
1028 std::swap(shapeIndex[i], shapeIndex[shapeIndex[i]]);
1032 for (
size_t i = 0; i < octrees.
size(); ++i)
1037 size_t eidx = endIdx;
1038 for (
size_t i = 0; i <
shapes->size(); ++i)
1040 size_t bidx = eidx - (*shapes)[i].second;
1041 (*shapes)[i].first->OptimizeParametrization(
pc, bidx, eidx, m_options.
m_bitmapEpsilon);
1046 for (
size_t i =
shapes->size(); i != 0; --i)
1048 if (
shapes->at(i - 1).second == 0)
1053 return currentSize - numInvalid;
1064 for (
size_t tries = 0; tries < m_maxCandTries; tries++)
1071 first = oct.Dereference(
rn_rand() % oct.size());
1072 }
while (shapeIndex[first] != -1);
1075 std::pair<size_t, size_t> nodeRange;
1078 if ((*node)->Size() < numSamples)
1083 while (samples->
size() < numSamples)
1088 i = oct.Dereference(
rn_rand() % (*node)->Size() + nodeRange.first);
1089 }
while ((shapeIndex[i] != -1 ||
1099 if (samples->
size() == numSamples)
1108 RansacShapeDetector::Fit(
bool allowDifferentShapes,
1113 std::pair<size_t, float>* score)
const
1115 if (!m_constructors.
size())
1121 bestShape = initialShape.
LSFit(