32 #include "DGtal/base/Common.h"
33 #include "DGtal/helpers/StdDefs.h"
34 #include "DGtal/images/ImageContainerBySTLVector.h"
35 #include "DGtal/io/writers/GenericWriter.h"
36 #include "DGtal/io/readers/GenericReader.h"
37 #include "DGtal/images/ConstImageAdapter.h"
38 #include "DGtal/kernel/BasicPointFunctors.h"
43 using namespace DGtal;
99 int main(
int argc,
char** argv )
101 typedef ImageContainerBySTLVector < Z3i::Domain, unsigned char > Image3D;
102 typedef ImageContainerBySTLVector < Z2i::Domain, unsigned char> Image2D;
103 typedef DGtal::ConstImageAdapter<Image3D, Z2i::Domain, DGtal::functors::Point2DEmbedderIn3D<DGtal::Z3i::Domain>,
104 Image3D::Value, DGtal::functors::Identity > ImageAdapterExtractor;
108 std::string inputFileName;
109 std::string outputFileName {
"result.pgm"};
110 int thresholdMin {128};
111 int thresholdMax {255};
112 DGtal::int64_t rescaleInputMin {0};
113 DGtal::int64_t rescaleInputMax {255};
117 unsigned int centerX {0};
118 unsigned int centerY {0};
119 unsigned int centerZ {0};
120 unsigned int heightImageScan {100};
121 unsigned int widthImageScan {100};
122 unsigned int heightFieldMaxScan {255};
123 unsigned int maxScan;
124 bool bgLastDepth =
false;
126 app.description(
"Convert volumetric file into a projected 2D image given from a normal direction N and from a starting point P. The 3D volume is scanned in this normal direction N starting from P with a step 1. If the intensity of the 3d point is inside the given thresholds its 2D gray values are set to the current scan number.\n Example:\n vol2heightfield -i ${DGtal}/examples/samples/lobster.vol -m 60 -M 500 --nx 0 --ny 0.7 --nz -1 -x 150 -y 0 -z 150 --width 300 --height 300 --heightFieldMaxScan 350 -o resultingHeightMap.pgm");
127 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." )
129 ->check(CLI::ExistingFile);
130 app.add_option(
"-o,--output,2", outputFileName,
"resulting image filename (in pgm or other).");
131 app.add_option(
"--thresholdMin,-m", thresholdMin,
"threshold min (excluded) to define binary shape.",
true);
132 app.add_option(
"--thresholdMax,-M", thresholdMax,
"threshold max (included) to define binary shape.",
true);
133 app.add_option(
"--rescaleInputMin", rescaleInputMin,
"min value used to rescale the input intensity (to avoid basic cast into 8 bits image).",
true);
134 app.add_option(
"--rescaleInputMax", rescaleInputMax,
"max value used to rescale the input intensity (to avoid basic cast into 8 bits image).",
true);
136 app.add_option(
"--nx",nx,
"set the x component of the projection direction.",
true);
137 app.add_option(
"--ny",ny,
"set the y component of the projection direction.",
true);
138 app.add_option(
"--nz",nz,
"set the z component of the projection direction.",
true);
139 app.add_option(
"--centerX,-x", centerX,
"choose x center of the projected image.",
true);
140 app.add_option(
"--centerY,-y", centerY,
"choose y center of the projected image.",
true);
141 app.add_option(
"--centerZ,-z", centerZ,
"choose z center of the projected image.",
true);
142 app.add_option(
"--width,-w", widthImageScan,
"set the width of the resulting height Field image.",
true);
143 app.add_option(
"--height", heightImageScan,
"set the height of the resulting height Field image.",
true);
144 app.add_option(
"--heightFieldMaxScan",maxScan,
"set the maximal scan deep.");
145 app.add_flag(
"--setBackgroundLastDepth", bgLastDepth,
"change the default background (black with the last filled intensity).");
148 app.get_formatter()->column_width(40);
149 CLI11_PARSE(app, argc, argv);
153 trace.info() <<
"Reading input file " << inputFileName ;
155 typedef DGtal::functors::Rescaling<DGtal::int64_t ,unsigned char > RescalFCT;
156 Image3D inputImage = GenericReader< Image3D >::importWithValueFunctor( inputFileName,RescalFCT(rescaleInputMin,
160 trace.info() <<
" [done] " << std::endl ;
161 std::ofstream outStream;
162 outStream.open(outputFileName.c_str());
164 trace.info() <<
"Processing image to output file " << outputFileName << std::endl;
166 if(maxScan > std::numeric_limits<Image2D::Value>::max()){
167 maxScan = std::numeric_limits<Image2D::Value>::max();
168 trace.warning()<<
"value --setBackgroundLastDepth outside mox value of image. Set to max value:" << maxScan << std::endl;
172 Image2D::Domain aDomain2D(DGtal::Z2i::Point(0,0),
173 DGtal::Z2i::Point(widthImageScan, heightImageScan));
174 Z3i::Point ptCenter (centerX, centerY, centerZ);
175 Z3i::RealPoint normalDir (nx, ny, nz);
176 Image2D resultingImage(aDomain2D);
178 for(Image2D::Domain::ConstIterator it = resultingImage.domain().begin();
179 it != resultingImage.domain().end(); it++){
180 resultingImage.setValue(*it, 0);
182 DGtal::functors::Identity idV;
184 unsigned int maxDepthFound = 0;
185 for(
unsigned int k=0; k < maxScan; k++){
186 Z3i::Point c (ptCenter+normalDir*k, DGtal::functors::Round<>());
187 DGtal::functors::Point2DEmbedderIn3D<DGtal::Z3i::Domain > embedder(inputImage.domain(),
191 ImageAdapterExtractor extractedImage(inputImage, aDomain2D, embedder, idV);
192 for(Image2D::Domain::ConstIterator it = extractedImage.domain().begin();
193 it != extractedImage.domain().end(); it++){
194 if( resultingImage(*it)== 0 && extractedImage(*it) < thresholdMax &&
195 extractedImage(*it) > thresholdMin){
197 resultingImage.setValue(*it, maxScan-k);
202 for(Image2D::Domain::ConstIterator it = resultingImage.domain().begin();
203 it != resultingImage.domain().end(); it++){
204 if( resultingImage(*it)== 0 ){
205 resultingImage.setValue(*it, maxScan-maxDepthFound);
209 resultingImage >> outputFileName;
210 trace.info() <<
" [done] " << std::endl ;