This example shows a not-so-greedy segmentation into naive planes of the surface at threshold 0 within volume Al.100.vol.
Colors for each plane are chosen randomly. Surfels in the same plane have the same color.
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include "DGtal/base/Common.h"
#include "DGtal/io/readers/VolReader.h"
#include "DGtal/io/viewers/PolyscopeViewer.h"
#include "DGtal/images/ImageSelector.h"
#include "DGtal/images/imagesSetsUtils/SetFromImage.h"
#include "DGtal/topology/DigitalSurface.h"
#include "DGtal/topology/DigitalSetBoundary.h"
#include "DGtal/graph/BreadthFirstVisitor.h"
#include "DGtal/geometry/surfaces/COBANaivePlaneComputer.h"
#include "DGtal/helpers/StdDefs.h"
#include "ConfigExamples.h"
typedef MyDigitalSurface::Vertex
Vertex;
typedef MyDigitalSurface::SurfelSet
SurfelSet;
};
{}
};
inline
{
}
int main(
int argc,
char** argv )
{
trace.info() <<
"Segments the surface at given threshold within given volume into digital planes of rational width num/den." << std::endl;
string inputFilename = examplesPath + "samples/Al.100.vol" ;
trace.info() <<
"input file used " << inputFilename << std::endl;
unsigned int threshold = 0;
trace.info() <<
"the value that defines the isosurface in the image (an integer between 0 and 255)= " << threshold<< std::endl;
unsigned int widthNum = 1;
trace.info() <<
"the numerator of the rational width (a non-null integer) =" << widthNum<< std::endl;
unsigned int widthDen = 1;
trace.info() <<
"the denominator of the rational width (a non-null integer)= " << widthDen<< std::endl;
typedef ImageSelector < Domain, int>::Type
Image;
trace.beginBlock(
"Set up digital surface." );
bool ok = ks.init( set3d.domain().lowerBound(),
set3d.domain().upperBound(), true );
if ( ! ok ) std::cerr << "[KSpace.init] Failed." << std::endl;
unsigned int j = 0;
unsigned int nb = digSurf.size();
trace.beginBlock(
"1) Segmentation first pass. Computes all planes so as to sort vertices by the plane size." );
std::map<Vertex,unsigned int> v2size;
std::priority_queue<VertexSize> Q;
for (
ConstIterator it = digSurf.begin(), itE= digSurf.end(); it != itE; ++it )
{
if ( ( (++j) % 50 == 0 ) || ( j == nb ) )
trace.progressBar( j, nb );
axis = ks.sOrthDir( v );
planeComputer.init( axis, 500, widthNum, widthDen );
while ( ! visitor.finished() )
{
Visitor::Node node = visitor.current();
v = node.first;
axis = ks.sOrthDir( v );
p = ks.sCoords( ks.sDirectIncident( v, axis ) );
bool isExtended = planeComputer.extend( p );
if ( isExtended )
visitor.expand();
else
visitor.ignore();
}
}
trace.beginBlock(
"2) Segmentation second pass. Visits vertices from the one with biggest plane to the one with smallest plane." );
std::set<Vertex> processedVertices;
std::vector<SegmentedPlane*> segmentedPlanes;
std::map<Vertex,SegmentedPlane*> v2plane;
j = 0;
while ( ! Q.empty() )
{
if ( ( (++j) % 50 == 0 ) || ( j == nb ) )
trace.progressBar( j, nb );
Q.pop();
if ( processedVertices.find( v ) != processedVertices.end() )
continue;
segmentedPlanes.push_back( ptrSegment );
axis = ks.sOrthDir( v );
ptrSegment->
plane.init( axis, 500, widthNum, widthDen );
while ( ! visitor.finished() )
{
Visitor::Node node = visitor.current();
v = node.first;
if ( processedVertices.find( v ) == processedVertices.end() )
{
axis = ks.sOrthDir( v );
p = ks.sCoords( ks.sDirectIncident( v, axis ) );
bool isExtended = ptrSegment->
plane.extend( p );
if ( isExtended )
{
processedVertices.insert( v );
v2plane[ v ] = ptrSegment;
visitor.expand();
}
else
visitor.ignore();
}
else
visitor.ignore();
}
ptrSegment->
color =
Color( rand() % 256, rand() % 256, rand() % 256, 255 );
}
PolyscopeViewer<> viewer( ks );
for ( std::map<Vertex,SegmentedPlane*>::const_iterator
it = v2plane.begin(), itE = v2plane.end();
it != itE; ++it )
{
viewer << it->second->color;
viewer << ks.unsigns( it->first );
}
for ( std::vector<SegmentedPlane*>::iterator
it = segmentedPlanes.begin(), itE = segmentedPlanes.end();
it != itE; ++it )
delete *it;
segmentedPlanes.clear();
v2plane.clear();
viewer.show();
return 0;
}
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
Aim: A class that contains the COBA algorithm (Emilie Charrier, Lilian Buzer, DGCI2008) for recognizi...
Structure representing an RGB triple with alpha component.
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of a given...
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
bool operator<(const VertexSize &vs1, const VertexSize &vs2)
SurfelSet::iterator SurfelSetIterator
COBANaivePlaneComputer< Z3, InternalInteger > NaivePlaneComputer
MyDigitalSurface::ConstIterator ConstIterator
MyDigitalSurface::SurfelSet SurfelSet
BreadthFirstVisitor< MyDigitalSurface > Visitor
DigitalSetBoundary< KSpace, DigitalSet > MyDigitalSurfaceContainer
DGtal::int64_t InternalInteger
Z3i this namespace gathers the standard of types for 3D imagery.
DGtal is the top-level namespace which contains all DGtal functions and types.
std::int64_t int64_t
signed 94-bit integer.
DGtal::uint32_t Dimension
static void append(Set &aSet, const ForegroundPredicate &isForeground, typename Image::Domain::ConstIterator itBegin, typename Image::Domain::ConstIterator itEnd)
static ImageContainer importVol(const std::string &filename, const Functor &aFunctor=Functor())
VertexSize(const Vertex &aV, std::size_t aSize)
ImageContainerBySTLVector< Domain, Value > Image
Z2i::DigitalSet DigitalSet