DGtalTools 2.1.0
Loading...
Searching...
No Matches
3dVolBoundaryViewer.cpp
1
30#include <iostream>
31#include <sstream>
32#include "DGtal/base/Common.h"
33#include "DGtal/base/BasicFunctors.h"
34#include "DGtal/kernel/SpaceND.h"
35#include "DGtal/kernel/domains/HyperRectDomain.h"
36#include "DGtal/images/ImageSelector.h"
37#include "DGtal/images/IntervalForegroundPredicate.h"
38#include "DGtal/topology/KhalimskySpaceND.h"
39#include "DGtal/topology/DigitalSurface.h"
40#include "DGtal/topology/SetOfSurfels.h"
41#include "DGtal/io/viewers/PolyscopeViewer.h"
42#include "DGtal/io/readers/PointListReader.h"
43#include "DGtal/io/readers/GenericReader.h"
44#ifdef DGTAL_WITH_ITK
45#include "DGtal/io/readers/DicomReader.h"
46#endif
47#include "DGtal/io/Color.h"
48#include "DGtal/io/colormaps/GradientColorMap.h"
49
50#include "CLI11.hpp"
51
52
53using namespace std;
54using namespace DGtal;
55
56
104int main( int argc, char** argv )
105{
106 typedef SpaceND<3,int> Space;
107 typedef KhalimskySpaceND<3,int> KSpace;
108 typedef HyperRectDomain<Space> Domain;
109 typedef ImageSelector<Domain, unsigned char>::Type Image;
110 typedef DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet;
111 typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
112
113 // parse command line using CLI ----------------------------------------------
114 CLI::App app;
115 app.description("Display the boundary of a volume file by using PolyscopeViewer. The mode specifies if you wish to see surface elements (BDRY), the inner voxels (INNER) or the outer voxels (OUTER) that touch the boundary. \n \t Example: 3dVolBoundaryViewer $DGtal/examples/samples/lobster.vol -m 60");
116 std::string inputFileName;
117 DGtal::int64_t rescaleInputMin {0};
118 DGtal::int64_t rescaleInputMax {255};
119 int dicomMin {-1000};
120 int dicomMax {3000};
121 int thresholdMin {0};
122 int thresholdMax {255};
123 std::string mode {"INNER"};
124
125 app.add_option("-i,--input,1", inputFileName, "vol file (.vol, .longvol .p3d, .pgm3d and if DGTAL_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." )
126 ->required()
127 ->check(CLI::ExistingFile);
128
129 app.add_option("--thresholdMin,-m", thresholdMin, "threshold min (excluded) to define binary shape.");
130 app.add_option("--thresholdMax,-M", thresholdMax, "threshold max (included) to define binary shape.");
131#ifdef DGTAL_WITH_ITK
132 app.add_option("--dicomMin",dicomMin,"set minimum density threshold on Hounsfield scale" );
133 app.add_option("--dicomMax",dicomMin,"set maximum density threshold on Hounsfield scale" );
134#endif
135 app.add_option("--mode", mode,"set mode for display: INNER: inner voxels, OUTER: outer voxels, BDRY: surfels" )
136 -> check(CLI::IsMember({"INNER", "OUTER", "BDRY"}));
137
138
139 app.get_formatter()->column_width(40);
140 CLI11_PARSE(app, argc, argv);
141 // END parse command line using CLI ----------------------------------------------
142
143
144 string extension = inputFileName.substr(inputFileName.find_last_of(".") + 1);
145 if(extension!="vol" && extension != "p3d" && extension != "pgm3D" && extension != "pgm3d" && extension != "sdp" && extension != "pgm"
146#ifdef DGTAL_WITH_ITK
147 && extension !="dcm"
148#endif
149 ){
150 trace.info() << "File extension not recognized: "<< extension << std::endl;
151 return 0;
152 }
153
154 if(extension=="vol" || extension=="pgm3d" || extension=="pgm3D"
155#ifdef DGTAL_WITH_ITK
156 || extension =="dcm"
157#endif
158 ){
159 trace.beginBlock( "Loading image into memory." );
160#ifdef DGTAL_WITH_ITK
161 typedef DGtal::functors::Rescaling<int ,unsigned char > RescalFCT;
162 Image image = extension == "dcm" ? DicomReader< Image, RescalFCT >::importDicom( inputFileName,
163 RescalFCT(dicomMin,
164 dicomMax,
165 0, 255) ) :
166 GenericReader<Image>::import( inputFileName );
167#else
168 Image image = GenericReader<Image>::import (inputFileName );
169#endif
170 trace.info() << "Image loaded: "<<image<< std::endl;
171 trace.endBlock();
172
174 trace.beginBlock( "Construct the Khalimsky space from the image domain." );
175 Domain domain = image.domain();
176 KSpace ks;
177 bool space_ok = ks.init( domain.lowerBound(), domain.upperBound(), true );
178 if (!space_ok)
179 {
180 trace.error() << "Error in the Khamisky space construction."<<std::endl;
181 return 2;
182 }
183 trace.endBlock();
185
187 trace.beginBlock( "Wrapping a digital set around image. " );
188 typedef functors::IntervalForegroundPredicate<Image> ThresholdedImage;
189 ThresholdedImage thresholdedImage( image, thresholdMin, thresholdMax );
190 trace.endBlock();
192
194 trace.beginBlock( "Extracting boundary by scanning the space. " );
195 typedef KSpace::SurfelSet SurfelSet;
196 typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
197 typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface;
198 MySurfelAdjacency surfAdj( true ); // interior in all directions.
199 MySetOfSurfels theSetOfSurfels( ks, surfAdj );
200 Surfaces<KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
201 ks, thresholdedImage,
202 domain.lowerBound(),
203 domain.upperBound() );
204 MyDigitalSurface digSurf( theSetOfSurfels );
205 trace.info() << "Digital surface has " << digSurf.size() << " surfels."
206 << std::endl;
207 trace.endBlock();
209
211 trace.beginBlock( "Displaying everything. " );
212 stringstream s;
213 s << "3dVolBoundaryViewer - DGtalTools: ";
214 string name = inputFileName.substr(inputFileName.find_last_of("/")+1,inputFileName.size()) ;
215 s << " " << name ;
216 polyscope::options::programName = s.str();
217 polyscope::options::groundPlaneMode = polyscope::GroundPlaneMode::None;
218 polyscope::view::setNavigateStyle(polyscope::NavigateStyle::Free);
219
220 PolyscopeViewer<Space,KSpace> viewer(ks);
221 viewer.allowReuseList = true;
222 typedef MyDigitalSurface::ConstIterator ConstIterator;
223 if ( mode == "BDRY" )
224 {
225 viewer.drawAsSimplified();
226 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
227 viewer << ks.unsigns( *it );
228 }else if ( mode == "INNER" )
229 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
230 viewer << ks.sCoords( ks.sDirectIncident( *it, ks.sOrthDir( *it ) ) );
231 else if ( mode == "OUTER" )
232 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
233 viewer << ks.sCoords( ks.sIndirectIncident( *it, ks.sOrthDir( *it ) ) );
234 else{
235 trace.error() << "Warning display mode (" << mode << ") not implemented." << std::endl;
236 trace.error() << "The display will be empty." << std::endl;
237 }
238 trace.endBlock();
239 viewer.show();
240 }
241 return 0;
242}
Definition ATu0v1.h:57