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"
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"
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"
62 #include <boost/program_options/options_description.hpp>
63 #include <boost/program_options/parsers.hpp>
64 #include <boost/program_options/variables_map.hpp>
69 using namespace DGtal;
72 namespace po = boost::program_options;
134 void missingParam ( std::string param )
136 trace.
error() <<
" Parameter: "<<param<<
" is required..";
142 int main (
int argc,
char**argv )
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)." );
158 po::variables_map vm;
160 po::store(po::parse_command_line(argc, argv, general_opt), vm);
161 }
catch(
const std::exception& ex){
163 trace.
info()<<
"Error checking program options: "<< ex.what()<< endl;
167 if (!parseOK || vm.count (
"help" ) ||argc<=1 )
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";
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>();
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>();
196 bool space_ok = ks.
init ( image.
domain().lowerBound(),
197 image.
domain().upperBound(), true );
200 trace.
error() <<
"Error in the Khamisky space construction."<<std::endl;
205 MySurfelAdjacency surfAdj (
true );
212 MyDigitalSurfaceContainer* ptrSurfContainer =
213 new MyDigitalSurfaceContainer ( ks, simplePredicate, surfAdj, bel );
214 MyDigitalSurface digSurf ( ptrSurfContainer );
215 MyDigitalSurface::ConstIterator it = digSurf.begin();
219 SurfaceEmbedder surfaceEmbedder ( digSurf );
228 MyGaussianEstimator myNormalEstimatorG ( digSurf, Gkernel );
232 SurfaceEmbedderWithGaussianNormal mySurfelEmbedderG ( surfaceEmbedder, myNormalEstimatorG );
235 myNormalEstimatorG.init ( 1.0, neighborhood );
237 trace.
info() <<
"Generating the NOFF surface "<< std::endl;
238 ofstream out2 ( ( outputFileName +
".off" ).c_str() );
240 digSurf.exportAs3DNOFF ( out2 ,mySurfelEmbedderG );
243 trace.
info() <<
"Generating the polar coordinates file"<< std::endl;
244 ofstream out3 ( ( outputFileName +
".txt" ).c_str() );
247 MyGaussianEstimator::Quantity res;
248 for ( MyDigitalSurface::ConstIterator it =digSurf.begin(),
249 itend = digSurf.end(); it != itend; ++it )
251 res = myNormalEstimatorG.eval ( it );
253 out3<< acos ( res [2] ) *180.0/M_PI <<
" " << ( atan2 ( res [1], res [0] ) + M_PI ) *180.0/M_PI;
255 if (vm.count(
"exportOriginAndExtremity"))
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];
bool init(const Point &lower, const Point &upper, bool isClosed)
Trace trace(traceWriterTerm)
const Domain & domain() const