90#include <DGtal/base/Common.h>
91#include <DGtal/helpers/StdDefs.h>
95#include <DGtal/images/ImageSelector.h>
96#include <DGtal/io/readers/GenericReader.h>
97#include <DGtal/topology/SurfelNeighborhood.h>
98#include <DGtal/topology/helpers/Surfaces.h>
99#include <DGtal/geometry/volumes/distance/VoronoiMap.h>
103#include "volSurfaceRegularization-details/surface_approx.h"
104#include "volSurfaceRegularization-details/surface_extract.h"
105#include "volSurfaceRegularization-details/shape.h"
110 double noise_level {0};
111 std::string image_filename;
112 double normal_radius {4} ;
113 double regularization_position {1e-3};
114 double regularization_center {1e-2};
116 double fairness{0.0};
117 double barycenter{1e-1};
118 std::string regularized_obj_filename;
119 std::string cubical_obj_filename;
127int main(
int argc,
char* argv[])
138 app.description(
"Regularize a cubical complex into a smooth quadrangulated complex.");
140 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();
141 app.add_option(
"--regularized-obj-filename,-o,1", options.regularized_obj_filename,
"output regularized obj") -> required();
142 app.add_option(
"--cubical-obj-filename,-n", options.cubical_obj_filename,
"output cubical obj");
143 app.add_option(
"--shape-noise,-k", options.noise_level,
"noise shape parameter" );
144 auto groupNormEst = app.add_option_group(
"Normal field estimator options");
145 groupNormEst->add_option(
"--normal-radius,-r", options.normal_radius,
"radius of normal estimator");
147 auto groupApprox = app.add_option_group(
"Surface approximation options");
148 groupApprox->add_option(
"--regularization-position,-p", options.regularization_position,
"vertex position regularization coeff" );
149 groupApprox->add_option(
"--regularization-center,-c",options.regularization_center,
"face center regularization coeff");
150 groupApprox->add_option(
"--align,-a", options.align,
"normal alignment coeff");
151 groupApprox->add_option(
"--fairness,-f",options.fairness,
"face fairness coeff");
152 groupApprox->add_option(
"--barycenter,-b", options.barycenter,
"barycenter fairness coeff");
154 app.get_formatter()->column_width(40);
155 CLI11_PARSE(app, argc, argv);
160 const Calculus calculus;
161 const FlatVector original_face_normals;
163 if (!ends_with(options.image_filename,
".csv"))
165 ASSERT( !options.image_filename.empty() );
166 typedef DGtal::Z3i::Domain Domain;
167 typedef DGtal::ImageSelector<Domain, unsigned char>::Type ImageUChar;
168 trace.info() <<
"image_filename=" << options.image_filename << endl;
169 ImageUChar image_uchar = DGtal::GenericReader<ImageUChar>::import(options.image_filename);
170 const Domain domain = image_uchar.domain();
171 trace.info() <<
"domain=" << domain << endl;
172 const Point center = (domain.upperBound()+domain.lowerBound())/2;
173 trace.info() <<
"center=" << center << endl;
176 const_cast<KSpace&
>(kspace).init(domain.lowerBound()-center-Point::diagonal(1), domain.upperBound()-center+Point::diagonal(1),
true);
178 std::tie(
const_cast<Calculus&
>(calculus),
const_cast<FlatVector&
>(original_face_normals)) =
179 initCalculusAndNormalsWithNoise(kspace, shape, options.normal_radius, options.noise_level);
182 if (ends_with(options.image_filename,
".csv"))
184 ASSERT( !options.image_filename.empty() );
185 trace.info() <<
"csv_filename=" << options.image_filename << endl;
186 std::tie(
const_cast<Calculus&
>(calculus),
const_cast<FlatVector&
>(original_face_normals)) =
187 initCalculusAndNormalsFromSurfelNormalsCSV(options.image_filename);
190 const FlatVector original_vertex_normals = vertexNormals(calculus, original_face_normals);
192 const FlatVector original_positions;
193 const FlatVector regularized_positions;
194 const FlatVector original_centers;
195 const FlatVector regularized_centers;
196 std::tie(
const_cast<FlatVector&
>(original_positions),
197 const_cast<FlatVector&
>(regularized_positions),
198 const_cast<FlatVector&
>(original_centers),
199 const_cast<FlatVector&
>(regularized_centers)) =
200 approximateSurface(calculus, original_face_normals,
201 ApproxParams({options.regularization_position, options.regularization_center, options.align, options.fairness, options.barycenter}));
202 ASSERT( original_positions.size() == 3*calculus.kFormLength(0, PRIMAL) );
203 ASSERT( regularized_positions.size() == 3*calculus.kFormLength(0, PRIMAL) );
204 ASSERT( original_centers.size() == 3*calculus.kFormLength(2, PRIMAL) );
205 ASSERT( regularized_centers.size() == 3*calculus.kFormLength(2, PRIMAL) );
208 trace.beginBlock(
"computing energies" );
211 double position_energy = 0;
212 double align_energy = 0;
213 std::tie( position_energy, align_energy ) = approximateSurfaceEnergies(
214 calculus, original_face_normals, original_positions );
215 align_energy *= options.align;
216 position_energy *= options.regularization_position;
217 trace.info() <<
"original_energies=" << position_energy <<
" "
218 << align_energy <<
" " << position_energy + align_energy
223 double position_energy = 0;
224 double align_energy = 0;
225 std::tie(position_energy, align_energy) = approximateSurfaceEnergies(calculus, original_face_normals, regularized_positions);
226 align_energy *= options.align;
227 position_energy *= options.regularization_position;
228 trace.info() <<
"regularized_energies=" << position_energy <<
" " << align_energy <<
" " << position_energy+align_energy << endl;
235 ASSERT( !options.regularized_obj_filename.empty() );
236 trace.info() <<
"regularized_obj_filename=" << options.regularized_obj_filename << endl;
237 exportOBJ(calculus, regularized_positions, options.regularized_obj_filename);
240 if (!options.cubical_obj_filename.empty())
242 ASSERT( !options.cubical_obj_filename.empty() );
243 trace.info() <<
"cubical_obj_filename=" << options.cubical_obj_filename << endl;
244 exportOBJ(calculus, original_positions, options.cubical_obj_filename);