DGtalTools 2.0.0
Loading...
Searching...
No Matches
volMask.cpp
1
32#include "DGtal/base/Common.h"
33#include <DGtal/helpers/StdDefs.h>
34#include <DGtal/images/ImageContainerBySTLVector.h>
35
36#include <DGtal/io/readers/GenericReader.h>
37#include <DGtal/io/writers/GenericWriter.h>
38
39#include "CLI11.hpp"
40
41#ifdef DGTAL_WITH_ITK
42#include "DGtal/io/readers/ITKReader.h"
43#include "DGtal/io/writers/ITKWriter.h"
44
45#endif
46
48using namespace std;
49using namespace DGtal;
51
93typedef ImageContainerBySTLVector < Z3i::Domain, unsigned char > Image3D;
94#ifdef DGTAL_WITH_ITK
95typedef ImageContainerBySTLVector < Z3i::Domain, double > Image3D_D;
96typedef ImageContainerBySTLVector < Z3i::Domain, int > Image3D_I;
97#endif
98
103template<typename TImage, typename TImageMask>
104typename TImageMask::Domain
105subDomainMasked(const TImage &image, const TImageMask &maskImage,
106 typename TImageMask::Value maskValue, unsigned int domainOffset=1){
107 typename TImageMask::Domain res;
108 Z3i::Point minP = image.domain().upperBound();
109 Z3i::Point maxP = image.domain().lowerBound();
110
111 Z3i::Point::Iterator minIt;
112 Z3i::Point::Iterator maxIt;
113 bool foundMaskedVal = false;
114 for(const auto &p: image.domain())
115 {
116 minIt = minP.begin();
117 maxIt = maxP.begin();
118 if( maskImage.domain().isInside(p) && maskImage(p) == maskValue ) // no noise on mask image
119 {
120 foundMaskedVal=true;
121 for(auto pIt=p.begin(); pIt!=p.end();pIt++ )
122 {
123 if( *pIt < *minIt ){*minIt = *pIt;}
124 if( *pIt > *maxIt ){*maxIt = *pIt;}
125 minIt++;
126 maxIt++;
127 }
128 }
129 }
130 if (!foundMaskedVal)
131 {
132 trace.info() << "No masked value found resulting image will be empty." << std::endl;
133 return image.domain();
134
135 }
136 // offset to avoid problems on borders
137 Z3i::Point offset(domainOffset,domainOffset,domainOffset);
138 minP -= offset;
139 maxP += offset;
140 trace.info() << "sub-domain:" << minP << " " << maxP << std::endl;
141 return typename TImageMask::Domain(minP, maxP);
142}
143
144
145template<typename TImage, typename TImageMask>
146void
147applyMask(const TImage &inputImage,TImage &outputImage,
148 const TImageMask &maskImage, typename TImageMask::Value maskValue)
149{
150 for (const auto &p: outputImage.domain())
151 {
152 if (inputImage.domain().isInside(p) && maskImage(p) == maskValue)
153 {
154 outputImage.setValue(p, inputImage(p) );
155 }
156 }
157
158}
159
160template<typename TImage, typename TImageMask>
161void
162processImage(const TImage &inputImage, const TImageMask &maskImage,
163 typename TImageMask::Value maskValue, std::string outputFileName, unsigned int offsetBorder ){
164 // First step getting the bounding box of the domain:
165 auto subDm = subDomainMasked(inputImage, maskImage, maskValue, offsetBorder);
166 TImage outputImage( subDm );
167 // Second step: masking source image
168 applyMask(inputImage, outputImage, maskImage, maskValue);
169 trace.info() << "writing output image...";
170 GenericWriter<TImage>::exportFile(outputFileName, outputImage);
171}
172
173
174int main( int argc, char** argv )
175{
176
177 // parse command line using CLI ----------------------------------------------
178 CLI::App app;
179 std::string inputFileName;
180 std::string outputFileName {"result.vol"};
181 std::string inputType;
182 std::string maskFileName;
183 unsigned int offsetBorder {0};
184 int maskValue {1};
185
186 app.description("Outputs a new image from two input images, one representing the data, one representing the selection mask. The size of output image is the size of the bounding box of selected values, plus the chosen border offset. \n Typical use example:\n \t volMask ${DGtal}/examples/samples/lobster.vol lobsMasked.vol -a ${DGtal}/examples/samples/lobster.vol -m 100 \n");
187
188#ifdef DGTAL_WITH_ITK
189 app.add_option("-i,--input,1", inputFileName, "an input 3D image vol (or ITK: .nii, mha, ... ) file." )
190 ->required()
191 ->check(CLI::ExistingFile);
192 app.add_option("--inputType,-t",inputType, "to specify the input image type (int or double).");
193
194 #else
195 app.add_option("-i,--input,1", inputFileName, "an input vol file." )
196 ->required()
197 ->check(CLI::ExistingFile);
198#endif
199
200 app.add_option("--mask,-a",maskFileName, "the mask image that represents the elements that are copied as output in the resulting image (by default set to 1 you can change this value by using --maskValue). ")
201 ->check(CLI::ExistingFile);
202 app.add_option("-o,--output,2", outputFileName, "the output masked image." );
203 app.add_option("--offsetBorder,-f", offsetBorder, "add a border offset to the bounding box of the masked value domain.");
204 app.add_option("--maskValue,-m", maskValue, "the masking value.");
205 app.get_formatter()->column_width(40);
206 CLI11_PARSE(app, argc, argv);
207 // END parse command line using CLI ----------------------------------------------
208
209
210
211 trace.info() << "Reading mask image...";
212 Image3D maskImage = DGtal::GenericReader<Image3D>::import(maskFileName);
213 trace.info() << "[done]"<< std::endl;
214 trace.info() << "Reading input image...";
215#ifdef DGTAL_WITH_ITK
216 if (inputType=="double")
217 {
218 Image3D_D inputImage = DGtal::GenericReader<Image3D_D>::import(inputFileName);
219 trace.info() << "[done]"<< std::endl;
220 processImage(inputImage, maskImage, maskValue, outputFileName, offsetBorder);
221 }
222 else if (inputType=="int")
223 {
224 Image3D_I inputImage = DGtal::GenericReader<Image3D_I>::import(inputFileName);
225 trace.info() << "[done]"<< std::endl;
226 processImage(inputImage, maskImage, maskValue, outputFileName, offsetBorder);
227 }
228 else
229 {
230 Image3D inputImage = DGtal::GenericReader<Image3D>::import(inputFileName);
231 trace.info() << "[done]"<< std::endl;
232 processImage(inputImage, maskImage, maskValue, outputFileName, offsetBorder);
233 }
234#else
235 Image3D inputImage = DGtal::GenericReader<Image3D>::import(inputFileName);
236 processImage(inputImage, maskImage, maskValue, outputFileName, offsetBorder);
237#endif
238
239 trace.info() << "[Done]" << std::endl;
240 return 0;
241}
242
Definition ATu0v1.h:57