DGtalTools  0.9.4
vol2normalField.cpp
1 
30 #include <iostream>
32 #include <iterator>
33 #include "DGtal/base/Common.h"
34 #include "DGtal/topology/CanonicDigitalSurfaceEmbedder.h"
35 #include "DGtal/topology/DigitalSurface.h"
36 #include "DGtal/topology/DigitalSetBoundary.h"
37 #include "DGtal/topology/ImplicitDigitalSurface.h"
38 #include "DGtal/topology/LightImplicitDigitalSurface.h"
39 #include "DGtal/topology/ExplicitDigitalSurface.h"
40 #include "DGtal/topology/LightExplicitDigitalSurface.h"
41 #include "DGtal/graph/BreadthFirstVisitor.h"
42 #include "DGtal/topology/helpers/FrontierPredicate.h"
43 #include "DGtal/topology/helpers/BoundaryPredicate.h"
44 #include "DGtal/graph/CUndirectedSimpleLocalGraph.h"
45 #include "DGtal/graph/CUndirectedSimpleGraph.h"
46 
47 #include "DGtal/io/readers/VolReader.h"
48 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
49 #include "DGtal/images/SimpleThresholdForegroundPredicate.h"
50 #include "DGtal/images/ImageSelector.h"
51 #include "DGtal/shapes/Shapes.h"
52 #include "DGtal/helpers/StdDefs.h"
53 #include "DGtal/kernel/CanonicEmbedder.h"
54 
55 #include "DGtal/geometry/surfaces/estimation/CNormalVectorEstimator.h"
56 #include "DGtal/geometry/surfaces/estimation/BasicConvolutionWeights.h"
57 #include "DGtal/geometry/surfaces/estimation/LocalConvolutionNormalVectorEstimator.h"
58 #include "DGtal/geometry/surfaces/estimation/DigitalSurfaceEmbedderWithNormalVectorEstimator.h"
59 
60 
61 
62 #include <boost/program_options/options_description.hpp>
63 #include <boost/program_options/parsers.hpp>
64 #include <boost/program_options/variables_map.hpp>
65 
67 
68 using namespace std;
69 using namespace DGtal;
70 using namespace Z3i;
71 
72 namespace po = boost::program_options;
73 
74 
134 void missingParam ( std::string param )
135 {
136  trace.error() <<" Parameter: "<<param<<" is required..";
137  trace.info() <<std::endl;
138  exit ( 1 );
139 }
140 
141 
142 int main ( int argc, char**argv )
143 {
144 
145  // parse command line ----------------------------------------------
146  po::options_description general_opt ( "Allowed options are: " );
147  general_opt.add_options()
148  ( "help,h", "display this message." )
149  ( "input,i", po::value<std::string>(), "Input vol file." )
150  ( "output,o", po::value<string>(),"Output filename." )
151  ( "level,l", po::value<unsigned int>()->default_value ( 0 ),"Iso-level for the surface construction." )
152  ( "sigma,s", po::value<double>()->default_value ( 5.0 ),"Sigma parameter of the Gaussian kernel." )
153  ("exportOriginAndExtremity", "exports the origin and extremity of the vector fields when exporting the vector field in TXT format (useful to be displayed in other viewer like meshViewer).")
154  ("vectorsNorm,N", po::value<double>()->default_value(1.0), "set the norm of the exported vectors in TXT format (when the extremity points are exported with --exportOriginAndExtremity). By using a negative value you will invert the direction of the vectors.")
155  ( "neighborhood,n", po::value<unsigned int>()->default_value ( 10 ),"Size of the neighborhood for the convolution (distance on surfel graph)." );
156 
157  bool parseOK=true;
158  po::variables_map vm;
159  try{
160  po::store(po::parse_command_line(argc, argv, general_opt), vm);
161  }catch(const std::exception& ex){
162  parseOK=false;
163  trace.info()<< "Error checking program options: "<< ex.what()<< endl;
164  }
165 
166  po::notify ( vm );
167  if (!parseOK || vm.count ( "help" ) ||argc<=1 )
168  {
169  trace.info() << "Generate normal vector field from a vol file using DGtal library."<<std::endl
170  << "It will output the embedded vector field (Gaussian convolution on elementary normal vectors)"<<std::endl
171  << "an OFF file, and a TXT normal vector file (theta, phi in degree)."
172  << std::endl << "Basic usage: "<<std::endl
173  << "\tvol2normalField[options] --input <volFileName> --o <outputFileName> "<<std::endl
174  << general_opt << "\n";
175  return 0;
176  }
177 
178  //Parse options
179  if ( ! ( vm.count ( "input" ) ) ) missingParam ( "--input" );
180  std::string filename = vm["input"].as<std::string>();
181  if ( ! ( vm.count ( "output" ) ) ) missingParam ( "--output" );
182  std::string outputFileName = vm["output"].as<std::string>();
183 
184  unsigned int level = vm["level"].as<unsigned int>();
185  double sigma = vm["sigma"].as<double>();
186  unsigned int neighborhood = vm["neighborhood"].as<unsigned int>();
187  double normExport = vm["vectorsNorm"].as<double>();
189  Image image = VolReader<Image>::importVol ( filename );
190 
191  trace.info() <<image<<std::endl;
192 
193  functors::SimpleThresholdForegroundPredicate<Image> simplePredicate ( image, level );
194 
195  KSpace ks;
196  bool space_ok = ks.init ( image.domain().lowerBound(),
197  image.domain().upperBound(), true );
198  if ( !space_ok )
199  {
200  trace.error() << "Error in the Khamisky space construction."<<std::endl;
201  return 2;
202  }
203 
204  typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
205  MySurfelAdjacency surfAdj ( true ); // interior in all directions.
206 
207  //Set up digital surface.
209  typedef DigitalSurface<MyDigitalSurfaceContainer> MyDigitalSurface;
210  SCell bel = Surfaces<KSpace>::findABel ( ks, simplePredicate );
211 
212  MyDigitalSurfaceContainer* ptrSurfContainer =
213  new MyDigitalSurfaceContainer ( ks, simplePredicate, surfAdj, bel );
214  MyDigitalSurface digSurf ( ptrSurfContainer ); // acquired
215  MyDigitalSurface::ConstIterator it = digSurf.begin();
216 
217  // Embedder definition
218  typedef CanonicDigitalSurfaceEmbedder<MyDigitalSurface> SurfaceEmbedder;
219  SurfaceEmbedder surfaceEmbedder ( digSurf );
220 
221  //Convolution kernel
223 
224  //Estimator definition
225  typedef deprecated::LocalConvolutionNormalVectorEstimator < MyDigitalSurface,
227  BOOST_CONCEPT_ASSERT ( ( concepts::CNormalVectorEstimator< MyGaussianEstimator > ) );
228  MyGaussianEstimator myNormalEstimatorG ( digSurf, Gkernel );
229 
230  // Embedder definition
232  SurfaceEmbedderWithGaussianNormal mySurfelEmbedderG ( surfaceEmbedder, myNormalEstimatorG );
233 
234  // Compute normal vector field and displays it.
235  myNormalEstimatorG.init ( 1.0, neighborhood );
236 
237  trace.info() << "Generating the NOFF surface "<< std::endl;
238  ofstream out2 ( ( outputFileName + ".off" ).c_str() );
239  if ( out2.good() )
240  digSurf.exportAs3DNOFF ( out2 ,mySurfelEmbedderG );
241  out2.close();
242 
243  trace.info() << "Generating the polar coordinates file"<< std::endl;
244  ofstream out3 ( ( outputFileName + ".txt" ).c_str() );
245  if ( out3.good() )
246  {
247  MyGaussianEstimator::Quantity res;
248  for ( MyDigitalSurface::ConstIterator it =digSurf.begin(),
249  itend = digSurf.end(); it != itend; ++it )
250  {
251  res = myNormalEstimatorG.eval ( it );
252  //We output Theta - Phi
253  out3<< acos ( res [2] ) *180.0/M_PI <<" " << ( atan2 ( res [1], res [0] ) + M_PI ) *180.0/M_PI;
254 
255  if (vm.count("exportOriginAndExtremity"))
256  {
257  res *= normExport;
258  out3 << " " << mySurfelEmbedderG(*it)[0]
259  << " " << mySurfelEmbedderG(*it)[1]
260  << " " << mySurfelEmbedderG(*it)[2] << " "
261  << mySurfelEmbedderG(*it)[0]+res[0] << " "
262  << mySurfelEmbedderG(*it)[1]+res[1] << " "
263  << mySurfelEmbedderG(*it)[2]+res[2];
264 
265  }
266 
267  out3 <<std::endl;
268  }
269  }
270  out3.close();
271 
272  return 0;
273 }
274 
275 
276 // //
278 
STL namespace.
bool init(const Point &lower, const Point &upper, bool isClosed)
Trace trace(traceWriterTerm)
std::ostream & info()
const Domain & domain() const
std::ostream & error()