33 #include <boost/program_options/options_description.hpp>
34 #include <boost/program_options/parsers.hpp>
35 #include <boost/program_options/variables_map.hpp>
36 #include <DGtal/kernel/sets/SetPredicate.h>
37 #include <DGtal/io/readers/VolReader.h>
38 #include <DGtal/images/ImageSelector.h>
39 #include <DGtal/images/SimpleThresholdForegroundPredicate.h>
40 #include <DGtal/images/ImageLinearCellEmbedder.h>
41 #include <DGtal/shapes/Shapes.h>
42 #include <DGtal/kernel/CanonicEmbedder.h>
43 #include <DGtal/helpers/StdDefs.h>
44 #include <DGtal/topology/helpers/Surfaces.h>
45 #include <DGtal/topology/DigitalSurface.h>
46 #include <DGtal/topology/SetOfSurfels.h>
47 #include <DGtal/geometry/volumes/KanungoNoise.h>
52 using namespace DGtal;
54 namespace po = boost::program_options;
115 int main(
int argc,
char** argv )
119 po::options_description general_opt(
"Allowed options are ");
120 general_opt.add_options()
121 (
"help,h",
"display this message")
122 (
"input,i", po::value<std::string>(),
"the volume file (.vol)" )
123 (
"threshold,t", po::value<unsigned int>()->default_value(1),
"the value that defines the isosurface in the image (an integer between 0 and 255)." )
124 (
"adjacency,a", po::value<unsigned int>()->default_value(0),
"0: interior adjacency, 1: exterior adjacency")
125 (
"output,o", po::value<std::string>()->default_value(
"marching-cubes.off" ),
"the output OFF file that represents the geometry of the isosurface")
126 (
"noise,n", po::value<double>(),
"Kanungo noise level in ]0,1[. Note that only the largest connected component is considered and that no specific embedder is used.");
130 po::variables_map vm;
132 po::store(po::parse_command_line(argc, argv, general_opt), vm);
133 }
catch(
const std::exception& ex){
135 trace.
info()<<
"Error checking program options: "<< ex.what()<< std::endl;
138 if ( !parseOK || vm.count(
"help") || ( argc <= 1 ) )
140 std::cout <<
"Usage: " << argv[0]
141 <<
" [-i <fileName.vol>] [-t <threshold>] [-a <adjacency>] [-o <output.off>]" << std::endl
142 <<
"Outputs the isosurface of value <threshold> of the volume <fileName.vol> as an OFF file <output.off>. The <adjacency> (0/1) allows to choose between interior (6,18) and exterior (18,6) adjacency." << std::endl
143 << general_opt << std::endl;
146 if ( ! vm.count(
"input") )
148 trace.
error() <<
"The input file name was defined." << std::endl;
151 std::string inputFilename = vm[
"input"].as<std::string>();
152 unsigned int threshold = vm[
"threshold"].as<
unsigned int>();
153 bool intAdjacency = ( vm[
"adjacency"].as<
unsigned int>() == 0 );
154 std::string outputFilename = vm[
"output"].as<std::string>();
157 if (vm.count(
"noise") )
160 noise = vm[
"noise"].as<
double>();
170 ThresholdedImage thresholdedImage( image, threshold );
176 trace.
beginBlock(
"Construct the Khalimsky space from the image domain." );
182 trace.
error() <<
"Error in the Khamisky space construction."<<std::endl;
190 MySurfelAdjacency surfAdj( intAdjacency );
198 MySetOfSurfels theSetOfSurfels( ks, surfAdj );
202 trace.
info()<<
"Adding some noise."<<std::endl;
204 std::vector< std::vector<SCell > > vectConnectedSCell;
205 trace.
info()<<
"Extracting all connected components."<<std::endl;
208 if( vectConnectedSCell.size() == 0 )
210 trace.
error()<<
"No surface component exists. Please check the vol file --min and --max parameters." << std::endl;
214 trace.
info()<<vectConnectedSCell.size()<<
" components."<<std::endl;
216 trace.
info()<<
"Extracting the largest one."<<std::endl;
217 int cc_max_size_idx = -1;
218 auto it_max = std::max_element( vectConnectedSCell.begin(), vectConnectedSCell.end(),
219 [] (std::vector<SCell >& v1, std::vector<SCell >& v2)
220 {
return v1.size() < v2.size(); } );
221 cc_max_size_idx = std::distance( vectConnectedSCell.begin(), it_max );
222 theSetOfSurfels.surfelSet().insert( vectConnectedSCell[ cc_max_size_idx ].begin(),
223 vectConnectedSCell[ cc_max_size_idx ].end() );
227 theSetOfSurfels.surfelSet(), ks, thresholdedImage,
230 MyDigitalSurface digSurf( theSetOfSurfels );
231 trace.
info() <<
"Digital surface has " << digSurf.size() <<
" surfels."
243 CellEmbedder cellEmbedder;
244 MyEmbedder trivialEmbedder;
252 for(
auto p: image.
domain())
253 largerImage.setValue( p, image(p));
255 std::ofstream out( outputFilename.c_str() );
259 digSurf.exportSurfaceAs3DOFF( out );
262 trace.
error()<<
"IO error while opening the output file"<<std::endl;
268 cellEmbedder.init( ks, image, trivialEmbedder,
269 ( (
double) threshold ) + 0.5 );
272 digSurf.exportEmbeddedSurfaceAs3DOFF( out, cellEmbedder );
274 trace.
error()<<
"IO error while opening the output file"<<std::endl;
void beginBlock(const std::string &keyword="")
static Self diagonal(Component val=1)
HyperRectDomain< Space > Domain
std::set< SCell > SurfelSet
static void sMakeBoundary(SCellSet &aBoundary, const KSpace &aKSpace, const PointPredicate &pp, const Point &aLowerBound, const Point &aUpperBound)
static ImageContainer importVol(const std::string &filename, const Functor &aFunctor=Functor())
bool init(const Point &lower, const Point &upper, bool isClosed)
static void extractAllConnectedSCell(std::vector< std::vector< SCell > > &aVectConnectedSCell, const KSpace &aKSpace, const SurfelAdjacency< KSpace::dimension > &aSurfelAdj, const PointPredicate &pp, bool forceOrientCellExterior=false)
const Point & upperBound() const
Trace trace(traceWriterTerm)
const Domain & domain() const
const Point & lowerBound() const