DGtalTools  1.3.beta
volAddNoise.cpp
1 
27 #include <DGtal/base/Common.h>
28 #include "DGtal/io/readers/GenericReader.h"
29 #include "DGtal/io/writers/GenericWriter.h"
30 #include "DGtal/images/ImageContainerBySTLVector.h"
31 #include "DGtal/images/ImageSelector.h"
32 #include <DGtal/geometry/volumes/KanungoNoise.h>
33 #include <DGtal/images/IntervalForegroundPredicate.h>
34 
35 #include "CLI11.hpp"
36 
37 // Max component option
38 #include <boost/pending/disjoint_sets.hpp>
39 
40 #include <vector>
41 #include <string>
42 #include <climits>
43 
44 using namespace DGtal;
45 
46 
94 void missingParam( const std::string &param )
95 {
96  trace.error() << " Parameter: " << param << " is required..";
97  trace.info() << std::endl;
98  exit( 1 );
99 }
100 
102 
103 int main( int argc, char ** argv )
104 {
105 
106  // parse command line using CLI ----------------------------------------------
107  CLI::App app;
108  std::string inputFileName;
109  std::string outputFileName {"result.vol"};
110  double noise {0.5};
111  bool MaxFlag {false};
112 
113  app.description("Adds Kanungo noise to a binary object with 0 values as "
114  "background points and values >0 for the foreground ones.\n Basic usage:\n \t volAddNoi0se [options] --input <imageName> --output <outputImage> -noise 0.3 \n");
115  app.add_option("-i,--input,1", inputFileName, "input image file name (any 3D image format accepted by DGtal::GenericReader)" )
116  ->required()
117  ->check(CLI::ExistingFile);
118  app.add_option("-o,--output,2", outputFileName, "output image file name (any 3D image format accepted by DGtal::GenericWriter)", true);
119 
120  app.add_option("--noise,-n", noise, "Kanungo noise level in ]0,1[ (default 0.5)\n", true);
121  app.add_flag("--max,-m", MaxFlag, "Extract only the largest 6-connected component.");
122 
123  app.get_formatter()->column_width(40);
124  CLI11_PARSE(app, argc, argv);
125  // END parse command line using CLI ----------------------------------------------
126 
127 
129  MyImage image = GenericReader<MyImage>::import( inputFileName );
130  trace.info() << "Input image: " << image << std::endl;
131  Binarizer predicate( image, 0, 255 );
132 
133  KanungoNoise<Binarizer, Z3i::Domain> kanungo( predicate, image.domain(),
134  noise );
135 
136  MyImage result( image.domain() );
137  for ( Z3i::Domain::ConstIterator it = image.domain().begin(),
138  itend = image.domain().end();
139  it != itend; ++it )
140  {
141  if ( kanungo( *it ) )
142  result.setValue( *it, 255 );
143  else
144  result.setValue( *it, 0 );
145  }
146 
147  // Exporting
148  if ( !MaxFlag )
149  {
150  result >> outputFileName;
151  }
152  else
153  {
154  trace.beginBlock( "Extracting the largest 6-connected component" );
155  typedef std::map<Z3i::Point, std::size_t> Rank; // => order on Element
156  typedef std::map<Z3i::Point, Z3i::Point> Parent;
157  Rank rankMap;
158  Parent parentMap;
159  boost::associative_property_map<Rank> rankPMap( rankMap );
160  boost::associative_property_map<Parent> parentPMap( parentMap );
161  boost::disjoint_sets<boost::associative_property_map<Rank>,
162  boost::associative_property_map<Parent>>
163  dsets( rankPMap, parentPMap );
164 
165  trace.beginBlock( "Initial disjoint sets construction" );
166  for ( auto e : result.domain() )
167  {
168  if ( result( e ) != 0 )
169  dsets.make_set( e );
170  }
171  trace.endBlock();
172 
173  trace.beginBlock( "Merging neighboring sets" );
174  typename Z3i::Point decx( 1, 0, 0 );
175  typename Z3i::Point decy( 0, 1, 0 );
176  typename Z3i::Point decz( 0, 0, 1 );
177 
178  // Merging process
179  for ( auto e : result.domain() )
180  {
181  if ( result( e ) != 0 )
182  {
183  if ( result.domain().isInside( e + decx ) &&
184  ( result( e ) == result( e + decx ) ) )
185  dsets.union_set( e, e + decx );
186 
187  if ( result.domain().isInside( e + decy ) &&
188  ( result( e ) == result( e + decy ) ) )
189  dsets.union_set( e, e + decy );
190 
191  if ( result.domain().isInside( e + decz ) &&
192  ( result( e ) == result( e + decz ) ) )
193  dsets.union_set( e, e + decz );
194  }
195  }
196  trace.endBlock();
197 
198  trace.beginBlock( "Counting component sizes" );
199  // counting
200  std::map<Z3i::Point, unsigned int> sizes;
201  for ( auto p : result.domain() )
202  {
203  if ( result( p ) != 0 )
204  {
205  Z3i::Point ref = dsets.find_set( p );
206  sizes[ ref ]++;
207  }
208  }
209  unsigned int maxElement = 0;
210  Z3i::Point maxP;
211  for ( auto i : sizes )
212  {
213  if ( maxElement < i.second )
214  {
215  maxElement = i.second;
216  maxP = i.first;
217  }
218  }
219  trace.info() << "Largest component has " << maxElement << " voxels."
220  << std::endl;
221  trace.endBlock();
222 
223  trace.beginBlock( "Cleaning up" );
224  // Cleaning
225  // Merging process
226  Z3i::Point largest = dsets.find_set( maxP );
227  trace.info() << "Largest ref point: " << largest << std::endl;
228  for ( auto e : result.domain() )
229  {
230  if ( result( e ) != 0 )
231  {
232  if ( dsets.find_set( e ) != largest )
233  result.setValue( e, 0 );
234  }
235  }
236  trace.endBlock();
237  trace.endBlock();
238  result >> outputFileName;
239  }
240  return 0;
241 }
void beginBlock(const std::string &keyword="")
double endBlock()
int main(int argc, char **argv)
static TContainer import(const std::string &filename, std::vector< unsigned int > dimSpace=std::vector< unsigned int >())
Trace trace(traceWriterTerm)
std::ostream & info()
const Domain & domain() const
void setValue(const Point &aPoint, const Value &aValue)
std::ostream & error()