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"
65 using namespace DGtal;
125 void missingParam ( std::string param )
127 trace.error() <<
" Parameter: "<<param<<
" is required..";
128 trace.info() <<std::endl;
133 int main (
int argc,
char**argv )
138 std::string filename;
139 std::string outputFileName;
140 unsigned int level {0};
142 unsigned int neighborhood {10};
143 double normExport {1.0};
145 app.description(
"Generates normal vector field from a vol file using DGtal library.\n Typical use example:\n \t vol2normalField[options] --input <volFileName> --o <outputFileName>\n");
146 app.add_option(
"-i,--input,1",filename,
"Input vol file.")->required()->check(CLI::ExistingFile);
147 app.add_option(
"-o,--output,2",outputFileName,
"Output file.")->required();
148 app.add_option(
"--level,-l",level,
"Iso-level for the surface construction (default 0).",
true);
149 app.add_option(
"--sigma,-s", sigma,
"Sigma parameter of the Gaussian kernel (default 5.0).",
true);
150 auto expOpt = app.add_flag(
"--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).");
151 app.add_option(
"--vectorsNorm,-N", normExport,
"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 (default 1.0).",
true);
152 app.add_option(
"--neighborhood,-n", neighborhood,
"Size of the neighborhood for the convolution (distance on surfel graph, default 10).",
true);
154 app.get_formatter()->column_width(40);
155 CLI11_PARSE(app, argc, argv);
158 typedef ImageSelector < Z3i::Domain, unsigned char>::Type Image;
159 Image image = VolReader<Image>::importVol ( filename );
161 trace.info() <<image<<std::endl;
163 functors::SimpleThresholdForegroundPredicate<Image> simplePredicate ( image, level );
166 bool space_ok = ks.init ( image.domain().lowerBound(),
167 image.domain().upperBound(),
true );
170 trace.error() <<
"Error in the Khamisky space construction."<<std::endl;
174 typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
175 MySurfelAdjacency surfAdj (
true );
178 typedef LightImplicitDigitalSurface<KSpace, functors::SimpleThresholdForegroundPredicate<Image> > MyDigitalSurfaceContainer;
179 typedef DigitalSurface<MyDigitalSurfaceContainer> MyDigitalSurface;
180 SCell bel = Surfaces<KSpace>::findABel ( ks, simplePredicate );
182 MyDigitalSurfaceContainer* ptrSurfContainer =
183 new MyDigitalSurfaceContainer ( ks, simplePredicate, surfAdj, bel );
184 MyDigitalSurface digSurf ( ptrSurfContainer );
185 MyDigitalSurface::ConstIterator it = digSurf.begin();
188 typedef CanonicDigitalSurfaceEmbedder<MyDigitalSurface> SurfaceEmbedder;
189 SurfaceEmbedder surfaceEmbedder ( digSurf );
192 deprecated::GaussianConvolutionWeights < MyDigitalSurface::Size > Gkernel ( sigma );
195 typedef deprecated::LocalConvolutionNormalVectorEstimator < MyDigitalSurface,
196 deprecated::GaussianConvolutionWeights< MyDigitalSurface::Size> > MyGaussianEstimator;
197 BOOST_CONCEPT_ASSERT ( ( concepts::CNormalVectorEstimator< MyGaussianEstimator > ) );
198 MyGaussianEstimator myNormalEstimatorG ( digSurf, Gkernel );
201 typedef DigitalSurfaceEmbedderWithNormalVectorEstimator<SurfaceEmbedder,MyGaussianEstimator> SurfaceEmbedderWithGaussianNormal;
202 SurfaceEmbedderWithGaussianNormal mySurfelEmbedderG ( surfaceEmbedder, myNormalEstimatorG );
205 myNormalEstimatorG.init ( 1.0, neighborhood );
207 trace.info() <<
"Generating the NOFF surface "<< std::endl;
208 ofstream out2 ( ( outputFileName +
".off" ).c_str() );
210 digSurf.exportAs3DNOFF ( out2 ,mySurfelEmbedderG );
213 trace.info() <<
"Generating the polar coordinates file"<< std::endl;
214 ofstream out3 ( ( outputFileName +
".txt" ).c_str() );
217 MyGaussianEstimator::Quantity res;
218 for ( MyDigitalSurface::ConstIterator it =digSurf.begin(),
219 itend = digSurf.end(); it != itend; ++it )
221 res = myNormalEstimatorG.eval ( it );
223 out3<< acos ( res [2] ) *180.0/M_PI <<
" " << ( atan2 ( res [1], res [0] ) + M_PI ) *180.0/M_PI;
225 if (expOpt->count()>0)
228 out3 <<
" " << mySurfelEmbedderG(*it)[0]
229 <<
" " << mySurfelEmbedderG(*it)[1]
230 <<
" " << mySurfelEmbedderG(*it)[2] <<
" "
231 << mySurfelEmbedderG(*it)[0]+res[0] <<
" "
232 << mySurfelEmbedderG(*it)[1]+res[1] <<
" "
233 << mySurfelEmbedderG(*it)[2]+res[2];