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>
44 using namespace DGtal;
94 void missingParam(
const std::string ¶m )
96 trace.error() <<
" Parameter: " << param <<
" is required..";
97 trace.info() << std::endl;
101 typedef ImageSelector<Z3i::Domain, unsigned char>::Type MyImage;
103 int main(
int argc,
char ** argv )
108 std::string inputFileName;
109 std::string outputFileName {
"result.vol"};
111 bool MaxFlag {
false};
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)" )
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);
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.");
123 app.get_formatter()->column_width(40);
124 CLI11_PARSE(app, argc, argv);
128 typedef functors::IntervalForegroundPredicate<MyImage> Binarizer;
129 MyImage image = GenericReader<MyImage>::import( inputFileName );
130 trace.info() <<
"Input image: " << image << std::endl;
131 Binarizer predicate( image, 0, 255 );
133 KanungoNoise<Binarizer, Z3i::Domain> kanungo( predicate, image.domain(),
136 MyImage result( image.domain() );
137 for ( Z3i::Domain::ConstIterator it = image.domain().begin(),
138 itend = image.domain().end();
141 if ( kanungo( *it ) )
142 result.setValue( *it, 255 );
144 result.setValue( *it, 0 );
150 result >> outputFileName;
154 trace.beginBlock(
"Extracting the largest 6-connected component" );
155 typedef std::map<Z3i::Point, std::size_t> Rank;
156 typedef std::map<Z3i::Point, Z3i::Point> Parent;
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 );
165 trace.beginBlock(
"Initial disjoint sets construction" );
166 for (
auto e : result.domain() )
168 if ( result( e ) != 0 )
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 );
179 for (
auto e : result.domain() )
181 if ( result( e ) != 0 )
183 if ( result.domain().isInside( e + decx ) &&
184 ( result( e ) == result( e + decx ) ) )
185 dsets.union_set( e, e + decx );
187 if ( result.domain().isInside( e + decy ) &&
188 ( result( e ) == result( e + decy ) ) )
189 dsets.union_set( e, e + decy );
191 if ( result.domain().isInside( e + decz ) &&
192 ( result( e ) == result( e + decz ) ) )
193 dsets.union_set( e, e + decz );
198 trace.beginBlock(
"Counting component sizes" );
200 std::map<Z3i::Point, unsigned int> sizes;
201 for (
auto p : result.domain() )
203 if ( result( p ) != 0 )
205 Z3i::Point ref = dsets.find_set( p );
209 unsigned int maxElement = 0;
211 for (
auto i : sizes )
213 if ( maxElement < i.second )
215 maxElement = i.second;
219 trace.info() <<
"Largest component has " << maxElement <<
" voxels."
223 trace.beginBlock(
"Cleaning up" );
226 Z3i::Point largest = dsets.find_set( maxP );
227 trace.info() <<
"Largest ref point: " << largest << std::endl;
228 for (
auto e : result.domain() )
230 if ( result( e ) != 0 )
232 if ( dsets.find_set( e ) != largest )
233 result.setValue( e, 0 );
238 result >> outputFileName;