bool AutoSegmentationTools::frontPropagationBasedSegmentation(GenericIndexedCloudPersist* theCloud, ScalarType minSeedDist, uchar octreeLevel, ReferenceCloudContainer& theSegmentedLists, GenericProgressCallback* progressCb, DgmOctree* inputOctree, bool applyGaussianFilter, float alpha) { unsigned numberOfPoints = (theCloud ? theCloud->size() : 0); if (numberOfPoints == 0) return false; //compute octree if none was provided DgmOctree* theOctree = inputOctree; if (!theOctree) { theOctree = new DgmOctree(theCloud); if (theOctree->build(progressCb)<1) { delete theOctree; return false; } } //on calcule le gradient (va ecraser le champ des distances) if (ScalarFieldTools::computeScalarFieldGradient(theCloud,true,true,progressCb,theOctree) < 0) { if (!inputOctree) delete theOctree; return false; } //et on lisse le resultat if (applyGaussianFilter) { uchar level = theOctree->findBestLevelForAGivenPopulationPerCell(NUMBER_OF_POINTS_FOR_GRADIENT_COMPUTATION); PointCoordinateType cellSize = theOctree->getCellSize(level); ScalarFieldTools::applyScalarFieldGaussianFilter(static_cast<float>(cellSize/3),theCloud,-1,progressCb,theOctree); } unsigned seedPoints = 0; unsigned numberOfSegmentedLists = 0; //on va faire la propagation avec le FastMarching(); FastMarchingForPropagation* fm = new FastMarchingForPropagation(); fm->setJumpCoef(50.0); fm->setDetectionThreshold(alpha); int result = fm->init(theCloud,theOctree,octreeLevel); int octreeLength = OCTREE_LENGTH(octreeLevel)-1; if (result<0) { if (!inputOctree) delete theOctree; delete fm; return false; } if (progressCb) { progressCb->reset(); progressCb->setMethodTitle("FM Propagation"); char buffer[256]; sprintf(buffer,"Octree level: %i\nNumber of points: %u",octreeLevel,numberOfPoints); progressCb->setInfo(buffer); progressCb->start(); } ScalarField* theDists = new ScalarField("distances"); { ScalarType d = theCloud->getPointScalarValue(0); if (!theDists->resize(numberOfPoints,true,d)) { if (!inputOctree) delete theOctree; return false; } } unsigned maxDistIndex = 0, begin = 0; CCVector3 startPoint; while (true) { ScalarType maxDist = NAN_VALUE; //on cherche la premiere distance superieure ou egale a "minSeedDist" while (begin<numberOfPoints) { const CCVector3 *thePoint = theCloud->getPoint(begin); const ScalarType& theDistance = theDists->getValue(begin); ++begin; //FIXME DGM: what happens if SF is negative?! if (theCloud->getPointScalarValue(begin) >= 0 && theDistance >= minSeedDist) { maxDist = theDistance; startPoint = *thePoint; maxDistIndex = begin; break; } } //il n'y a plus de point avec des distances suffisamment grandes ! if (maxDist<minSeedDist) break; //on finit la recherche du max for (unsigned i=begin; i<numberOfPoints; ++i) { const CCVector3 *thePoint = theCloud->getPoint(i); const ScalarType& theDistance = theDists->getValue(i); if ((theCloud->getPointScalarValue(i)>=0.0)&&(theDistance > maxDist)) { maxDist = theDistance; startPoint = *thePoint; maxDistIndex = i; } } int pos[3]; theOctree->getTheCellPosWhichIncludesThePoint(&startPoint,pos,octreeLevel); //clipping (important!) pos[0] = std::min(octreeLength,pos[0]); pos[1] = std::min(octreeLength,pos[1]); pos[2] = std::min(octreeLength,pos[2]); fm->setSeedCell(pos); ++seedPoints; int result = fm->propagate(); //if the propagation was successful if (result >= 0) { //we extract the corresponding points ReferenceCloud* newCloud = new ReferenceCloud(theCloud); if (fm->extractPropagatedPoints(newCloud) && newCloud->size() != 0) { theSegmentedLists.push_back(newCloud); ++numberOfSegmentedLists; } else { //not enough memory?! delete newCloud; newCloud = 0; } if (progressCb) progressCb->update(float(numberOfSegmentedLists % 100)); fm->cleanLastPropagation(); //break; } if (maxDistIndex == begin) ++begin; } if (progressCb) progressCb->stop(); for (unsigned i=0; i<numberOfPoints; ++i) theCloud->setPointScalarValue(i,theDists->getValue(i)); delete fm; fm = 0; theDists->release(); theDists = 0; if (!inputOctree) delete theOctree; return true; }
bool AutoSegmentationTools::frontPropagationBasedSegmentation(GenericIndexedCloudPersist* theCloud, bool signedSF, DistanceType minSeedDist, uchar octreeLevel, ReferenceCloudContainer& theSegmentedLists, GenericProgressCallback* progressCb, DgmOctree* _theOctree, bool applyGaussianFilter, float alpha) { if (!theCloud) return false; unsigned numberOfPoints = theCloud->size(); if (numberOfPoints<1) return false; //on calcule l'octree DgmOctree* theOctree = _theOctree; if (!theOctree) { theOctree = new DgmOctree(theCloud); if (theOctree->build(progressCb)<1) { delete theOctree; return false; } } ScalarField* theDists = new ScalarField("distances",true); if (!theDists->reserve(numberOfPoints)) { if (!_theOctree) delete theOctree; return false; } theCloud->placeIteratorAtBegining(); unsigned k=0; DistanceType d = theCloud->getPointScalarValue(k); for (;k<numberOfPoints;++k) theDists->addElement(d); //on calcule le gradient (va écraser le champ des distances) if (ScalarFieldTools::computeScalarFieldGradient(theCloud,signedSF,true,true,progressCb,theOctree)<0) { if (!_theOctree) delete theOctree; return false; } //et on lisse le résultat if (applyGaussianFilter) { uchar level = theOctree->findBestLevelForAGivenPopulationPerCell(NUMBER_OF_POINTS_FOR_GRADIENT_COMPUTATION); float cellSize = theOctree->getCellSize(level); ScalarFieldTools::applyScalarFieldGaussianFilter(cellSize*0.33f,theCloud,signedSF,-1,progressCb,theOctree); } DistanceType maxDist; unsigned seedPoints = 0; unsigned numberOfSegmentedLists = 0; //on va faire la propagation avec le FastMarching(); FastMarchingForPropagation* fm = new FastMarchingForPropagation(); fm->setJumpCoef(50.0); fm->setDetectionThreshold(alpha); int result = fm->init(theCloud,theOctree,octreeLevel); int octreeLength = OCTREE_LENGTH(octreeLevel)-1; if (result<0) { if (!_theOctree) delete theOctree; delete fm; return false; } if (progressCb) { progressCb->reset(); progressCb->setMethodTitle("FM Propagation"); char buffer[256]; sprintf(buffer,"Octree level: %i\nNumber of points: %i",octreeLevel,numberOfPoints); progressCb->setInfo(buffer); progressCb->start(); } unsigned maxDistIndex=0,begin = 0; CCVector3 startPoint; while (true) { maxDist = HIDDEN_VALUE; //on cherche la première distance supérieure ou égale à "minSeedDist" while (begin<numberOfPoints) { const CCVector3 *thePoint = theCloud->getPoint(begin); const DistanceType& theDistance = theDists->getValue(begin); ++begin; if ((theCloud->getPointScalarValue(begin)>=0.0)&&(theDistance >= minSeedDist)) { maxDist = theDistance; startPoint = *thePoint; maxDistIndex = begin; break; } } //il n'y a plus de point avec des distances suffisamment grandes ! if (maxDist<minSeedDist) break; //on finit la recherche du max for (unsigned i=begin;i<numberOfPoints;++i) { const CCVector3 *thePoint = theCloud->getPoint(i); const DistanceType& theDistance = theDists->getValue(i); if ((theCloud->getPointScalarValue(i)>=0.0)&&(theDistance > maxDist)) { maxDist = theDistance; startPoint = *thePoint; maxDistIndex = i; } } //on lance la propagation à partir du point de distance maximale //propagateFromPoint(aList,_GradientNorms,maxDistIndex,octreeLevel,_gui); int pos[3]; theOctree->getTheCellPosWhichIncludesThePoint(&startPoint,pos,octreeLevel); //clipping (important !) pos[0] = std::min(octreeLength,pos[0]); pos[1] = std::min(octreeLength,pos[1]); pos[2] = std::min(octreeLength,pos[2]); fm->setSeedCell(pos); ++seedPoints; int result = fm->propagate(); //si la propagation s'est bien passée if (result>=0) { //on la termine (i.e. on extrait les points correspondant) ReferenceCloud* newCloud = fm->extractPropagatedPoints(); //si la liste convient //on la rajoute au groupe des listes segmentées theSegmentedLists.push_back(newCloud); ++numberOfSegmentedLists; if (progressCb) progressCb->update(float(numberOfSegmentedLists % 100)); fm->endPropagation(); //break; } if (maxDistIndex == begin) ++begin; } if (progressCb) progressCb->stop(); for (unsigned i=0;i<numberOfPoints;++i) theCloud->setPointScalarValue(i,theDists->getValue(i)); delete fm; theDists->release(); theDists=0; if (!_theOctree) delete theOctree; return true; }