31 #include "DGtal/base/Common.h"
32 #include "DGtal/helpers/StdDefs.h"
33 #include <boost/format.hpp>
35 #include "DGtal/io/readers/GenericReader.h"
36 #include "DGtal/io/writers/GenericWriter.h"
37 #include "DGtal/images/ConstImageAdapter.h"
38 #include "DGtal/kernel/BasicPointFunctors.h"
43 using namespace DGtal;
95 int main(
int argc,
char** argv )
97 typedef ImageContainerBySTLVector < Z3i::Domain, unsigned char > Image3D;
98 typedef ImageContainerBySTLVector < Z2i::Domain, unsigned char > Image2D;
99 typedef DGtal::ConstImageAdapter<Image3D, Image2D::Domain, DGtal::functors::Projector< DGtal::Z3i::Space>,
100 Image3D::Value, DGtal::functors::Identity > SliceImageAdapter;
105 std::string inputFileName;
106 std::string outputFileName =
"result.pgm";
107 DGtal::int64_t rescaleInputMin {0};
108 DGtal::int64_t rescaleInputMax {255};
109 int userStartSlice {0};
111 unsigned int sliceOrientation {2};
114 app.description(
"Convert a volumetric file (.vol, .longvol, .pgm3d) into a set of 2D slice images. \n Typical use: to extract all slices defined in Y plane (y=cst): \n vol2slice image3d.vol slice.pgm -s 1 \n");
116 app.add_option(
"-i,--input,1", inputFileName,
"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.")
118 ->check(CLI::ExistingFile);
120 app.add_option(
"--output,-o,2",outputFileName ,
"base_name.extension: extracted 2D slice volumetric files (will result n files base_name_xxx.extension)",
true);
121 app.add_option(
"--setFirstSlice,-f", userStartSlice,
"Set the first slice index to be extracted.",
true)
122 -> check(CLI::Number);
123 app.add_option(
"--setLastSlice,-l", userEndSlice,
"Set the last slice index to be extracted (by default set to maximal value according to the given volume).")
124 -> check(CLI::Number);
125 app.add_option(
"--sliceOrientation,-s", sliceOrientation,
"specify the slice orientation for which the slice are defined (by default =2 (Z direction))",
true)
126 -> check(CLI::IsMember({0, 1, 2}));
127 app.add_option(
"--rescaleInputMin", rescaleInputMin,
"min value used to rescale the input intensity (to avoid basic cast into 8 bits image).",
true);
128 app.add_option(
"--rescaleInputMax", rescaleInputMax,
"max value used to rescale the input intensity (to avoid basic cast into 8 bits image).",
true);
129 app.get_formatter()->column_width(40);
131 CLI11_PARSE(app, argc, argv);
133 std::string outputExt = outputFileName.substr(outputFileName.find_last_of(
".")+1);
134 std::string outputBasename = outputFileName.substr(0, outputFileName.find_last_of(
"."));
137 trace.info()<<
"Importing volume file base name: " << outputBasename <<
" extension: " << outputExt <<
" ..." ;
138 typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
139 Image3D input3dImage = GenericReader< Image3D >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
143 trace.info()<<
"[done]" << endl;
145 unsigned int startSlice=0;
146 unsigned int endSlice=input3dImage.domain().upperBound()[sliceOrientation];
148 if(userStartSlice !=0){
149 startSlice = userStartSlice;
151 if(userEndSlice != 0){
152 endSlice = userEndSlice;
156 #pragma omp parallel for schedule(dynamic)
157 for(
unsigned int i=startSlice; i <= endSlice; i++){
158 trace.info() <<
"Exporting slice image "<< i ;
159 DGtal::functors::Projector<DGtal::Z2i::Space> invFunctor; invFunctor.initRemoveOneDim(sliceOrientation);
160 DGtal::Z2i::Domain domain2D(invFunctor(input3dImage.domain().lowerBound()),
161 invFunctor(input3dImage.domain().upperBound()));
162 DGtal::functors::Projector<DGtal::Z3i::Space> aSliceFunctor(i); aSliceFunctor.initAddOneDim(sliceOrientation);
163 const DGtal::functors::Identity identityFunctor{};
164 SliceImageAdapter sliceImage( input3dImage, domain2D, aSliceFunctor, identityFunctor );
165 stringstream outName; outName << outputBasename <<
"_" << boost::format(
"%|05|")% i <<
"."<< outputExt ;
166 trace.info() <<
": "<< outName.str() ;
167 GenericWriter<SliceImageAdapter>::exportFile(outName.str(), sliceImage);
168 trace.info() <<
" [done]"<< endl;