32 #include "DGtal/base/Common.h"
33 #include "DGtal/helpers/StdDefs.h"
34 #include "DGtal/topology/helpers/Surfaces.h"
36 #include "DGtal/images/ImageContainerBySTLVector.h"
37 #include "DGtal/io/readers/GenericReader.h"
38 #include "DGtal/io/writers/GenericWriter.h"
40 #include "DGtal/images/IntervalForegroundPredicate.h"
41 #include <DGtal/topology/SetOfSurfels.h>
42 #include "DGtal/topology/DigitalSurface.h"
43 #include "DGtal/topology/helpers/Surfaces.h"
49 using namespace DGtal;
112 std::vector<unsigned int> getHistoFromImage(
const Image3D &image){
114 std::vector<unsigned int> vectHisto(UCHAR_MAX);
116 vectHisto[image(*it)]++;
123 getOtsuThreshold(
const Image3D &image){
124 std::vector<unsigned int> histo = getHistoFromImage(image);
125 unsigned int imageSize = image.
domain().size();
126 unsigned int sumA = 0;
127 unsigned int sumB = imageSize;
130 unsigned int sumMuAll= 0;
131 for(
unsigned int t=0; t< histo.size();t++){
132 sumMuAll+=histo[t]*t;
135 unsigned int thresholdRes=0;
137 for(
unsigned int t=0; t< histo.size(); t++){
148 double muAr=muA/(double)sumA;
149 double muBr=muB/(double)sumB;
150 double sigma= (double)sumA*(
double)sumB*(muAr-muBr)*(muAr-muBr);
160 template<
typename TImageOutput>
162 applySegmentation(TImageOutput &imageResuSegmentation,
const Image3D &inputImage, CLI::Option *labelOpt,
int maxTh,
int minTh) {
166 bool space_ok = K.
init( inputImage.
domain().lowerBound(), inputImage.
domain().upperBound(),
false );
168 trace.
error() <<
"problem initializing 3d space" << endl;
171 std::vector< std::vector<Z3i::SCell > > vectConnectedSCell;
174 for(
unsigned int i = 0; i<vectConnectedSCell.size(); i++)
181 for(std::vector<Z3i::SCell>::const_iterator it= vectConnectedSCell.at(i).begin(); it != vectConnectedSCell.at(i).end(); ++it)
183 aSet.surfelSet().insert(aSet.surfelSet().begin(), *it);
184 unsigned int orth_dir = K.
sOrthDir( *it );
187 if(p1[0] < lowerPoint[0]) lowerPoint[0]= p1[0];
188 if(p1[1] < lowerPoint[1]) lowerPoint[1]= p1[1];
189 if(p1[2] < lowerPoint[2]) lowerPoint[2]= p1[2];
191 if(p1[0] > upperPoint[0]) upperPoint[0]= p1[0];
192 if(p1[1] > upperPoint[1]) upperPoint[1]= p1[1];
193 if(p1[2] > upperPoint[2]) upperPoint[2]= p1[2];
195 if(p2[0] < lowerPoint[0]) lowerPoint[0]= p2[0];
196 if(p2[1] < lowerPoint[1]) lowerPoint[1]= p2[1];
197 if(p2[2] < lowerPoint[2]) lowerPoint[2]= p2[2];
199 if(p2[0] > upperPoint[0]) upperPoint[0]= p2[0];
200 if(p2[1] > upperPoint[1]) upperPoint[1]= p2[1];
201 if(p2[2] > upperPoint[2]) upperPoint[2]= p2[2];
206 kRestr.
init( lowerPoint, upperPoint,
false );
207 if(simplePredicate(p2)){
209 imageResuSegmentation,
211 }
else if (labelOpt->count() > 0){
213 imageResuSegmentation,
225 int main(
int argc,
char** argv )
230 std::string inputFileName;
231 std::string outputFileName {
"result.vol"};
232 bool labelBackground {
false};
235 bool outputTypeInt {
false};
237 app.description(
"Segment volumetric file from a simple threshold which can be set automatically from the otsu estimation.\n The segmentation result is given by an integer label given in the resulting image. Example:\n volSegment ${DGtal}/examples/samples/lobster.vol segmentation.vol \n");
238 app.add_option(
"-i,--input,1", inputFileName,
"volumetric input file (.vol, .pgm, .pgm3d, .longvol)." )
240 ->check(CLI::ExistingFile);
241 app.add_option(
"-o,--output,2", outputFileName,
"volumetric output file (.vol, .pgm, .pgm3d, .longvol)",
true);
243 app.add_flag(
"--outputTypeUInt", outputTypeInt,
"to specify the output image type (unsigned int) instead using the default unsigned char. If this flag is selected you have to check the output file format type (longvol, or an ITK image type if the DGtal WITH_ITK option is selected).");
245 auto labelOpt = app.add_flag(
"--labelBackground",labelBackground,
"option to define a label to regions associated to object background.");
246 app.add_option(
"-m,--thresholdMin",minTh,
"min threshold (if not given the max threshold is computed with Otsu algorithm).",
true );
247 auto maxThOpt = app.add_option(
"-M,--thresholdMax", maxTh,
"max threshold",
true );
250 app.get_formatter()->column_width(40);
251 CLI11_PARSE(app, argc, argv);
254 trace.
info() <<
"Reading input file " << inputFileName ;
256 trace.
info() <<
" [done] " << std::endl ;
258 std::ofstream outStream;
259 outStream.open(outputFileName.c_str());
260 if(maxThOpt->count()==0){
261 maxTh = getOtsuThreshold(inputImage);
262 trace.
info() <<
"maximal threshold value not specified, using Otsu value: " << maxTh << std::endl;
264 trace.
info() <<
"Processing image to output file " << outputFileName << std::endl;
270 applySegmentation(imageResuSegmentation, inputImage, labelOpt, maxTh, minTh);
275 applySegmentation(imageResuSegmentation, inputImage, labelOpt, maxTh, minTh);
int main(int argc, char **argv)
const Domain & domain() const
std::vector< Value >::const_iterator ConstIterator
std::set< SCell > SurfelSet
bool init(const Point &lower, const Point &upper, bool isClosed)
Dimension sOrthDir(const SCell &s) const
SCell sIncident(const SCell &c, Dimension k, bool up) const
Point sCoords(const SCell &c) const
unsigned static int uFillInterior(const KSpace &aKSpace, const TSurfelPredicate &aSurfPred, TImageContainer &anImage, const typename TImageContainer::Value &aValue, bool empty_is_inside=false, bool incrementMode=true)
unsigned static int uFillExterior(const KSpace &aKSpace, const SurfelPredicate &aSurfPred, TImageContainer &anImage, const typename TImageContainer::Value &aValue, bool empty_is_outside=true, bool incrementMode=true)
void progressBar(const double currentValue, const double maximalValue)
Trace trace(traceWriterTerm)
static TContainer import(const std::string &filename, std::vector< unsigned int > dimSpace=std::vector< unsigned int >())