DGtal  1.3.beta
geometry/surfaces/greedy-plane-segmentation-ex2.cpp

This example shows a not-so-greedy segmentation into naive planes of the surface at threshold 0 within volume Al.100.vol.

It enhances the polyhedrization of greedy-plane-segmentation.cpp by selecting first the vertices that induces the biggest planes. This is much slower than the other, but it gives nicer results. For each vertex, it computes its best plane by breadth-first traversal. It stores the obtained size for each vertex independently. It puts them in a priority queue, the first to be popped are the ones with the biggest size. The remaining of the algorithm is unchanged.

Colors for each plane are chosen randomly. Surfels in the same plane have the same color.

See also
Application to greedy segmentation into digital planes (solution of exercice 2)
# naive plane: width=1/1
$ ./examples/geometry/surfaces/greedy-plane-segmentation-ex2 -i ./examples/samples/Al.100.vol -t 0 -w 1 -d 1
Not-so-greedy segmentation of Al capone into naive planes.
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include "DGtal/base/Common.h"
#include "DGtal/io/readers/VolReader.h"
#include "DGtal/io/Display3D.h"
#include "DGtal/io/viewers/Viewer3D.h"
#include "DGtal/io/DrawWithDisplay3DModifier.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"
using namespace std;
using namespace DGtal;
using namespace Z3i;
// We choose the DigitalSetBoundary surface container in order to
// segment connected or unconnected surfaces.
typedef SurfelSet::iterator SurfelSetIterator;
struct SegmentedPlane {
Color color;
};
struct VertexSize {
Vertex v;
std::size_t size;
inline VertexSize( const Vertex & aV, std::size_t aSize )
: v( aV ), size( aSize )
{}
};
inline
bool operator<( const VertexSize & vs1, const VertexSize & vs2 )
{
return vs1.size < vs2.size;
}
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;
// Setting default options: ----------------------------------------------
// input file used:
string inputFilename = examplesPath + "samples/Al.100.vol" ;
trace.info() << "input file used " << inputFilename << std::endl;
// parameter threshold
unsigned int threshold = 0;
trace.info() << "the value that defines the isosurface in the image (an integer between 0 and 255)= " << threshold<< std::endl;
// parameter widthNum
unsigned int widthNum = 1;
trace.info() << "the numerator of the rational width (a non-null integer) =" << widthNum<< std::endl;
// parameter widthDen
unsigned int widthDen = 1;
trace.info() << "the denominator of the rational width (a non-null integer)= " << widthDen<< std::endl;
QApplication application(argc,argv);
Image image = VolReader<Image>::importVol(inputFilename);
DigitalSet set3d (image.domain());
SetFromImage<DigitalSet>::append<Image>(set3d, image, threshold,255);
trace.beginBlock( "Set up digital surface." );
// We initializes the cellular grid space used for defining the
// digital surface.
KSpace ks;
bool ok = ks.init( set3d.domain().lowerBound(),
set3d.domain().upperBound(), true );
if ( ! ok ) std::cerr << "[KSpace.init] Failed." << std::endl;
SurfelAdjacency<KSpace::dimension> surfAdj( true ); // interior in all directions.
MyDigitalSurfaceContainer* ptrSurfContainer =
new MyDigitalSurfaceContainer( ks, set3d, surfAdj );
MyDigitalSurface digSurf( ptrSurfContainer ); // acquired
Point p;
Dimension axis;
unsigned int j = 0;
unsigned int nb = digSurf.size();
// First pass to find biggest planes.
trace.beginBlock( "1) Segmentation first pass. Computes all planes so as to sort vertices by the plane size." );
std::map<Vertex,unsigned int> v2size;
NaivePlaneComputer planeComputer;
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 );
Vertex v = *it;
axis = ks.sOrthDir( v );
planeComputer.init( axis, 500, widthNum, widthDen );
// The visitor takes care of all the breadth-first traversal.
Visitor visitor( digSurf, v );
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 )
// surfel is in plane.
visitor.expand();
else // surfel is not in plane and should not be used in the visit.
visitor.ignore();
}
Q.push( VertexSize( v, planeComputer.size() ) );
}
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 );
Vertex v = Q.top().v;
Q.pop();
if ( processedVertices.find( v ) != processedVertices.end() ) // already in set
continue; // process to next vertex
SegmentedPlane* ptrSegment = new SegmentedPlane;
segmentedPlanes.push_back( ptrSegment ); // to delete them afterwards.
axis = ks.sOrthDir( v );
ptrSegment->plane.init( axis, 500, widthNum, widthDen );
// The visitor takes care of all the breadth-first traversal.
Visitor visitor( digSurf, v );
while ( ! visitor.finished() )
{
Visitor::Node node = visitor.current();
v = node.first;
if ( processedVertices.find( v ) == processedVertices.end() )
{ // Vertex is not in processedVertices
axis = ks.sOrthDir( v );
p = ks.sCoords( ks.sDirectIncident( v, axis ) );
bool isExtended = ptrSegment->plane.extend( p );
if ( isExtended )
{ // surfel is in plane.
processedVertices.insert( v );
v2plane[ v ] = ptrSegment;
visitor.expand();
}
else // surfel is not in plane and should not be used in the visit.
visitor.ignore();
}
else // surfel is already in some plane.
visitor.ignore();
}
// Assign random color for each plane.
ptrSegment->color = Color( rand() % 256, rand() % 256, rand() % 256, 255 );
}
Viewer3D<> viewer( ks );
viewer.show();
for ( std::map<Vertex,SegmentedPlane*>::const_iterator
it = v2plane.begin(), itE = v2plane.end();
it != itE; ++it )
{
viewer << CustomColors3D( it->second->color, it->second->color );
viewer << ks.unsigns( it->first );
}
viewer << Viewer3D<>::updateDisplay;
for ( std::vector<SegmentedPlane*>::iterator
it = segmentedPlanes.begin(), itE = segmentedPlanes.end();
it != itE; ++it )
delete *it;
segmentedPlanes.clear();
v2plane.clear();
return application.exec();
}
operator<
bool operator<(const VertexSize &vs1, const VertexSize &vs2)
Definition: greedy-plane-segmentation-ex2.cpp:115
ConstIterator
MyDigitalSurface::ConstIterator ConstIterator
Definition: greedy-plane-segmentation-ex2.cpp:93
DGtal::DigitalSurface::SurfelSet
KSpace::SurfelSet SurfelSet
Definition: DigitalSurface.h:167
DGtal::DigitalSurface::ConstIterator
DigitalSurfaceContainer::SurfelConstIterator ConstIterator
Definition: DigitalSurface.h:163
DGtal::SetFromImage
Aim: Define utilities to convert a digital set into an image.
Definition: SetFromImage.h:63
NaivePlaneComputer
COBANaivePlaneComputer< Z3, InternalInteger > NaivePlaneComputer
Definition: greedy-plane-segmentation-ex2.cpp:88
DGtal::COBANaivePlaneComputer::init
void init(Dimension axis, InternalInteger diameter, InternalInteger widthNumerator=NumberTraits< InternalInteger >::ONE, InternalInteger widthDenominator=NumberTraits< InternalInteger >::ONE)
DGtal::Trace::endBlock
double endBlock()
DGtal::COBANaivePlaneComputer::extend
bool extend(const Point &p)
DGtal::ImageContainerBySTLVector
Definition: ImageContainerBySTLVector.h:126
DGtal::DigitalSurface
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
Definition: DigitalSurface.h:139
DGtal::SurfelAdjacency< KSpace::dimension >
DGtal::Color
Structure representing an RGB triple with alpha component.
Definition: Color.h:66
DGtal::KhalimskySpaceND::init
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
DGtal::COBANaivePlaneComputer::size
Size size() const
DGtal::trace
Trace trace
Definition: Common.h:154
DGtal::DigitalSetBoundary
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of a given...
Definition: DigitalSetBoundary.h:69
DGtal::BreadthFirstVisitor
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
Definition: BreadthFirstVisitor.h:94
DGtal::Dimension
DGtal::uint32_t Dimension
Definition: Common.h:137
DGtal::BreadthFirstVisitor::Node
std::pair< Vertex, Data > Node
FIXME.
Definition: BreadthFirstVisitor.h:115
DGtal::Trace::beginBlock
void beginBlock(const std::string &keyword="")
Visitor
BreadthFirstVisitor< MyDigitalSurface > Visitor
Definition: greedy-plane-segmentation-ex2.cpp:97
DGtal::KhalimskySpaceND::sCoords
Point sCoords(const SCell &c) const
Return its digital coordinates.
Vertex
TriMesh::Vertex Vertex
Definition: testTriangulatedSurface.cpp:57
SurfelSetIterator
SurfelSet::iterator SurfelSetIterator
Definition: greedy-plane-segmentation-ex2.cpp:96
DGtal::Trace::info
std::ostream & info()
DGtal::Trace::progressBar
void progressBar(const double currentValue, const double maximalValue)
DGtal::KhalimskySpaceND::sDirectIncident
SCell sDirectIncident(const SCell &p, Dimension k) const
Return the direct incident cell of [p] along [k] (the incident cell along [k])
DGtal::Z2i::DigitalSet
DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet
Definition: StdDefs.h:100
DGtal::Viewer3D
Definition: Viewer3D.h:135
Image
ImageContainerBySTLVector< Domain, Value > Image
Definition: testSimpleRandomAccessRangeFromPoint.cpp:45
DGtal
DGtal is the top-level namespace which contains all DGtal functions and types.
DGtal::CustomColors3D
Definition: DrawWithDisplay3DModifier.h:129
main
int main(int argc, char **argv)
Definition: testArithmeticDSS-benchmark.cpp:147
DGtal::KhalimskySpaceND::sOrthDir
Dimension sOrthDir(const SCell &s) const
Given a signed surfel [s], returns its orthogonal direction (ie, the coordinate where the surfel is c...
DGtal::Image
Aim: implements association bewteen points lying in a digital domain and values.
Definition: Image.h:69
DGtal::DigitalSurface::Vertex
Surfel Vertex
Defines the type for a vertex.
Definition: DigitalSurface.h:177
MyDigitalSurfaceContainer
DigitalSetBoundary< KSpace, DigitalSet > MyDigitalSurfaceContainer
Definition: greedy-plane-segmentation-ex2.cpp:91
DGtal::VolReader
Aim: implements methods to read a "Vol" file format.
Definition: VolReader.h:89
DGtal::int64_t
boost::int64_t int64_t
signed 94-bit integer.
Definition: BasicTypes.h:74
DGtal::KhalimskySpaceND::unsigns
Cell unsigns(const SCell &p) const
Creates an unsigned cell from a signed one.
DGtal::COBANaivePlaneComputer< Z3, InternalInteger >
Point
MyPointD Point
Definition: testClone2.cpp:383
InternalInteger
DGtal::int64_t InternalInteger
Definition: greedy-plane-segmentation-ex2.cpp:87
MyDigitalSurface
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
Definition: greedy-plane-segmentation-ex2.cpp:92
SurfelSet
MyDigitalSurface::SurfelSet SurfelSet
Definition: greedy-plane-segmentation-ex2.cpp:95
DGtal::KhalimskySpaceND
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
Definition: KhalimskySpaceND.h:64