DGtalTools 2.1.0
Loading...
Searching...
No Matches
volSurfaceRegularization.cpp
1
91#include <DGtal/base/Common.h>
92#include <DGtal/helpers/StdDefs.h>
93
94#include "CLI11.hpp"
95
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>
101#include <random>
102#include <iomanip>
103#include <regex>
104#include "volSurfaceRegularization-details/surface_approx.h"
105#include "volSurfaceRegularization-details/surface_extract.h"
106#include "volSurfaceRegularization-details/shape.h"
107
108
109struct Options
110{
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};
116 double align {1.0};
117 double fairness{0.0};
118 double barycenter{1e-1};
119 std::string regularized_obj_filename;
120 std::string cubical_obj_filename;
121};
122
123
124
125
126
127
128int main(int argc, char* argv[])
129{
130 using DGtal::trace;
131 using std::endl;
132 using DGtal::PRIMAL;
133 using DGtal::DUAL;
134
135 // parse command line using CLI ----------------------------------------------
136 CLI::App app;
137 Options options;
138
139 app.description("Regularize a cubical complex into a smooth quadrangulated complex.");
140
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");
147
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");
154
155 app.get_formatter()->column_width(40);
156 CLI11_PARSE(app, argc, argv);
157 // END parse command line using CLI ----------------------------------------------
158
159 const KSpace kspace;
160
161 const Calculus calculus;
162 const FlatVector original_face_normals;
163
164 if (!ends_with(options.image_filename, ".csv"))
165 {
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;
175 const ImageShape<ImageUChar> shape(&image_uchar, center);
176
177 const_cast<KSpace&>(kspace).init(domain.lowerBound()-center-Point::diagonal(1), domain.upperBound()-center+Point::diagonal(1), true);
178
179 std::tie(const_cast<Calculus&>(calculus), const_cast<FlatVector&>(original_face_normals)) =
180 initCalculusAndNormalsWithNoise(kspace, shape, options.normal_radius, options.noise_level);
181 }
182
183 if (ends_with(options.image_filename, ".csv"))
184 {
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);
189 }
190
191 const FlatVector original_vertex_normals = vertexNormals(calculus, original_face_normals);
192
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) );
207
208 {
209 trace.beginBlock( "computing energies" );
210
211 {
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
220 << endl;
221 }
222
223 {
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;
230 }
231
232 trace.endBlock();
233 }
234
235 {
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);
239 }
240
241 if (!options.cubical_obj_filename.empty())
242 {
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);
246 }
247
248 return 0;
249}
250
251