DGtalTools  0.9.4
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 #include <boost/program_options/options_description.hpp>
35 #include <boost/program_options/parsers.hpp>
36 #include <boost/program_options/variables_map.hpp>
37 
38 // Max component option
39 #include <boost/pending/disjoint_sets.hpp>
40 
41 #include <vector>
42 #include <string>
43 #include <climits>
44 
45 using namespace DGtal;
46 
48 namespace po = boost::program_options;
49 
92 void missingParam( const std::string &param )
93 {
94  trace.error() << " Parameter: " << param << " is required..";
95  trace.info() << std::endl;
96  exit( 1 );
97 }
98 
100 
101 int main( int argc, char ** argv )
102 {
103  // parse command line ----------------------------------------------
104  po::options_description general_opt( "Allowed options are: " );
105  general_opt.add_options()( "help,h", "display this message" )(
106  "input,i", po::value<std::string>(),
107  "input image file name (any 3D image format accepted by "
108  "DGtal::GenericReader)" )( "output,o", po::value<std::string>(),
109  "output image file name (any 3D image format "
110  "accepted by DGtal::GenericWriter)" )(
111  "noise,n", po::value<double>()->default_value( 0.5 ),
112  "Kanungo noise level in ]0,1[ (default 0.5)" )(
113  "max,m", "Extract only the largest 6-connected component." );
114 
115  bool parseOK = true;
116  po::variables_map vm;
117  try
118  {
119  po::store( po::parse_command_line( argc, argv, general_opt ), vm );
120  }
121  catch ( const std::exception & ex )
122  {
123  trace.info() << "Error checking program options: " << ex.what()
124  << std::endl;
125  parseOK = false;
126  }
127  po::notify( vm );
128  if ( vm.count( "help" ) || argc <= 1 || !parseOK )
129  {
130  trace.info() << "Adds Kanungo noise to a binary object with 0 values as "
131  "background points and values >0 for the foreground ones."
132  << std::endl
133  << "Basic usage: " << std::endl
134  << "\t volAddNoi0se [options] --input <imageName> --output "
135  "<outputImage> -noise 0.3"
136  << std::endl
137  << general_opt << "\n";
138  return 0;
139  }
140 
141  // Parameters
142  bool MaxFlag = vm.count( "max" );
143 
144  if ( !( vm.count( "input" ) ) )
145  missingParam( "--input" );
146  const std::string input = vm[ "input" ].as<std::string>();
147  if ( !( vm.count( "output" ) ) )
148  missingParam( "--output" );
149  const std::string output = vm[ "output" ].as<std::string>();
150  const double noise = vm[ "noise" ].as<double>();
151 
153  MyImage image = GenericReader<MyImage>::import( input );
154  trace.info() << "Input image: " << image << std::endl;
155  Binarizer predicate( image, 0, 255 );
156 
157  KanungoNoise<Binarizer, Z3i::Domain> kanungo( predicate, image.domain(),
158  noise );
159 
160  MyImage result( image.domain() );
161  for ( Z3i::Domain::ConstIterator it = image.domain().begin(),
162  itend = image.domain().end();
163  it != itend; ++it )
164  {
165  if ( kanungo( *it ) )
166  result.setValue( *it, 255 );
167  else
168  result.setValue( *it, 0 );
169  }
170 
171  // Exporting
172  if ( !MaxFlag )
173  {
174  result >> output;
175  }
176  else
177  {
178  trace.beginBlock( "Extracting the largest 6-connected component" );
179  typedef std::map<Z3i::Point, std::size_t> Rank; // => order on Element
180  typedef std::map<Z3i::Point, Z3i::Point> Parent;
181  Rank rankMap;
182  Parent parentMap;
183  boost::associative_property_map<Rank> rankPMap( rankMap );
184  boost::associative_property_map<Parent> parentPMap( parentMap );
185  boost::disjoint_sets<boost::associative_property_map<Rank>,
186  boost::associative_property_map<Parent>>
187  dsets( rankPMap, parentPMap );
188 
189  trace.beginBlock( "Initial disjoint sets construction" );
190  for ( auto e : result.domain() )
191  {
192  if ( result( e ) != 0 )
193  dsets.make_set( e );
194  }
195  trace.endBlock();
196 
197  trace.beginBlock( "Merging neighboring sets" );
198  typename Z3i::Point decx( 1, 0, 0 );
199  typename Z3i::Point decy( 0, 1, 0 );
200  typename Z3i::Point decz( 0, 0, 1 );
201 
202  // Merging process
203  for ( auto e : result.domain() )
204  {
205  if ( result( e ) != 0 )
206  {
207  if ( result.domain().isInside( e + decx ) &&
208  ( result( e ) == result( e + decx ) ) )
209  dsets.union_set( e, e + decx );
210 
211  if ( result.domain().isInside( e + decy ) &&
212  ( result( e ) == result( e + decy ) ) )
213  dsets.union_set( e, e + decy );
214 
215  if ( result.domain().isInside( e + decz ) &&
216  ( result( e ) == result( e + decz ) ) )
217  dsets.union_set( e, e + decz );
218  }
219  }
220  trace.endBlock();
221 
222  trace.beginBlock( "Counting component sizes" );
223  // counting
224  std::map<Z3i::Point, unsigned int> sizes;
225  for ( auto p : result.domain() )
226  {
227  if ( result( p ) != 0 )
228  {
229  Z3i::Point ref = dsets.find_set( p );
230  sizes[ ref ]++;
231  }
232  }
233  unsigned int maxElement = 0;
234  Z3i::Point maxP;
235  for ( auto i : sizes )
236  {
237  if ( maxElement < i.second )
238  {
239  maxElement = i.second;
240  maxP = i.first;
241  }
242  }
243  trace.info() << "Largest component has " << maxElement << " voxels."
244  << std::endl;
245  trace.endBlock();
246 
247  trace.beginBlock( "Cleaning up" );
248  // Cleaning
249  // Merging process
250  Z3i::Point largest = dsets.find_set( maxP );
251  trace.info() << "Largest ref point: " << largest << std::endl;
252  for ( auto e : result.domain() )
253  {
254  if ( result( e ) != 0 )
255  {
256  if ( dsets.find_set( e ) != largest )
257  result.setValue( e, 0 );
258  }
259  }
260  trace.endBlock();
261  trace.endBlock();
262  result >> output;
263  }
264  return 0;
265 }
void beginBlock(const std::string &keyword="")
double endBlock()
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
std::ostream & error()