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>
38#include <boost/pending/disjoint_sets.hpp>
95void missingParam(
const std::string ¶m )
97 trace.error() <<
" Parameter: " << param <<
" is required..";
98 trace.info() << std::endl;
102typedef ImageSelector<Z3i::Domain, unsigned char>::Type MyImage;
104int main(
int argc,
char ** argv )
109 std::string inputFileName;
110 std::string outputFileName {
"result.vol"};
112 bool MaxFlag {
false};
114 app.description(
"Adds Kanungo noise to a binary object with 0 values as "
115 "background points and values >0 for the foreground ones.\n Basic usage:\n \t volAddNoi0se [options] --input <imageName> --output <outputImage> -noise 0.3 \n");
116 app.add_option(
"-i,--input,1", inputFileName,
"input image file name (any 3D image format accepted by DGtal::GenericReader)" )
118 ->check(CLI::ExistingFile);
119 app.add_option(
"-o,--output,2", outputFileName,
"output image file name (any 3D image format accepted by DGtal::GenericWriter)");
121 app.add_option(
"--noise,-n", noise,
"Kanungo noise level in ]0,1[ (default 0.5)\n");
122 app.add_flag(
"--max,-m", MaxFlag,
"Extract only the largest 6-connected component.");
124 app.get_formatter()->column_width(40);
125 CLI11_PARSE(app, argc, argv);
129 typedef functors::IntervalForegroundPredicate<MyImage> Binarizer;
130 MyImage image = GenericReader<MyImage>::import( inputFileName );
131 trace.info() <<
"Input image: " << image << std::endl;
132 Binarizer predicate( image, 0, 255 );
134 KanungoNoise<Binarizer, Z3i::Domain> kanungo( predicate, image.domain(),
137 MyImage result( image.domain() );
138 for ( Z3i::Domain::ConstIterator it = image.domain().begin(),
139 itend = image.domain().end();
142 if ( kanungo( *it ) )
143 result.setValue( *it, 255 );
145 result.setValue( *it, 0 );
151 result >> outputFileName;
155 trace.beginBlock(
"Extracting the largest 6-connected component" );
156 typedef std::map<Z3i::Point, std::size_t> Rank;
157 typedef std::map<Z3i::Point, Z3i::Point> Parent;
160 boost::associative_property_map<Rank> rankPMap( rankMap );
161 boost::associative_property_map<Parent> parentPMap( parentMap );
162 boost::disjoint_sets<boost::associative_property_map<Rank>,
163 boost::associative_property_map<Parent>>
164 dsets( rankPMap, parentPMap );
166 trace.beginBlock(
"Initial disjoint sets construction" );
167 for (
auto e : result.domain() )
169 if ( result( e ) != 0 )
174 trace.beginBlock(
"Merging neighboring sets" );
175 typename Z3i::Point decx( 1, 0, 0 );
176 typename Z3i::Point decy( 0, 1, 0 );
177 typename Z3i::Point decz( 0, 0, 1 );
180 for (
auto e : result.domain() )
182 if ( result( e ) != 0 )
184 if ( result.domain().isInside( e + decx ) &&
185 ( result( e ) == result( e + decx ) ) )
186 dsets.union_set( e, e + decx );
188 if ( result.domain().isInside( e + decy ) &&
189 ( result( e ) == result( e + decy ) ) )
190 dsets.union_set( e, e + decy );
192 if ( result.domain().isInside( e + decz ) &&
193 ( result( e ) == result( e + decz ) ) )
194 dsets.union_set( e, e + decz );
199 trace.beginBlock(
"Counting component sizes" );
201 std::map<Z3i::Point, unsigned int> sizes;
202 for (
auto p : result.domain() )
204 if ( result( p ) != 0 )
206 Z3i::Point ref = dsets.find_set( p );
210 unsigned int maxElement = 0;
212 for (
auto i : sizes )
214 if ( maxElement < i.second )
216 maxElement = i.second;
220 trace.info() <<
"Largest component has " << maxElement <<
" voxels."
224 trace.beginBlock(
"Cleaning up" );
227 Z3i::Point largest = dsets.find_set( maxP );
228 trace.info() <<
"Largest ref point: " << largest << std::endl;
229 for (
auto e : result.domain() )
231 if ( result( e ) != 0 )
233 if ( dsets.find_set( e ) != largest )
234 result.setValue( e, 0 );
239 result >> outputFileName;