DGtalTools 2.0.0
Loading...
Searching...
No Matches
3dVolBoundaryViewer.cpp
1
30#include <iostream>
31
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
103int main( int argc, char** argv )
104{
105 typedef SpaceND<3,int> Space;
106 typedef KhalimskySpaceND<3,int> KSpace;
107 typedef HyperRectDomain<Space> Domain;
108 typedef ImageSelector<Domain, unsigned char>::Type Image;
109 typedef DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet;
110 typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
111
112 // parse command line using CLI ----------------------------------------------
113 CLI::App app;
114 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");
115 std::string inputFileName;
116 DGtal::int64_t rescaleInputMin {0};
117 DGtal::int64_t rescaleInputMax {255};
118 int dicomMin {-1000};
119 int dicomMax {3000};
120 int thresholdMin {0};
121 int thresholdMax {255};
122 std::string mode {"INNER"};
123
124 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." )
125 ->required()
126 ->check(CLI::ExistingFile);
127
128 app.add_option("--thresholdMin,-m", thresholdMin, "threshold min (excluded) to define binary shape.");
129 app.add_option("--thresholdMax,-M", thresholdMax, "threshold max (included) to define binary shape.");
130#ifdef DGTAL_WITH_ITK
131 app.add_option("--dicomMin",dicomMin,"set minimum density threshold on Hounsfield scale" );
132 app.add_option("--dicomMax",dicomMin,"set maximum density threshold on Hounsfield scale" );
133#endif
134 app.add_option("--mode", mode,"set mode for display: INNER: inner voxels, OUTER: outer voxels, BDRY: surfels" )
135 -> check(CLI::IsMember({"INNER", "OUTER", "BDRY"}));
136
137
138 app.get_formatter()->column_width(40);
139 CLI11_PARSE(app, argc, argv);
140 // END parse command line using CLI ----------------------------------------------
141
142
143 string extension = inputFileName.substr(inputFileName.find_last_of(".") + 1);
144 if(extension!="vol" && extension != "p3d" && extension != "pgm3D" && extension != "pgm3d" && extension != "sdp" && extension != "pgm"
145#ifdef DGTAL_WITH_ITK
146 && extension !="dcm"
147#endif
148 ){
149 trace.info() << "File extension not recognized: "<< extension << std::endl;
150 return 0;
151 }
152
153 if(extension=="vol" || extension=="pgm3d" || extension=="pgm3D"
154#ifdef DGTAL_WITH_ITK
155 || extension =="dcm"
156#endif
157 ){
158 trace.beginBlock( "Loading image into memory." );
159#ifdef DGTAL_WITH_ITK
160 typedef DGtal::functors::Rescaling<int ,unsigned char > RescalFCT;
161 Image image = extension == "dcm" ? DicomReader< Image, RescalFCT >::importDicom( inputFileName,
162 RescalFCT(dicomMin,
163 dicomMax,
164 0, 255) ) :
165 GenericReader<Image>::import( inputFileName );
166#else
167 Image image = GenericReader<Image>::import (inputFileName );
168#endif
169 trace.info() << "Image loaded: "<<image<< std::endl;
170 trace.endBlock();
171
173 trace.beginBlock( "Construct the Khalimsky space from the image domain." );
174 Domain domain = image.domain();
175 KSpace ks;
176 bool space_ok = ks.init( domain.lowerBound(), domain.upperBound(), true );
177 if (!space_ok)
178 {
179 trace.error() << "Error in the Khamisky space construction."<<std::endl;
180 return 2;
181 }
182 trace.endBlock();
184
186 trace.beginBlock( "Wrapping a digital set around image. " );
187 typedef functors::IntervalForegroundPredicate<Image> ThresholdedImage;
188 ThresholdedImage thresholdedImage( image, thresholdMin, thresholdMax );
189 trace.endBlock();
191
193 trace.beginBlock( "Extracting boundary by scanning the space. " );
194 typedef KSpace::SurfelSet SurfelSet;
195 typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
196 typedef DigitalSurface< MySetOfSurfels > MyDigitalSurface;
197 MySurfelAdjacency surfAdj( true ); // interior in all directions.
198 MySetOfSurfels theSetOfSurfels( ks, surfAdj );
199 Surfaces<KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
200 ks, thresholdedImage,
201 domain.lowerBound(),
202 domain.upperBound() );
203 MyDigitalSurface digSurf( theSetOfSurfels );
204 trace.info() << "Digital surface has " << digSurf.size() << " surfels."
205 << std::endl;
206 trace.endBlock();
208
210 trace.beginBlock( "Displaying everything. " );
211 PolyscopeViewer<Space,KSpace> viewer(ks);
212 viewer.allowReuseList = true;
213 typedef MyDigitalSurface::ConstIterator ConstIterator;
214 if ( mode == "BDRY" )
215 {
216 viewer.drawAsSimplified();
217 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
218 viewer << ks.unsigns( *it );
219 }else if ( mode == "INNER" )
220 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
221 viewer << ks.sCoords( ks.sDirectIncident( *it, ks.sOrthDir( *it ) ) );
222 else if ( mode == "OUTER" )
223 for ( ConstIterator it = digSurf.begin(), itE = digSurf.end(); it != itE; ++it )
224 viewer << ks.sCoords( ks.sIndirectIncident( *it, ks.sOrthDir( *it ) ) );
225 else{
226 trace.error() << "Warning display mode (" << mode << ") not implemented." << std::endl;
227 trace.error() << "The display will be empty." << std::endl;
228 }
229 trace.endBlock();
230 viewer.show();
231 }
232 return 0;
233}
Definition ATu0v1.h:57