91#include <DGtal/base/Common.h>
92#include <DGtal/helpers/StdDefs.h>
96#include <DGtal/images/ImageSelector.h>
97#include <DGtal/io/readers/GenericReader.h>
98#include <DGtal/topology/SurfelNeighborhood.h>
99#include <DGtal/topology/helpers/Surfaces.h>
100#include <DGtal/geometry/volumes/distance/VoronoiMap.h>
104#include "volSurfaceRegularization-details/surface_approx.h"
105#include "volSurfaceRegularization-details/surface_extract.h"
106#include "volSurfaceRegularization-details/shape.h"
111 double noise_level {0};
112 std::string image_filename;
113 double normal_radius {4} ;
114 double regularization_position {1e-3};
115 double regularization_center {1e-2};
117 double fairness{0.0};
118 double barycenter{1e-1};
119 std::string regularized_obj_filename;
120 std::string cubical_obj_filename;
128int main(
int argc,
char* argv[])
139 app.description(
"Regularize a cubical complex into a smooth quadrangulated complex.");
141 app.add_option(
"--image-filename,-i,1",options.image_filename,
"input vol filename for image shape (object voxels have values > 0) or input cvs filename for surfels and normals") -> required();
142 app.add_option(
"--regularized-obj-filename,-o,1", options.regularized_obj_filename,
"output regularized obj") -> required();
143 app.add_option(
"--cubical-obj-filename,-n", options.cubical_obj_filename,
"output cubical obj");
144 app.add_option(
"--shape-noise,-k", options.noise_level,
"noise shape parameter" );
145 auto groupNormEst = app.add_option_group(
"Normal field estimator options");
146 groupNormEst->add_option(
"--normal-radius,-r", options.normal_radius,
"radius of normal estimator");
148 auto groupApprox = app.add_option_group(
"Surface approximation options");
149 groupApprox->add_option(
"--regularization-position,-p", options.regularization_position,
"vertex position regularization coeff" );
150 groupApprox->add_option(
"--regularization-center,-c",options.regularization_center,
"face center regularization coeff");
151 groupApprox->add_option(
"--align,-a", options.align,
"normal alignment coeff");
152 groupApprox->add_option(
"--fairness,-f",options.fairness,
"face fairness coeff");
153 groupApprox->add_option(
"--barycenter,-b", options.barycenter,
"barycenter fairness coeff");
155 app.get_formatter()->column_width(40);
156 CLI11_PARSE(app, argc, argv);
161 const Calculus calculus;
162 const FlatVector original_face_normals;
164 if (!ends_with(options.image_filename,
".csv"))
166 ASSERT( !options.image_filename.empty() );
167 typedef DGtal::Z3i::Domain Domain;
168 typedef DGtal::ImageSelector<Domain, unsigned char>::Type ImageUChar;
169 trace.info() <<
"image_filename=" << options.image_filename << endl;
170 ImageUChar image_uchar = DGtal::GenericReader<ImageUChar>::import(options.image_filename);
171 const Domain domain = image_uchar.domain();
172 trace.info() <<
"domain=" << domain << endl;
173 const Point center = (domain.upperBound()+domain.lowerBound())/2;
174 trace.info() <<
"center=" << center << endl;
177 const_cast<KSpace&
>(kspace).init(domain.lowerBound()-center-Point::diagonal(1), domain.upperBound()-center+Point::diagonal(1),
true);
179 std::tie(
const_cast<Calculus&
>(calculus),
const_cast<FlatVector&
>(original_face_normals)) =
180 initCalculusAndNormalsWithNoise(kspace, shape, options.normal_radius, options.noise_level);
183 if (ends_with(options.image_filename,
".csv"))
185 ASSERT( !options.image_filename.empty() );
186 trace.info() <<
"csv_filename=" << options.image_filename << endl;
187 std::tie(
const_cast<Calculus&
>(calculus),
const_cast<FlatVector&
>(original_face_normals)) =
188 initCalculusAndNormalsFromSurfelNormalsCSV(options.image_filename);
191 const FlatVector original_vertex_normals = vertexNormals(calculus, original_face_normals);
193 const FlatVector original_positions;
194 const FlatVector regularized_positions;
195 const FlatVector original_centers;
196 const FlatVector regularized_centers;
197 std::tie(
const_cast<FlatVector&
>(original_positions),
198 const_cast<FlatVector&
>(regularized_positions),
199 const_cast<FlatVector&
>(original_centers),
200 const_cast<FlatVector&
>(regularized_centers)) =
201 approximateSurface(calculus, original_face_normals,
202 ApproxParams({options.regularization_position, options.regularization_center, options.align, options.fairness, options.barycenter}));
203 ASSERT( original_positions.size() == 3*calculus.kFormLength(0, PRIMAL) );
204 ASSERT( regularized_positions.size() == 3*calculus.kFormLength(0, PRIMAL) );
205 ASSERT( original_centers.size() == 3*calculus.kFormLength(2, PRIMAL) );
206 ASSERT( regularized_centers.size() == 3*calculus.kFormLength(2, PRIMAL) );
209 trace.beginBlock(
"computing energies" );
212 double position_energy = 0;
213 double align_energy = 0;
214 std::tie( position_energy, align_energy ) = approximateSurfaceEnergies(
215 calculus, original_face_normals, original_positions );
216 align_energy *= options.align;
217 position_energy *= options.regularization_position;
218 trace.info() <<
"original_energies=" << position_energy <<
" "
219 << align_energy <<
" " << position_energy + align_energy
224 double position_energy = 0;
225 double align_energy = 0;
226 std::tie(position_energy, align_energy) = approximateSurfaceEnergies(calculus, original_face_normals, regularized_positions);
227 align_energy *= options.align;
228 position_energy *= options.regularization_position;
229 trace.info() <<
"regularized_energies=" << position_energy <<
" " << align_energy <<
" " << position_energy+align_energy << endl;
236 ASSERT( !options.regularized_obj_filename.empty() );
237 trace.info() <<
"regularized_obj_filename=" << options.regularized_obj_filename << endl;
238 exportOBJ(calculus, regularized_positions, options.regularized_obj_filename);
241 if (!options.cubical_obj_filename.empty())
243 ASSERT( !options.cubical_obj_filename.empty() );
244 trace.info() <<
"cubical_obj_filename=" << options.cubical_obj_filename << endl;
245 exportOBJ(calculus, original_positions, options.cubical_obj_filename);