1 #ifndef CGAL_SURFACE_MESH_SEGMENTATION_FILTERS_H
2 #define CGAL_SURFACE_MESH_SEGMENTATION_FILTERS_H
19 template<
class Polyhedron>
20 class Neighbor_selector_by_edge;
22 template<
class Polyhedron>
23 class Neighbor_selector_by_vertex;
26 template <
class Polyhedron,
class NeighborSelector = Neighbor_selector_by_edge<Polyhedron> >
27 class Bilateral_filtering
40 template<
class ValuePropertyMap>
41 void operator()(
const Polyhedron& mesh,
43 ValuePropertyMap values)
const
45 typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
46 typedef typename Polyhedron::Facet_const_iterator Facet_const_iterator;
48 std::vector<double> smoothed_values;
49 smoothed_values.reserve(mesh.size_of_facets());
51 for(Facet_const_iterator facet_it = mesh.facets_begin(); facet_it != mesh.facets_end(); ++facet_it)
53 std::map<Facet_const_handle, int> neighbors;
54 NeighborSelector()(facet_it, window_size, neighbors);
57 double current_sdf_value = values[facet_it];
58 double deviation = 0.0;
59 for(
typename std::map<Facet_const_handle, int>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
61 deviation += std::pow(values[it->first] - current_sdf_value, 2);
63 deviation = std::sqrt(deviation / neighbors.size());
68 smoothed_values.push_back(current_sdf_value);
72 double total_sdf_value = 0.0, total_weight = 0.0;
73 for(
typename std::map<Facet_const_handle, int>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
75 double spatial_weight = gaussian_function(it->second, window_size / 2.0);
76 double range_weight = gaussian_function(values[it->first] - current_sdf_value, 1.5 * deviation);
78 double weight = spatial_weight * range_weight;
80 total_sdf_value += values[it->first] * weight;
81 total_weight += weight;
83 smoothed_values.push_back(total_sdf_value / total_weight);
86 std::vector<double>::iterator smoothed_value_it = smoothed_values.begin();
87 for(Facet_const_iterator facet_it = mesh.facets_begin(); facet_it != mesh.facets_end();
88 ++facet_it, ++smoothed_value_it)
90 values[facet_it] = *smoothed_value_it;
95 double gaussian_function(
double value,
double deviation)
const
97 return exp(-0.5 * (std::pow(value / deviation, 2)));
102 template <
class Polyhedron,
class NeighborSelector = Neighbor_selector_by_vertex<Polyhedron> >
103 class Median_filtering
114 template<
class ValuePropertyMap>
115 void operator()(
const Polyhedron& mesh,
117 ValuePropertyMap values)
const
119 typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
120 typedef typename Polyhedron::Facet_const_iterator Facet_const_iterator;
122 std::vector<double> smoothed_values;
123 smoothed_values.reserve(mesh.size_of_facets());
124 for(Facet_const_iterator facet_it = mesh.facets_begin(); facet_it != mesh.facets_end(); ++facet_it)
126 std::map<Facet_const_handle, int> neighbors;
127 NeighborSelector()(facet_it, window_size, neighbors);
129 std::vector<double> neighbor_values;
130 neighbor_values.reserve(neighbors.size());
131 for(
typename std::map<Facet_const_handle, int>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
133 neighbor_values.push_back(values[it->first]);
136 int half_neighbor_count = neighbor_values.size() / 2;
137 std::nth_element(neighbor_values.begin(), neighbor_values.begin() + half_neighbor_count, neighbor_values.end());
138 double median_sdf = neighbor_values[half_neighbor_count];
139 if(neighbor_values.size() % 2 == 0)
141 median_sdf += *std::max_element(neighbor_values.begin(), neighbor_values.begin() + half_neighbor_count);
144 smoothed_values.push_back(median_sdf);
147 std::vector<double>::iterator smoothed_value_it = smoothed_values.begin();
148 for(Facet_const_iterator facet_it = mesh.facets_begin(); facet_it != mesh.facets_end();
151 values[facet_it] = *smoothed_value_it;
157 template<
class Polyhedron>
158 class Neighbor_selector_by_edge
161 typedef typename Polyhedron::Facet::Halfedge_around_facet_const_circulator Halfedge_around_facet_const_circulator;
163 typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
170 void operator()(Facet_const_handle facet,
172 std::map<Facet_const_handle, int>& neighbors)
const
174 typedef std::pair<Facet_const_handle, int> Facet_level_pair;
176 std::queue<Facet_level_pair> facet_queue;
177 facet_queue.push(Facet_level_pair(facet, 0));
178 neighbors.insert(facet_queue.front());
180 while(!facet_queue.empty())
182 const Facet_level_pair& pair = facet_queue.front();
184 Halfedge_around_facet_const_circulator facet_circulator = pair.first->facet_begin();
186 if(!facet_circulator->opposite()->is_border())
188 Facet_level_pair new_pair(facet_circulator->opposite()->facet(), pair.second + 1);
189 if(neighbors.insert(new_pair).second && new_pair.second < max_level)
191 facet_queue.push(new_pair);
194 }
while(++facet_circulator != pair.first->facet_begin());
202 template<
class Polyhedron>
203 class Neighbor_selector_by_vertex
206 typedef typename Polyhedron::Facet::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator;
207 typedef typename Polyhedron::Halfedge_const_iterator Halfedge_const_iterator;
208 typedef typename Polyhedron::Vertex_const_iterator Vertex_const_iterator;
210 typedef typename Polyhedron::Facet_const_handle Facet_const_handle;
217 void operator()(Facet_const_handle facet,
219 std::map<Facet_const_handle, int>& neighbors)
const
221 typedef std::pair<Facet_const_handle, int> Facet_level_pair;
223 std::queue<Facet_level_pair> facet_queue;
224 facet_queue.push(Facet_level_pair(facet, 0));
225 neighbors.insert(facet_queue.front());
227 while(!facet_queue.empty())
229 const Facet_level_pair& pair = facet_queue.front();
231 Facet_const_handle facet_front = pair.first;
232 Halfedge_const_iterator edge = facet_front->halfedge();
234 Vertex_const_iterator vertex = edge->vertex();
235 Halfedge_around_vertex_const_circulator vertex_circulator = vertex->vertex_begin();
237 if(!vertex_circulator->is_border())
239 Facet_level_pair new_pair(vertex_circulator->opposite()->facet(), pair.second + 1);
240 if(neighbors.insert(new_pair).second && new_pair.second < max_level)
242 facet_queue.push(new_pair);
245 }
while(++vertex_circulator != vertex->vertex_begin());
246 }
while((edge = edge->next()) != facet_front->halfedge());
255 #endif //CGAL_SURFACE_MESH_SEGMENTATION_FILTERS_H