Ejemplo n.º 1
0
//extrait les composantes connexes d'un nuage
//--> version avec des ReferenceCloud (uniquement des références vers les points)
//pour permettre une récupération au niveau de l'application cliente
//des couleurs, normales, etc.
bool AutoSegmentationTools::extractConnectedComponents(GenericIndexedCloudPersist* theCloud, ReferenceCloudContainer& cc)
{
	if (!theCloud)
		return false;
	unsigned numberOfPoints = theCloud->size();
	if (numberOfPoints<1)
		return false;

	//on admet que "labelConnectedComponents" a bien déjà été appelé
	//les labels des CCs sont alors stockées dans le champ scalaire "courant"
	cc.clear();

	//theCloud->placeIteratorAtBegining();
	for (unsigned i=0;i<numberOfPoints;++i)
	{
		int ccLabel=(int)theCloud->getPointScalarValue(i)-1; //les labels commencent à 1 !

		//on remplit le vecteur de "CCs" vides jusqu'à arriver au bon numéro de CC
		//on s'occupera en théorie des autres plus tard
		while (ccLabel>=(int)cc.size())
			cc.push_back(new ReferenceCloud(theCloud));

		//on rajoute le point à la CC courante
		cc[ccLabel]->addPointIndex(i);
	}

	return true;
}
Ejemplo n.º 2
0
bool AutoSegmentationTools::extractConnectedComponents(GenericIndexedCloudPersist* theCloud, ReferenceCloudContainer& cc)
{
	unsigned numberOfPoints = (theCloud ? theCloud->size() : 0);
	if (numberOfPoints == 0)
	{
		return false;
	}

	//components should have already been labeled and labels should have been stored in the active scalar field!
	if (!theCloud->isScalarFieldEnabled())
	{
		return false;
	}

	//empty the input vector if necessary
	while (!cc.empty())
	{
		delete cc.back();
		cc.pop_back();
	}

	for (unsigned i = 0; i < numberOfPoints; ++i)
	{
		ScalarType slabel = theCloud->getPointScalarValue(i);
		if (slabel >= 1) //labels start from 1! (this test rejects NaN values as well)
		{
			int ccLabel = static_cast<int>(theCloud->getPointScalarValue(i)) - 1;

			//we fill the components vector with empty components until we reach the current label
			//(they will be "used" later)
			try
			{
				while (static_cast<size_t>(ccLabel) >= cc.size())
				{
					cc.push_back(new ReferenceCloud(theCloud));
				}
			}
			catch (const std::bad_alloc&)
			{
				//not enough memory
				cc.clear();
				return false;
			}

			//add the point to the current component
			if (!cc[ccLabel]->addPointIndex(i))
			{
				//not enough memory
				while (!cc.empty())
				{
					delete cc.back();
					cc.pop_back();
				}
				return false;
			}
		}
	}

	return true;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}