33 #include <boost/program_options/options_description.hpp>
34 #include <boost/program_options/parsers.hpp>
35 #include <boost/program_options/variables_map.hpp>
37 #include "DGtal/base/Common.h"
38 #include "DGtal/base/BasicFunctors.h"
39 #include "DGtal/kernel/SpaceND.h"
40 #include "DGtal/kernel/domains/HyperRectDomain.h"
41 #include "DGtal/images/ImageSelector.h"
42 #include "DGtal/images/IntervalForegroundPredicate.h"
43 #include "DGtal/topology/KhalimskySpaceND.h"
44 #include "DGtal/topology/DigitalSurface.h"
45 #include "DGtal/topology/SetOfSurfels.h"
46 #include "DGtal/io/boards/Board3D.h"
47 #include "DGtal/io/readers/PointListReader.h"
48 #include "DGtal/io/readers/GenericReader.h"
50 #include "DGtal/io/readers/DicomReader.h"
52 #include "DGtal/io/Color.h"
53 #include "DGtal/io/colormaps/GradientColorMap.h"
57 using namespace DGtal;
61 namespace po = boost::program_options;
111 int main(
int argc,
char** argv )
120 po::options_description general_opt(
"Allowed options are: ");
121 general_opt.add_options()
122 (
"help,h",
"display this message")
123 (
"input,i", po::value<std::string>(),
"vol file (.vol, .longvol .p3d, .pgm3d and if WITH_ITK is selected: dicom, dcm, mha, mhd). For longvol, dicom, dcm, mha or mhd formats, the input values are linearly scaled between 0 and 255." )
124 (
"output,o", po::value<std::string>(),
"output obj file (.obj)" )
125 (
"thresholdMin,m", po::value<int>()->default_value(0),
"threshold min (excluded) to define binary shape" )
126 (
"thresholdMax,M", po::value<int>()->default_value(255),
"threshold max (included) to define binary shape" )
127 (
"rescaleInputMin", po::value<DGtal::int64_t>()->default_value(0),
"min value used to rescale the input intensity (to avoid basic cast into 8 bits image).")
128 (
"rescaleInputMax", po::value<DGtal::int64_t>()->default_value(255),
"max value used to rescale the input intensity (to avoid basic cast into 8 bits image).")
129 (
"mode", po::value<std::string>()->default_value(
"BDRY"),
"set mode for display: INNER: inner voxels, OUTER: outer voxels, BDRY: surfels (default), CLOSURE: surfels with linels and pointels.")
130 (
"normalization,n",
"Normalization so that the geometry fits in [-1/2,1/2]^3") ;
133 po::variables_map vm;
135 po::store(po::parse_command_line(argc, argv, general_opt), vm);
136 }
catch(
const std::exception& ex){
138 trace.
info()<<
"Error checking program options: "<< ex.what()<< endl;
141 if( !parseOK || vm.count(
"help")||argc<=1)
143 std::cout <<
"Usage: " << argv[0] <<
" -i [input] -o [output]\n"
144 <<
"Export the boundary of a volume file to OBJ format. The mode specifies if you wish to see surface elements (BDRY), the inner voxels (INNER) or the outer voxels (OUTER) that touch the boundary."<< endl
145 << general_opt <<
"\n";
149 if(! vm.count(
"input"))
151 trace.
error() <<
" The file name was defined" << endl;
155 if(! vm.count(
"output"))
157 trace.
error() <<
" The output filename was defined" << endl;
161 string inputFilename = vm[
"input"].as<std::string>();
162 int thresholdMin = vm[
"thresholdMin"].as<
int>();
163 int thresholdMax = vm[
"thresholdMax"].as<
int>();
164 string mode = vm[
"mode"].as<
string>();
165 bool normalization =
false;
166 if (vm.count(
"normalization"))
167 normalization =
true;
177 trace.
info() <<
"Image loaded: "<<image<< std::endl;
180 trace.
beginBlock(
"Construct the Khalimsky space from the image domain." );
181 Domain domain = image.
domain();
183 bool space_ok = ks.
init( domain.lowerBound(), domain.upperBound(), true );
186 trace.
error() <<
"Error in the Khamisky space construction."<<std::endl;
193 ThresholdedImage thresholdedImage( image, thresholdMin, thresholdMax );
200 MySurfelAdjacency surfAdj(
true );
201 MySetOfSurfels theSetOfSurfels( ks, surfAdj );
203 ks, thresholdedImage,
205 domain.upperBound() );
206 MyDigitalSurface digSurf( theSetOfSurfels );
207 trace.
info() <<
"Digital surface has " << digSurf.size() <<
" surfels."
215 board <<
SetMode3D( (*digSurf.begin()).className(),
"Basic" );
217 typedef MyDigitalSurface::ConstIterator ConstIterator;
218 if ( mode ==
"BDRY" )
219 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
231 n = sc -
Z3i::RealPoint(static_cast<Z3i::RealPoint::Component>(ip[0]),
232 static_cast<Z3i::RealPoint::Component>(ip[1]),
233 static_cast<Z3i::RealPoint::Component>(ip[2]));
234 bool xodd = ks.
sIsOpen( *it, 0 );
235 bool yodd = ks.
sIsOpen( *it, 1 );
236 bool zodd = ks.
sIsOpen( *it, 2 );
237 board.addQuadFromSurfelCenterWithNormal
238 (
Z3i::RealPoint( sc[0]+(xodd? 0:0.5 ), sc[1]+(yodd? 0:0.5 ), sc[2]+(zodd? 0:0.5 ) ),
239 ! xodd, ! yodd, ! zodd, n,
true,
true,
false );
241 else if ( mode ==
"INNER" )
242 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
244 else if ( mode ==
"OUTER" )
245 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
247 else if (mode ==
"CLOSURE")
249 std::set<KSpace::Cell> container;
250 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
252 container.insert( ks.
unsigns( *it ) );
255 for(KSpace::SCells::ConstIterator itt = oneNeig.begin(), ittend = oneNeig.end(); itt != ittend; ++itt)
257 container.insert( ks.
unsigns( *itt) );
260 for(KSpace::SCells::ConstIterator ittt = oneNeig2.begin(), itttend = oneNeig2.end(); ittt != itttend; ++ittt)
261 container.insert( ks.
unsigns(*ittt) );
264 trace.
info()<<
"Exporting "<< container.size() <<
" cells"<<std::endl;
265 for(
auto cell: container)
269 string outputFilename = vm[
"output"].as<std::string>();
271 board.saveOBJ(outputFilename, normalization);
void beginBlock(const std::string &keyword="")
SpaceND< 2, Integer > Space
std::set< SCell > SurfelSet
SCells sLowerIncident(const SCell &c) const
SCell sDirectIncident(const SCell &p, Dimension k) const
const Point & lowerBound() const
Dimension sOrthDir(const SCell &s) const
bool init(const Point &lower, const Point &upper, bool isClosed)
Point sCoords(const SCell &c) const
Trace trace(traceWriterTerm)
SCell sIndirectIncident(const SCell &p, Dimension k) const
const Domain & domain() const
Cell unsigns(const SCell &p) const
bool sIsOpen(const SCell &p, Dimension k) const
AnyCellCollection< SCell > SCells
typename Self::Domain Domain