DGtal  1.5.beta
greedy-plane-segmentation-ex2.cpp
Go to the documentation of this file.
1 
60 #include <iostream>
61 #include <vector>
62 #include <set>
63 #include <map>
64 #include <queue>
65 #include "DGtal/base/Common.h"
66 #include "DGtal/io/readers/VolReader.h"
67 
68 #include "DGtal/io/Display3D.h"
69 #include "DGtal/io/viewers/Viewer3D.h"
70 #include "DGtal/io/DrawWithDisplay3DModifier.h"
71 #include "DGtal/images/ImageSelector.h"
72 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
73 #include "DGtal/topology/DigitalSurface.h"
74 #include "DGtal/topology/DigitalSetBoundary.h"
75 #include "DGtal/graph/BreadthFirstVisitor.h"
76 #include "DGtal/geometry/surfaces/COBANaivePlaneComputer.h"
77 #include "DGtal/helpers/StdDefs.h"
78 #include "ConfigExamples.h"
79 
81 
82 using namespace std;
83 using namespace DGtal;
84 
86 using namespace Z3i;
89 // We choose the DigitalSetBoundary surface container in order to
90 // segment connected or unconnected surfaces.
96 typedef SurfelSet::iterator SurfelSetIterator;
102 struct SegmentedPlane {
103  NaivePlaneComputer plane;
104  Color color;
105 };
106 struct VertexSize {
107  Vertex v;
108  std::size_t size;
109  inline VertexSize( const Vertex & aV, std::size_t aSize )
110  : v( aV ), size( aSize )
111  {}
112 };
113 
114 inline
115 bool operator<( const VertexSize & vs1, const VertexSize & vs2 )
116 {
117  return vs1.size < vs2.size;
118 }
120 
122 
123 int main( int argc, char** argv )
124 {
126  trace.info() << "Segments the surface at given threshold within given volume into digital planes of rational width num/den." << std::endl;
127  // Setting default options: ----------------------------------------------
128  // input file used:
129  string inputFilename = examplesPath + "samples/Al.100.vol" ;
130  trace.info() << "input file used " << inputFilename << std::endl;
131  // parameter threshold
132  unsigned int threshold = 0;
133  trace.info() << "the value that defines the isosurface in the image (an integer between 0 and 255)= " << threshold<< std::endl;
134  // parameter widthNum
135  unsigned int widthNum = 1;
136  trace.info() << "the numerator of the rational width (a non-null integer) =" << widthNum<< std::endl;
137  // parameter widthDen
138  unsigned int widthDen = 1;
139  trace.info() << "the denominator of the rational width (a non-null integer)= " << widthDen<< std::endl;
141 
143  QApplication application(argc,argv);
145  Image image = VolReader<Image>::importVol(inputFilename);
146  DigitalSet set3d (image.domain());
147  SetFromImage<DigitalSet>::append<Image>(set3d, image, threshold,255);
149 
151  trace.beginBlock( "Set up digital surface." );
152  // We initializes the cellular grid space used for defining the
153  // digital surface.
154  KSpace ks;
155  bool ok = ks.init( set3d.domain().lowerBound(),
156  set3d.domain().upperBound(), true );
157  if ( ! ok ) std::cerr << "[KSpace.init] Failed." << std::endl;
158  SurfelAdjacency<KSpace::dimension> surfAdj( true ); // interior in all directions.
159  MyDigitalSurfaceContainer* ptrSurfContainer =
160  new MyDigitalSurfaceContainer( ks, set3d, surfAdj );
161  MyDigitalSurface digSurf( ptrSurfContainer ); // acquired
162  trace.endBlock();
164 
166  Point p;
167  Dimension axis;
168  unsigned int j = 0;
169  unsigned int nb = digSurf.size();
170 
171  // First pass to find biggest planes.
172  trace.beginBlock( "1) Segmentation first pass. Computes all planes so as to sort vertices by the plane size." );
173  std::map<Vertex,unsigned int> v2size;
174  NaivePlaneComputer planeComputer;
175  std::priority_queue<VertexSize> Q;
176  for ( ConstIterator it = digSurf.begin(), itE= digSurf.end(); it != itE; ++it )
177  {
178  if ( ( (++j) % 50 == 0 ) || ( j == nb ) ) trace.progressBar( j, nb );
179  Vertex v = *it;
180  axis = ks.sOrthDir( v );
181  planeComputer.init( axis, 500, widthNum, widthDen );
182  // The visitor takes care of all the breadth-first traversal.
183  Visitor visitor( digSurf, v );
184  while ( ! visitor.finished() )
185  {
186  Visitor::Node node = visitor.current();
187  v = node.first;
188  axis = ks.sOrthDir( v );
189  p = ks.sCoords( ks.sDirectIncident( v, axis ) );
190  bool isExtended = planeComputer.extend( p );
191  if ( isExtended )
192  // surfel is in plane.
193  visitor.expand();
194  else // surfel is not in plane and should not be used in the visit.
195  visitor.ignore();
196  }
197  Q.push( VertexSize( v, planeComputer.size() ) );
198  }
199  trace.endBlock();
200 
201  trace.beginBlock( "2) Segmentation second pass. Visits vertices from the one with biggest plane to the one with smallest plane." );
202  std::set<Vertex> processedVertices;
203  std::vector<SegmentedPlane*> segmentedPlanes;
204  std::map<Vertex,SegmentedPlane*> v2plane;
205  j = 0;
206  while ( ! Q.empty() )
207  {
208  if ( ( (++j) % 50 == 0 ) || ( j == nb ) ) trace.progressBar( j, nb );
209  Vertex v = Q.top().v;
210  Q.pop();
211  if ( processedVertices.find( v ) != processedVertices.end() ) // already in set
212  continue; // process to next vertex
213 
214  SegmentedPlane* ptrSegment = new SegmentedPlane;
215  segmentedPlanes.push_back( ptrSegment ); // to delete them afterwards.
216  axis = ks.sOrthDir( v );
217  ptrSegment->plane.init( axis, 500, widthNum, widthDen );
218  // The visitor takes care of all the breadth-first traversal.
219  Visitor visitor( digSurf, v );
220  while ( ! visitor.finished() )
221  {
222  Visitor::Node node = visitor.current();
223  v = node.first;
224  if ( processedVertices.find( v ) == processedVertices.end() )
225  { // Vertex is not in processedVertices
226  axis = ks.sOrthDir( v );
227  p = ks.sCoords( ks.sDirectIncident( v, axis ) );
228  bool isExtended = ptrSegment->plane.extend( p );
229  if ( isExtended )
230  { // surfel is in plane.
231  processedVertices.insert( v );
232  v2plane[ v ] = ptrSegment;
233  visitor.expand();
234  }
235  else // surfel is not in plane and should not be used in the visit.
236  visitor.ignore();
237  }
238  else // surfel is already in some plane.
239  visitor.ignore();
240  }
241  // Assign random color for each plane.
242  ptrSegment->color = Color( rand() % 256, rand() % 256, rand() % 256, 255 );
243  }
244  trace.endBlock();
246 
248  Viewer3D<> viewer( ks );
249  viewer.show();
250  for ( std::map<Vertex,SegmentedPlane*>::const_iterator
251  it = v2plane.begin(), itE = v2plane.end();
252  it != itE; ++it )
253  {
254  viewer << CustomColors3D( it->second->color, it->second->color );
255  viewer << ks.unsigns( it->first );
256  }
257  viewer << Viewer3D<>::updateDisplay;
259 
261  for ( std::vector<SegmentedPlane*>::iterator
262  it = segmentedPlanes.begin(), itE = segmentedPlanes.end();
263  it != itE; ++it )
264  delete *it;
265  segmentedPlanes.clear();
266  v2plane.clear();
268 
269  return application.exec();
270 }
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
const Node & current() const
std::pair< Vertex, Data > Node
FIXME.
void init(Dimension axis, InternalInteger diameter, InternalInteger widthNumerator=NumberTraits< InternalInteger >::ONE, InternalInteger widthDenominator=NumberTraits< InternalInteger >::ONE)
bool extend(const Point &p)
Structure representing an RGB triple with alpha component.
Definition: Color.h:68
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of a given...
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
DigitalSurfaceContainer::SurfelConstIterator ConstIterator
Surfel Vertex
Defines the type for a vertex.
ConstIterator begin() const
ConstIterator end() const
KSpace::SurfelSet SurfelSet
Aim: implements association bewteen points lying in a digital domain and values.
Definition: Image.h:70
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
Dimension sOrthDir(const SCell &s) const
Given a signed surfel [s], returns its orthogonal direction (ie, the coordinate where the surfel is c...
Cell unsigns(const SCell &p) const
Creates an unsigned cell from a signed one.
Point sCoords(const SCell &c) const
Return its digital coordinates.
SCell sDirectIncident(const SCell &p, Dimension k) const
Return the direct incident cell of [p] along [k] (the incident cell along [k])
void beginBlock(const std::string &keyword="")
std::ostream & info()
void progressBar(const double currentValue, const double maximalValue)
double endBlock()
virtual void show()
Overload QWidget method in order to add a call to updateList() method (to ensure that the lists are w...
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
bool operator<(const VertexSize &vs1, const VertexSize &vs2)
SurfelSet::iterator SurfelSetIterator
int main(int argc, char **argv)
[greedy-plane-segmentation-ex2-typedefs]
MyDigitalSurface::Vertex Vertex
COBANaivePlaneComputer< Z3, InternalInteger > NaivePlaneComputer
MyDigitalSurface::ConstIterator ConstIterator
MyDigitalSurface::SurfelSet SurfelSet
BreadthFirstVisitor< MyDigitalSurface > Visitor
DigitalSetBoundary< KSpace, DigitalSet > MyDigitalSurfaceContainer
DGtal::int64_t InternalInteger
DGtal is the top-level namespace which contains all DGtal functions and types.
boost::int64_t int64_t
signed 94-bit integer.
Definition: BasicTypes.h:74
DGtal::uint32_t Dimension
Definition: Common.h:136
Trace trace
Definition: Common.h:153
Aim: Define utilities to convert a digital set into an image.
Definition: SetFromImage.h:64
Aim: implements methods to read a "Vol" file format.
Definition: VolReader.h:90
ImageContainerBySTLVector< Domain, Value > Image
TriMesh::Vertex Vertex