DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
greedy-plane-segmentation.cpp
1 
30 
31 #include <iostream>
32 #include <vector>
33 #include <set>
34 #include <map>
35 #include <iostream>
36 #include <boost/program_options/options_description.hpp>
37 #include <boost/program_options/parsers.hpp>
38 #include <boost/program_options/variables_map.hpp>
39 
40 #include <QtGui/qapplication.h>
41 #include "DGtal/base/Common.h"
42 #include "DGtal/io/readers/VolReader.h"
43 #include "DGtal/io/viewers/Viewer3D.h"
44 #include "DGtal/io/Display3D.h"
45 
46 #include "DGtal/io/DrawWithDisplay3DModifier.h"
47 #include "DGtal/images/ImageSelector.h"
48 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
49 #include "DGtal/topology/DigitalSurface.h"
50 #include "DGtal/topology/DigitalSetBoundary.h"
51 #include "DGtal/topology/BreadthFirstVisitor.h"
52 #include "DGtal/geometry/surfaces/COBANaivePlane.h"
53 #include "DGtal/helpers/StdDefs.h"
54 #include "ConfigExamples.h"
55 
57 
58 using namespace std;
59 using namespace DGtal;
60 namespace po = boost::program_options;
61 
63 using namespace Z3i;
64 typedef DGtal::int64_t InternalInteger;
66 // We choose the DigitalSetBoundary surface container in order to
67 // segment connected or unconnected surfaces.
70 typedef MyDigitalSurface::ConstIterator ConstIterator;
71 typedef MyDigitalSurface::Vertex Vertex;
72 typedef MyDigitalSurface::SurfelSet SurfelSet;
73 typedef SurfelSet::iterator SurfelSetIterator;
79 struct SegmentedPlane {
80  NaivePlaneComputer plane;
81  Color color;
82 };
84 
86 
87 int main( int argc, char** argv )
88 {
90  // parse command line ----------------------------------------------
91  po::options_description general_opt("Allowed options are: ");
92  general_opt.add_options()
93  ("help,h", "display this message")
94  ("input-file,i", po::value<std::string>()->default_value( examplesPath + "samples/Al.100.vol" ), "the volume file (.vol)" )
95  ("threshold,t", po::value<unsigned int>()->default_value(1), "the value that defines the isosurface in the image (an integer between 0 and 255)." )
96  ("width-num,w", po::value<unsigned int>()->default_value(1), "the numerator of the rational width (a non-null integer)." )
97  ("width-den,d", po::value<unsigned int>()->default_value(1), "the denominator of the rational width (a non-null integer)." );
98 
99  bool parseOK = true;
100  po::variables_map vm;
101  try {
102  po::store(po::parse_command_line(argc, argv, general_opt), vm);
103  } catch ( const std::exception & ex ) {
104  parseOK = false;
105  trace.info() << "Error checking program options: "<< ex.what()<< endl;
106  }
107  po::notify(vm);
108  if ( ! parseOK || vm.count("help") || ( argc <= 1 ) )
109  {
110  std::cout << "Usage: " << argv[0]
111  << " [-i <fileName.vol>] [-t <threshold>] [-w <num>] [-d <den>]" << std::endl
112  << "Segments the surface at given threshold within given volume into digital planes of rational width num/den." << std::endl
113  << general_opt << std::endl;
114  return 0;
115  }
116  string inputFilename = vm["input-file"].as<std::string>();
117  unsigned int threshold = vm["threshold"].as<unsigned int>();
118  unsigned int widthNum = vm["width-num"].as<unsigned int>();
119  unsigned int widthDen = vm["width-den"].as<unsigned int>();
121 
123  QApplication application(argc,argv);
125  Image image = VolReader<Image>::importVol(inputFilename);
126  DigitalSet set3d (image.domain());
127  SetFromImage<DigitalSet>::append<Image>(set3d, image, threshold,255);
129 
131  trace.beginBlock( "Set up digital surface." );
132  // We initializes the cellular grid space used for defining the
133  // digital surface.
134  KSpace ks;
135  bool ok = ks.init( set3d.domain().lowerBound(),
136  set3d.domain().upperBound(), true );
137  if ( ! ok ) std::cerr << "[KSpace.init] Failed." << std::endl;
138  SurfelAdjacency<KSpace::dimension> surfAdj( true ); // interior in all directions.
139  MyDigitalSurfaceContainer* ptrSurfContainer =
140  new MyDigitalSurfaceContainer( ks, set3d, surfAdj );
141  MyDigitalSurface digSurf( ptrSurfContainer ); // acquired
142  trace.endBlock();
144 
146  trace.beginBlock( "Segment into planes." );
147  std::set<Vertex> processedVertices;
148  std::vector<SegmentedPlane*> segmentedPlanes;
149  std::map<Vertex,SegmentedPlane*> v2plane;
150  Point p;
151  Dimension axis;
152  unsigned int j = 0;
153  unsigned int nb = digSurf.size();
154  for ( ConstIterator it = digSurf.begin(), itE= digSurf.end(); it != itE; ++it )
155  {
156  if ( ( (++j) % 50 == 0 ) || ( j == nb ) ) trace.progressBar( j, nb );
157  Vertex v = *it;
158  if ( processedVertices.find( v ) != processedVertices.end() ) // already in set
159  continue; // process to next vertex
160 
161  SegmentedPlane* ptrSegment = new SegmentedPlane;
162  segmentedPlanes.push_back( ptrSegment ); // to delete them afterwards.
163  axis = ks.sOrthDir( v );
164  ptrSegment->plane.init( axis, 500, widthNum, widthDen );
165  // The visitor takes care of all the breadth-first traversal.
166  Visitor visitor( digSurf, v );
167  while ( ! visitor.finished() )
168  {
169  Visitor::Node node = visitor.current();
170  v = node.first;
171  if ( processedVertices.find( v ) == processedVertices.end() )
172  { // Vertex is not in processedVertices
173  axis = ks.sOrthDir( v );
174  p = ks.sCoords( ks.sDirectIncident( v, axis ) );
175  bool isExtended = ptrSegment->plane.extend( p );
176  if ( isExtended )
177  { // surfel is in plane.
178  processedVertices.insert( v );
179  v2plane[ v ] = ptrSegment;
180  visitor.expand();
181  }
182  else // surfel is not in plane and should not be used in the visit.
183  visitor.ignore();
184  }
185  else // surfel is already in some plane.
186  visitor.ignore();
187  }
188  // Assign random color for each plane.
189  ptrSegment->color = Color( random() % 256, random() % 256, random() % 256, 255 );
190  }
191  trace.endBlock();
193 
195  Viewer3D viewer;
196  viewer.show();
197  for ( std::map<Vertex,SegmentedPlane*>::const_iterator
198  it = v2plane.begin(), itE = v2plane.end();
199  it != itE; ++it )
200  {
201  viewer << CustomColors3D( it->second->color, it->second->color );
202  viewer << ks.unsigns( it->first );
203  }
204  viewer << Display3D::updateDisplay;
206 
208  for ( std::vector<SegmentedPlane*>::iterator
209  it = segmentedPlanes.begin(), itE = segmentedPlanes.end();
210  it != itE; ++it )
211  delete *it;
212  segmentedPlanes.clear();
213  v2plane.clear();
215 
216  return application.exec();
217 }