int main( int narg, char **argv ) { trace.beginBlock("Identifying the domain."); Z3i::Domain domain = scene_dimensions( argv[1] ) ; if ( domain.lowerBound() == domain.upperBound() ) { trace.error()<<"Invalid domain ("<<__FILE__<<")"<<std::endl; return -1 ; } trace.endBlock() ; trace.beginBlock("Reading slices."); Z3i::DigitalSet set3d( domain ) ; SetPredicate<Z3i::DigitalSet> set3dPredicate( set3d ) ; for ( uint depth = 0 ; depth < domain.upperBound().at(2) ; depth++ ) process_slice( argv[1], depth, set3d ) ; trace.endBlock() ; if ( 0) { try { Gray3DImage aImage( domain ); for ( Z3i::Domain::ConstIterator pt = domain.begin() ; pt != domain.end() ; pt++ ) aImage.setValue( (*pt), 255 ) ; boost::filesystem::path pathvolname = argv[1] ; pathvolname /= "obj.vol" ; if ( ! DGtal::VolWriter< Gray3DImage, GrayColorMap >::exportVol ( pathvolname.string(), aImage, 0, 255 ) ) { trace.error() <<"Can not export data (generated 3D object)"<<std::endl; return -4 ; } else { trace.info()<<"export data to "<<pathvolname.string()<<std::endl; } pathvolname = argv[1] ; pathvolname /= "obj.pgm3d" ; if ( ! PNMWriter<Gray3DImage, GrayColorMap >::exportPGM3D( pathvolname.string(), aImage, 0, 255 ) ) { trace.error() <<"Can not export data (generated 3D object)"<<std::endl; return -4 ; } else { trace.info()<<"export data to "<<pathvolname.string()<<std::endl; } } catch ( std::exception &e ) { trace.error() <<"Can not export data (generated 3D object) "<<e.what()<<std::endl; return -8 ; } } trace.beginBlock( "Decompose the object into connected components." ); { DGtal::Z3i::Object6_18 scene( DGtal::Z3i::dt6_18, set3d ) ; std::vector< Z3i::Object6_18 > v_obj ; back_insert_iterator< std::vector< Z3i::Object6_18 > > it( v_obj ) ; scene.writeComponents( it ) ; boost::filesystem::path scenefilename = argv[1] ; scenefilename /= "scene.pgm3d" ; IOPgm3d::write( v_obj, scenefilename.string().c_str() ) ; } trace.endBlock( ); return -64; trace.beginBlock( "Construct the Khalimsky space from the image domain." ); Z3i::KSpace ks; bool space_ok = ks.init( domain.lowerBound(), domain.upperBound(), true ); if (!space_ok) { trace.error() << "Error in the Khamisky space construction."<<std::endl; return -2; } trace.endBlock(); typedef SurfelAdjacency<Z3i::KSpace::dimension> MySurfelAdjacency; MySurfelAdjacency surfAdj( true ); // interior in all directions. trace.beginBlock( "Extracting boundary by tracking from an initial bel." ); Z3i::KSpace::SCellSet boundary; Z3i::SCell bel = Surfaces<Z3i::KSpace>::findABel( ks, set3dPredicate, 100000 ); Surfaces<Z3i::KSpace>::trackBoundary( boundary, ks, surfAdj, set3dPredicate, bel ); trace.endBlock(); trace.beginBlock( "Displaying surface in Viewer3D." ); QApplication application(narg,argv); Viewer3D viewer; viewer.show(); viewer << SetMode3D( boundary.begin()->className(), "") ; //CustomColors3D(Color(250, 0, 0 ), Color( 128, 128, 128 ) ); unsigned long nbSurfels = 0; for ( Z3i::KSpace::SCellSet::const_iterator it = boundary.begin(), it_end = boundary.end(); it != it_end; ++it, ++nbSurfels ) viewer << ks.uCell( Z3i::Point( (*it).myCoordinates.at(0), (*it).myCoordinates.at(1), (*it).myCoordinates.at(2) ) ) ; /** for ( Z3i::KSpace::SCellSet::const_iterator it = boundary.begin(), it_end = boundary.end(); it != it_end; ++it, ++nbSurfels ) viewer << (*it) ; */ trace.info() << *boundary.begin()<<std::endl; viewer << Viewer3D::updateDisplay; trace.info() << "nb surfels = " << nbSurfels << std::endl; trace.endBlock(); return application.exec(); }
int main( int argc, char** argv ) { // parse command line ---------------------------------------------- po::options_description general_opt("Allowed options are"); general_opt.add_options() ("help,h", "display this message") ("input,i", po::value< std::string >(), ".vol file") ("radius,r", po::value< double >(), "Kernel radius for IntegralInvariant" ) ("threshold,t", po::value< unsigned int >()->default_value(8), "Min size of SCell boundary of an object" ) ("minImageThreshold,l", po::value< int >()->default_value(0), "set the minimal image threshold to define the image object (object defined by the voxel with intensity belonging to ]minImageThreshold, maxImageThreshold ] )." ) ("maxImageThreshold,u", po::value< int >()->default_value(255), "set the minimal image threshold to define the image object (object defined by the voxel with intensity belonging to ]minImageThreshold, maxImageThreshold] )." ) ("mode,m", po::value< std::string >()->default_value("mean"), "type of output : mean, gaussian, k1, k2, prindir1, prindir2 or normal (default mean)") ("exportOBJ,o", po::value< std::string >(), "Export the scene to specified OBJ/MTL filename (extensions added)." ) ("exportDAT,d", po::value<std::string>(), "Export resulting curvature (for mean, gaussian, k1 or k2 mode) in a simple data file each line representing a surfel. ") ("exportOnly", "Used to only export the result without the 3d Visualisation (usefull for scripts)." ) ("imageScale,s", po::value<std::vector<double> >()->multitoken(), "scaleX, scaleY, scaleZ: re sample the source image according with a grid of size 1.0/scale (usefull to compute curvature on image defined on anisotropic grid). Set by default to 1.0 for the three axis. ") ("normalization,n", "When exporting to OBJ, performs a normalization so that the geometry fits in [-1/2,1/2]^3") ; bool parseOK = true; po::variables_map vm; try { po::store( po::parse_command_line( argc, argv, general_opt ), vm ); } catch( const std::exception & ex ) { parseOK = false; trace.error() << " Error checking program options: " << ex.what() << std::endl; } bool neededArgsGiven=true; if (parseOK && !(vm.count("input"))){ missingParam("--input"); neededArgsGiven=false; } if (parseOK && !(vm.count("radius"))){ missingParam("--radius"); neededArgsGiven=false; } bool normalization = false; if (parseOK && vm.count("normalization")) normalization = true; std::string mode; if( parseOK ) mode = vm["mode"].as< std::string >(); if ( parseOK && ( mode.compare("gaussian") != 0 ) && ( mode.compare("mean") != 0 ) && ( mode.compare("k1") != 0 ) && ( mode.compare("k2") != 0 ) && ( mode.compare("prindir1") != 0 ) && ( mode.compare("prindir2") != 0 ) && ( mode.compare("normal") != 0 )) { parseOK = false; trace.error() << " The selected mode ("<<mode << ") is not defined."<<std::endl; } #ifndef WITH_VISU3D_QGLVIEWER bool enable_visu = false; #else bool enable_visu = !vm.count("exportOnly"); ///<! Default QGLViewer viewer. Disabled if exportOnly is set. #endif bool enable_obj = vm.count("exportOBJ"); ///<! Export to a .obj file. bool enable_dat = vm.count("exportDAT"); ///<! Export to a .dat file. if( !enable_visu && !enable_obj && !enable_dat ) { #ifndef WITH_VISU3D_QGLVIEWER trace.error() << "You should specify what you want to export with --export and/or --exportDat." << std::endl; #else trace.error() << "You should specify what you want to export with --export and/or --exportDat, or remove --exportOnly." << std::endl; #endif neededArgsGiven = false; } if(!neededArgsGiven || !parseOK || vm.count("help") || argc <= 1 ) { trace.info()<< "Visualisation of 3d curvature from .vol file using curvature from Integral Invariant" <<std::endl << general_opt << "\n" << "Basic usage: "<<std::endl << "\t3dCurvatureViewer -i file.vol --radius 5 --mode mean"<<std::endl << std::endl << "Below are the different available modes: " << std::endl << "\t - \"mean\" for the mean curvature" << std::endl << "\t - \"gaussian\" for the Gaussian curvature" << std::endl << "\t - \"k1\" for the first principal curvature" << std::endl << "\t - \"k2\" for the second principal curvature" << std::endl << "\t - \"prindir1\" for the first principal curvature direction" << std::endl << "\t - \"prindir2\" for the second principal curvature direction" << std::endl << "\t - \"normal\" for the normal vector" << std::endl << std::endl; return 0; } unsigned int threshold = vm["threshold"].as< unsigned int >(); int minImageThreshold = vm["minImageThreshold"].as< int >(); int maxImageThreshold = vm["maxImageThreshold"].as< int >(); double h = 1.0; std::string export_obj_filename; std::string export_dat_filename; if( enable_obj ) { export_obj_filename = vm["exportOBJ"].as< std::string >(); if( export_obj_filename.find(".obj") == std::string::npos ) { std::ostringstream oss; oss << export_obj_filename << ".obj" << std::endl; export_obj_filename = oss.str(); } } if( enable_dat ) { export_dat_filename = vm["exportDAT"].as<std::string>(); } double re_convolution_kernel = vm["radius"].as< double >(); std::vector< double > aGridSizeReSample; if( vm.count( "imageScale" )) { std::vector< double> vectScale = vm["imageScale"].as<std::vector<double > >(); if( vectScale.size() != 3 ) { trace.error() << "The grid size should contains 3 elements" << std::endl; return 0; } else { aGridSizeReSample.push_back(1.0/vectScale.at(0)); aGridSizeReSample.push_back(1.0/vectScale.at(1)); aGridSizeReSample.push_back(1.0/vectScale.at(2)); } } else { aGridSizeReSample.push_back(1.0); aGridSizeReSample.push_back(1.0); aGridSizeReSample.push_back(1.0); } // Construction of the shape from vol file typedef Z3i::Space::RealPoint RealPoint; typedef Z3i::Point Point; typedef ImageSelector< Z3i::Domain, int>::Type Image; typedef DGtal::functors::BasicDomainSubSampler< HyperRectDomain<SpaceND<3, int> >, DGtal::int32_t, double > ReSampler; typedef DGtal::ConstImageAdapter<Image, Image::Domain, ReSampler, Image::Value, DGtal::functors::Identity > SamplerImageAdapter; typedef IntervalForegroundPredicate< SamplerImageAdapter > ImagePredicate; typedef BinaryPointPredicate<DomainPredicate<Image::Domain>, ImagePredicate, AndBoolFct2 > Predicate; typedef Z3i::KSpace KSpace; typedef KSpace::SCell SCell; typedef KSpace::Cell Cell; trace.beginBlock("Loading the file"); std::string filename = vm["input"].as< std::string >(); Image image = GenericReader<Image>::import( filename ); PointVector<3,int> shiftVector3D( 0 ,0, 0 ); DGtal::functors::BasicDomainSubSampler< HyperRectDomain< SpaceND< 3, int > >, DGtal::int32_t, double > reSampler(image.domain(), aGridSizeReSample, shiftVector3D); const functors::Identity identityFunctor{}; SamplerImageAdapter sampledImage ( image, reSampler.getSubSampledDomain(), reSampler, identityFunctor ); ImagePredicate predicateIMG = ImagePredicate( sampledImage, minImageThreshold, maxImageThreshold ); DomainPredicate<Z3i::Domain> domainPredicate( sampledImage.domain() ); AndBoolFct2 andF; Predicate predicate(domainPredicate, predicateIMG, andF ); Z3i::Domain domain = sampledImage.domain(); Z3i::KSpace K; bool space_ok = K.init( domain.lowerBound()-Z3i::Domain::Point::diagonal(), domain.upperBound()+Z3i::Domain::Point::diagonal(), true ); if (!space_ok) { trace.error() << "Error in the Khalimsky space construction."<<std::endl; return 2; } CanonicSCellEmbedder< KSpace > embedder( K ); SurfelAdjacency< Z3i::KSpace::dimension > Sadj( true ); trace.endBlock(); // Viewer settings // Extraction of components typedef KSpace::SurfelSet SurfelSet; typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels; typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface; trace.beginBlock("Extracting surfaces"); std::vector< std::vector<SCell > > vectConnectedSCell; Surfaces<KSpace>::extractAllConnectedSCell(vectConnectedSCell,K, Sadj, predicate, false); std::ofstream outDat; if( enable_dat ) { trace.info() << "Exporting curvature as dat file: "<< export_dat_filename <<std::endl; outDat.open( export_dat_filename.c_str() ); outDat << "# data exported from 3dCurvatureViewer implementing the II curvature estimator (Coeurjolly, D.; Lachaud, J.O; Levallois, J., (2013). Integral based Curvature" << " Estimators in Digital Geometry. DGCI 2013.) " << std::endl; outDat << "# format: surfel coordinates (in Khalimsky space) curvature: "<< mode << std::endl; } trace.info()<<"Number of components= "<<vectConnectedSCell.size()<<std::endl; trace.endBlock(); if( vectConnectedSCell.size() == 0 ) { trace.error()<< "No surface component exists. Please check the vol file threshold parameter."; trace.info()<<std::endl; exit(2); } #ifdef WITH_VISU3D_QGLVIEWER QApplication application( argc, argv ); typedef Viewer3D<Z3i::Space, Z3i::KSpace> Viewer; #endif typedef Board3D<Z3i::Space, Z3i::KSpace> Board; #ifdef WITH_VISU3D_QGLVIEWER Viewer viewer( K ); #endif Board board( K ); #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { viewer.show(); } #endif for( unsigned int i = 0; i<vectConnectedSCell.size(); ++i ) { if( vectConnectedSCell[i].size() <= threshold ) { continue; } MySetOfSurfels aSet(K, Sadj); for( std::vector<SCell>::const_iterator it = vectConnectedSCell.at(i).begin(); it != vectConnectedSCell.at(i).end(); ++it ) { aSet.surfelSet().insert( *it); } MyDigitalSurface digSurf( aSet ); typedef DepthFirstVisitor<MyDigitalSurface> Visitor; typedef GraphVisitorRange< Visitor > VisitorRange; typedef VisitorRange::ConstIterator SurfelConstIterator; VisitorRange range( new Visitor( digSurf, *digSurf.begin() ) ); SurfelConstIterator abegin = range.begin(); SurfelConstIterator aend = range.end(); VisitorRange range2( new Visitor( digSurf, *digSurf.begin() ) ); SurfelConstIterator abegin2 = range2.begin(); trace.beginBlock("Curvature computation on a component"); if( ( mode.compare("gaussian") == 0 ) || ( mode.compare("mean") == 0 ) || ( mode.compare("k1") == 0 ) || ( mode.compare("k2") == 0 )) { typedef double Quantity; std::vector< Quantity > results; std::back_insert_iterator< std::vector< Quantity > > resultsIterator( results ); if ( mode.compare("mean") == 0 ) { typedef functors::IIMeanCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor; typedef IntegralInvariantVolumeEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator; MyIICurvatureFunctor functor; functor.init( h, re_convolution_kernel ); MyIIEstimator estimator( functor ); estimator.attach( K, predicate ); estimator.setParams( re_convolution_kernel/h ); estimator.init( h, abegin, aend ); estimator.eval( abegin, aend, resultsIterator ); } else if ( mode.compare("gaussian") == 0 ) { typedef functors::IIGaussianCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor; typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator; MyIICurvatureFunctor functor; functor.init( h, re_convolution_kernel ); MyIIEstimator estimator( functor ); estimator.attach( K, predicate ); estimator.setParams( re_convolution_kernel/h ); estimator.init( h, abegin, aend ); estimator.eval( abegin, aend, resultsIterator ); } else if ( mode.compare("k1") == 0 ) { typedef functors::IIFirstPrincipalCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor; typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator; MyIICurvatureFunctor functor; functor.init( h, re_convolution_kernel ); MyIIEstimator estimator( functor ); estimator.attach( K, predicate ); estimator.setParams( re_convolution_kernel/h ); estimator.init( h, abegin, aend ); estimator.eval( abegin, aend, resultsIterator ); } else if ( mode.compare("k2") == 0 ) { typedef functors::IISecondPrincipalCurvature3DFunctor<Z3i::Space> MyIICurvatureFunctor; typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator; MyIICurvatureFunctor functor; functor.init( h, re_convolution_kernel ); MyIIEstimator estimator( functor ); estimator.attach( K, predicate ); estimator.setParams( re_convolution_kernel/h ); estimator.init( h, abegin, aend ); estimator.eval( abegin, aend, resultsIterator ); } trace.endBlock(); // Drawing results trace.beginBlock("Visualisation"); Quantity min = results[ 0 ]; Quantity max = results[ 0 ]; for ( unsigned int i = 1; i < results.size(); ++i ) { if ( results[ i ] < min ) { min = results[ i ]; } else if ( results[ i ] > max ) { max = results[ i ]; } } trace.info() << "Max value= "<<max<<" min value= "<<min<<std::endl; ASSERT( min <= max ); typedef GradientColorMap< Quantity > Gradient; Gradient cmap_grad( min, (max==min)? max+1: max ); cmap_grad.addColor( Color( 50, 50, 255 ) ); cmap_grad.addColor( Color( 255, 0, 0 ) ); cmap_grad.addColor( Color( 255, 255, 10 ) ); #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { viewer << SetMode3D((*abegin2).className(), "Basic" ); } #endif if( enable_obj ) { board << SetMode3D((K.unsigns(*abegin2)).className(), "Basic" ); } for ( unsigned int i = 0; i < results.size(); ++i ) { #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { viewer << CustomColors3D( Color::Black, cmap_grad( results[ i ] )); viewer << *abegin2; } #endif if( enable_obj ) { board << CustomColors3D( Color::Black, cmap_grad( results[ i ] )); board << K.unsigns(*abegin2); } if( enable_dat ) { Point kCoords = K.uKCoords(K.unsigns(*abegin2)); outDat << kCoords[0] << " " << kCoords[1] << " " << kCoords[2] << " " << results[i] << std::endl; } ++abegin2; } } else { typedef Z3i::Space::RealVector Quantity; std::vector< Quantity > results; std::back_insert_iterator< std::vector< Quantity > > resultsIterator( results ); if( mode.compare("prindir1") == 0 ) { typedef functors::IIFirstPrincipalDirectionFunctor<Z3i::Space> MyIICurvatureFunctor; typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator; MyIICurvatureFunctor functor; functor.init( h, re_convolution_kernel ); MyIIEstimator estimator( functor ); estimator.attach( K, predicate ); estimator.setParams( re_convolution_kernel/h ); estimator.init( h, abegin, aend ); estimator.eval( abegin, aend, resultsIterator ); } else if( mode.compare("prindir2") == 0 ) { typedef functors::IISecondPrincipalDirectionFunctor<Z3i::Space> MyIICurvatureFunctor; typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator; MyIICurvatureFunctor functor; functor.init( h, re_convolution_kernel ); MyIIEstimator estimator( functor ); estimator.attach( K, predicate ); estimator.setParams( re_convolution_kernel/h ); estimator.init( h, abegin, aend ); estimator.eval( abegin, aend, resultsIterator ); } else if( mode.compare("normal") == 0 ) { typedef functors::IINormalDirectionFunctor<Z3i::Space> MyIICurvatureFunctor; typedef IntegralInvariantCovarianceEstimator<Z3i::KSpace, Predicate, MyIICurvatureFunctor> MyIIEstimator; MyIICurvatureFunctor functor; functor.init( h, re_convolution_kernel ); MyIIEstimator estimator( functor ); estimator.attach( K, predicate ); estimator.setParams( re_convolution_kernel/h ); estimator.init( h, abegin, aend ); estimator.eval( abegin, aend, resultsIterator ); } ///Visualizaton / export #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { viewer << SetMode3D(K.uCell( K.sKCoords(*abegin2) ).className(), "Basic" ); } #endif if( enable_obj ) { board << SetMode3D(K.uCell( K.sKCoords(*abegin2) ).className(), "Basic" ); } for ( unsigned int i = 0; i < results.size(); ++i ) { DGtal::Dimension kDim = K.sOrthDir( *abegin2 ); SCell outer = K.sIndirectIncident( *abegin2, kDim); if ( predicate(embedder(outer)) ) { outer = K.sDirectIncident( *abegin2, kDim); } Cell unsignedSurfel = K.uCell( K.sKCoords(*abegin2) ); #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { viewer << CustomColors3D( DGtal::Color(255,255,255,255), DGtal::Color(255,255,255,255)) << unsignedSurfel; } #endif if( enable_obj ) { board << CustomColors3D( DGtal::Color(255,255,255,255), DGtal::Color(255,255,255,255)) << unsignedSurfel; } if( enable_dat ) { Point kCoords = K.uKCoords(K.unsigns(*abegin2)); outDat << kCoords[0] << " " << kCoords[1] << " " << kCoords[2] << " " << results[i][0] << " " << results[i][1] << " " << results[i][2] << std::endl; } RealPoint center = embedder( outer ); #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { if( mode.compare("prindir1") == 0 ) { viewer.setLineColor( AXIS_COLOR_BLUE ); } else if( mode.compare("prindir2") == 0 ) { viewer.setLineColor( AXIS_COLOR_RED ); } else if( mode.compare("normal") == 0 ) { viewer.setLineColor( AXIS_COLOR_GREEN ); } viewer.addLine ( RealPoint( center[0] - 0.5 * results[i][0], center[1] - 0.5 * results[i][1], center[2] - 0.5 * results[i][2] ), RealPoint( center[0] + 0.5 * results[i][0], center[1] + 0.5 * results[i][1], center[2] + 0.5 * results[i][2] ), AXIS_LINESIZE ); } #endif if( enable_obj ) { if( mode.compare("prindir1") == 0 ) { board.setFillColor( AXIS_COLOR_BLUE ); } else if( mode.compare("prindir2") == 0 ) { board.setFillColor( AXIS_COLOR_RED ); } else if( mode.compare("normal") == 0 ) { board.setFillColor( AXIS_COLOR_GREEN ); } board.addCylinder ( RealPoint( center[0] - 0.5 * results[i][0], center[1] - 0.5 * results[i][1], center[2] - 0.5 * results[i][2]), RealPoint( center[0] + 0.5 * results[i][0], center[1] + 0.5 * results[i][1], center[2] + 0.5 * results[i][2]), 0.2 ); } ++abegin2; } } trace.endBlock(); } #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { viewer << Viewer3D<>::updateDisplay; } #endif if( enable_obj ) { trace.info()<< "Exporting object: " << export_obj_filename << " ..."; board.saveOBJ(export_obj_filename,normalization); trace.info() << "[done]" << std::endl; } if( enable_dat ) { outDat.close(); } #ifdef WITH_VISU3D_QGLVIEWER if( enable_visu ) { return application.exec(); } #endif return 0; }
int main( int argc, char** argv ) { if ( argc != 4 ) { trace.error() << "Usage: " << argv[0] << " <fileName.vol> <threshold> <re_convolution_kernel>" << std::endl; trace.error() << "Example : "<< argv[0] << " Al.150.vol 0 7.39247665" << std::endl; return 0; } trace.beginBlock ( "Example IntegralInvariantCurvature3D" ); trace.info() << "Args:"; for ( int i = 0; i < argc; ++i ) trace.info() << " " << argv[ i ]; trace.info() << endl; double h = 1.0; unsigned int threshold = atoi( argv[ 2 ] ); /// Construction of the shape from vol file typedef ImageSelector< Z3i::Domain, unsigned int >::Type Image; typedef SimpleThresholdForegroundPredicate< Image > ImagePredicate; typedef Z3i::KSpace::Surfel Surfel; typedef LightImplicitDigitalSurface< Z3i::KSpace, ImagePredicate > MyLightImplicitDigitalSurface; typedef DigitalSurface< MyLightImplicitDigitalSurface > MyDigitalSurface; std::string filename = argv[1]; Image image = VolReader<Image>::importVol( filename ); ImagePredicate predicate = ImagePredicate( image, threshold ); Z3i::Domain domain = image.domain(); Z3i::KSpace KSpaceShape; bool space_ok = KSpaceShape.init( domain.lowerBound(), domain.upperBound(), true ); if (!space_ok) { trace.error() << "Error in the Khalimsky space construction."<<std::endl; return 2; } SurfelAdjacency< Z3i::KSpace::dimension > SAdj( true ); Surfel bel = Surfaces< Z3i::KSpace >::findABel( KSpaceShape, predicate, 100000 ); MyLightImplicitDigitalSurface LightImplDigSurf( KSpaceShape, predicate, SAdj, bel ); MyDigitalSurface digSurf( LightImplDigSurf ); typedef DepthFirstVisitor< MyDigitalSurface > Visitor; typedef GraphVisitorRange< Visitor > VisitorRange; typedef VisitorRange::ConstIterator SurfelConstIterator; VisitorRange range( new Visitor( digSurf, *digSurf.begin() ) ); SurfelConstIterator abegin = range.begin(); SurfelConstIterator aend = range.end(); typedef ImageToConstantFunctor< Image, ImagePredicate > MyPointFunctor; MyPointFunctor pointFunctor( &image, &predicate, 1 ); /// Integral Invariant stuff //! [IntegralInvariantUsage] double re_convolution_kernel = atof(argv[3]); typedef FunctorOnCells< MyPointFunctor, Z3i::KSpace > MyCellFunctor; typedef IntegralInvariantGaussianCurvatureEstimator< Z3i::KSpace, MyCellFunctor > MyCurvatureEstimator; // Gaussian curvature estimator MyCellFunctor functor ( pointFunctor, KSpaceShape ); // Creation of a functor on Cells, returning true if the cell is inside the shape MyCurvatureEstimator estimator ( KSpaceShape, functor ); estimator.init( h, re_convolution_kernel ); // Initialisation for a given Euclidean radius of convolution kernel std::vector< double > results; back_insert_iterator< std::vector< double > > resultsIterator( results ); // output iterator for results of Integral Invariante curvature computation estimator.eval ( abegin, aend, resultsIterator ); // Computation //! [IntegralInvariantUsage] /// Drawing results typedef MyCurvatureEstimator::Quantity Quantity; Quantity min = numeric_limits < Quantity >::max(); Quantity max = numeric_limits < Quantity >::min(); for ( unsigned int i = 0; i < results.size(); ++i ) { if ( results[ i ] < min ) { min = results[ i ]; } else if ( results[ i ] > max ) { max = results[ i ]; } } QApplication application( argc, argv ); Viewer3D<> viewer; viewer.show(); typedef GradientColorMap< Quantity > Gradient; Gradient cmap_grad( min, max ); cmap_grad.addColor( Color( 50, 50, 255 ) ); cmap_grad.addColor( Color( 255, 0, 0 ) ); cmap_grad.addColor( Color( 255, 255, 10 ) ); VisitorRange range2( new Visitor( digSurf, *digSurf.begin() ) ); abegin = range2.begin(); for ( unsigned int i = 0; i < results.size(); ++i ) { viewer << CustomColors3D( Color::Black, cmap_grad( results[ i ] )) << *abegin; ++abegin; } viewer << Viewer3D<>::updateDisplay; trace.endBlock(); return application.exec(); }