DGtalTools 2.0.0
Loading...
Searching...
No Matches
surface_extract.ih
1
2#include <DGtal/topology/SurfelAdjacency.h>
3#include <DGtal/topology/helpers/Surfaces.h>
4#include <DGtal/topology/SetOfSurfels.h>
5#include <DGtal/topology/DigitalSurface.h>
6#include <DGtal/dec/DiscreteExteriorCalculusFactory.h>
7#include <DGtal/geometry/surfaces/estimation/IIGeometricFunctors.h>
8#include <DGtal/geometry/surfaces/estimation/IntegralInvariantCovarianceEstimator.h>
9#include <DGtal/geometry/surfaces/estimation/LocalEstimatorFromSurfelFunctorAdapter.h>
10#include <DGtal/geometry/surfaces/estimation/estimationFunctors/ElementaryConvolutionNormalVectorEstimator.h>
11#include <DGtal/geometry/volumes/KanungoNoise.h>
12#include <DGtal/math/ScalarFunctors.h>
13#include <DGtal/geometry/volumes/distance/LpMetric.h>
14
15template <typename Shape>
16Calculus
17createCalculusFromShapeBorder(const KSpace& kspace, const Shape& shape)
18{
19 using DGtal::trace;
20 using std::endl;
21 using DGtal::PRIMAL;
22 using DGtal::DUAL;
23
24 trace.beginBlock("extracting surfels");
25
26 typedef KSpace::SurfelSet MySurfelSet;
27 typedef DGtal::SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
28 typedef DGtal::SetOfSurfels<KSpace, MySurfelSet> MySetOfSurfels;
29 typedef std::vector<SCell> MySCellsVector;
30 typedef std::vector<MySCellsVector> MyConnectedSCells;
31
32 const MySurfelAdjacency surfel_adjacency(true);
33 const MySetOfSurfels set_of_surfels(kspace, surfel_adjacency);
34 MyConnectedSCells connected_scells;
35 DGtal::Surfaces<KSpace>::extractAllConnectedSCell(connected_scells, kspace, surfel_adjacency, shape, false);
36 trace.info() << "connected_components_size=" << connected_scells.size() << endl;
37 ASSERT( !connected_scells.empty() );
38
39 const MyConnectedSCells::const_iterator max_connected_scells = std::max_element(connected_scells.begin(), connected_scells.end(),
40 [](const MySCellsVector& aa, const MySCellsVector& bb) { return aa.size() < bb.size(); });
41 ASSERT( max_connected_scells != connected_scells.end() );
42 trace.info() << "scells_size=" << max_connected_scells->size() << endl;
43
44 trace.endBlock();
45
46 trace.beginBlock("creating calculus");
47
48 typedef DGtal::DiscreteExteriorCalculusFactory<DGtal::EigenLinearAlgebraBackend> CalculusFactory;
49 const Calculus calculus = CalculusFactory::createFromNSCells<2>(max_connected_scells->begin(), max_connected_scells->end());
50 trace.info() << "calculus=" << calculus << endl;
51
52 {
53 const Calculus::PrimalForm2 primal_areas = calculus.hodge<0, DUAL>()*Calculus::DualForm0::ones(calculus);
54 const Calculus::DualForm2 dual_areas = calculus.hodge<0, PRIMAL>()*Calculus::PrimalForm0::ones(calculus);
55 const double primal_area = primal_areas.myContainer.array().sum();
56 const double dual_area = dual_areas.myContainer.array().sum();
57 trace.info() << "primal_area=" << primal_area << endl;
58 trace.info() << "dual_area=" << dual_area << endl;
59 ASSERT( primal_area == dual_area );
60 }
61
62 trace.endBlock();
63
64 return calculus;
65}
66
67template <typename Shape>
68FlatVector
69computeFaceNormals(const Calculus& calculus, const Shape& shape, const double radius)
70{
71 using DGtal::trace;
72 using std::endl;
73 using DGtal::PRIMAL;
74
75 trace.beginBlock("estimating normals");
76
77 typedef DGtal::Z3i::RealVector RealVector;
78 typedef std::vector<RealVector> RealVectors;
79
80 const KSpace& kspace = calculus.myKSpace;
81
82 const auto buildFlatVector = [&kspace, &calculus](const RealVectors& real_vectors)
83 {
84 ASSERT( real_vectors.size() == calculus.kFormLength(2, PRIMAL) );
85 const int nsurfels = real_vectors.size();
86 FlatVector vectors(3*real_vectors.size());
87 int index = 0;
88 for (const RealVector& real_vector : real_vectors)
89 {
90 for (int dim=0; dim<3; dim++)
91 vectors[index+nsurfels*dim] = real_vector[dim];
92 index ++;
93 }
94 return vectors;
95 };
96
97 const Calculus::SCells& surfels = calculus.getIndexedSCells<2, PRIMAL>();
98
99 trace.info() << "radius=" << radius << endl;
100
101 RealVectors nii_normals_estimations;
102 {
103 typedef DGtal::Z3i::Space Space;
104 typedef DGtal::functors::IINormalDirectionFunctor<Space> IINormalFunctor;
105 typedef DGtal::IntegralInvariantCovarianceEstimator<KSpace, Shape, IINormalFunctor> IINormalEstimator;
106
107 IINormalEstimator nii_estimator(kspace, shape);
108 nii_estimator.setParams(radius);
109 nii_estimator.init(1, surfels.begin(), surfels.end());
110
111 nii_estimator.eval(surfels.begin(), surfels.end(), std::back_inserter(nii_normals_estimations));
112 trace.info() << "nii_estimations_size=" << nii_normals_estimations.size() << endl;
113 ASSERT( nii_normals_estimations.size() == surfels.size() );
114 }
115
116 RealVectors nt_normals_estimations;
117 {
118 typedef DGtal::Z3i::Space Space;
119 typedef DGtal::SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
120 typedef KSpace::SurfelSet MySurfelSet;
121 typedef DGtal::SetOfSurfels<KSpace, MySurfelSet> MySetOfSurfels;
122 typedef DGtal::DigitalSurface<MySetOfSurfels> MyDigitalSurface;
123 typedef DGtal::LpMetric<Space> MyMetric;
124 typedef DGtal::CanonicSCellEmbedder<KSpace> MyCanonicSCellEmbedder;
125 typedef DGtal::functors::ElementaryConvolutionNormalVectorEstimator<SCell, MyCanonicSCellEmbedder> MySurfelFunctor;
126 typedef RealVector::Component MyScalar;
127 typedef DGtal::functors::HatFunction<MyScalar> MyHatFunctor;
128 typedef DGtal::LocalEstimatorFromSurfelFunctorAdapter<MySetOfSurfels, MyMetric, MySurfelFunctor, MyHatFunctor> TrivialNormalEstimator;
129
130 const MySurfelAdjacency surfel_adjacency(true);
131 MySetOfSurfels surfels_set(kspace, surfel_adjacency);
132 std::copy(surfels.begin(), surfels.end(), std::inserter(surfels_set.surfelSet(), surfels_set.surfelSet().begin()));
133 const MyDigitalSurface digital_surface(surfels_set);
134 trace.info() << "digital_surface_size=" << digital_surface.size() << endl;
135
136 const MyHatFunctor hat_functor(1., radius);
137 const MyCanonicSCellEmbedder canonic_embedder(kspace);
138 MySurfelFunctor surfel_functor(canonic_embedder, 1.);
139 const MyMetric metric(2.0);
140
141 TrivialNormalEstimator nt_estimator;
142 nt_estimator.attach(digital_surface);
143 nt_estimator.setParams(metric, surfel_functor, hat_functor, radius);
144 nt_estimator.init(1, surfels.begin(), surfels.end());
145
146 nt_estimator.eval(surfels.begin(), surfels.end(), std::back_inserter(nt_normals_estimations));
147 trace.info() << "nt_estimations_size=" << nt_normals_estimations.size() << endl;
148 ASSERT( nt_normals_estimations.size() == surfels.size() );
149 }
150
151 RealVectors::iterator nt_normals_estimations_iter = nt_normals_estimations.begin();
152 for (RealVector& normal : nii_normals_estimations)
153 {
154 if (nt_normals_estimations_iter->dot(normal) > 0) normal = -normal;
155 nt_normals_estimations_iter++;
156 }
157
158 trace.endBlock();
159
160 return buildFlatVector(nii_normals_estimations);
161}
162
163template <typename Shape>
164std::tuple<Calculus, FlatVector>
165initCalculusAndNormalsWithNoise(const KSpace& kspace, const Shape& shape, const double radius, const double noise)
166{
167 using DGtal::trace;
168 using std::endl;
169
170 if (noise <= 0) return initCalculusAndNormals(kspace, shape, radius);
171
172 typedef DGtal::Z3i::Domain Domain;
173 const Domain domain(kspace.lowerBound(), kspace.upperBound());
174 trace.info() << "noise=" << noise << endl;
175 trace.info() << "domain=" << domain << endl;
176
177 typedef DGtal::KanungoNoise<Shape, Domain> KanungoPredicate;
178 typedef DGtal::functors::DomainPredicate<Domain> DomainPredicate;
179 typedef DGtal::functors::BinaryPointPredicate<DomainPredicate, KanungoPredicate, DGtal::functors::AndBoolFct2> NoisyShape;
180 const KanungoPredicate kanungo_pred(shape, domain, noise);
181 const DomainPredicate domain_pred(domain);
182 const DGtal::functors::AndBoolFct2 and_functor = DGtal::functors::AndBoolFct2();
183 const NoisyShape noisy_shape(domain_pred, kanungo_pred, and_functor);
184
185 return initCalculusAndNormals(kspace, noisy_shape, radius);
186}
187
188template <typename Shape>
189std::tuple<Calculus, FlatVector>
190initCalculusAndNormals(const KSpace& kspace, const Shape& shape, const double radius)
191{
192 Calculus calculus = createCalculusFromShapeBorder(kspace, shape);
193 FlatVector normals = computeFaceNormals(calculus, shape, radius);
194 return std::make_tuple(calculus, normals);
195}
196
197