edge_weight_computer.hpp
Go to the documentation of this file.
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2014-, Open Perception, Inc.
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of the copyright holder(s) nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38#ifndef PCL_GRAPH_IMPL_EDGE_WEIGHT_COMPUTER_CPP
39#define PCL_GRAPH_IMPL_EDGE_WEIGHT_COMPUTER_CPP
40
42#include "point_cloud_graph.h"
43#include "utils.h"
44
45namespace pcl
46{
47
48 namespace graph
49 {
50
51 namespace detail
52 {
53
54 /** A predicate to be used with pcl::graph::remove_edge_if, returns
55 * \c true when the edge wight is below a certain threshold.
56 *
57 * Properly handles both plain graphs and graphs wrapped in
58 * boost::subgraph. */
59 template <typename EdgeWeightMap>
61 {
62
63 remove_edge_predicate(const EdgeWeightMap& weights, float threshold) :
64 weights_(weights), threshold_(threshold)
65 {
66 }
67
68 template <typename EdgeDescriptor>
69 bool
70 operator()(EdgeDescriptor e) const
71 {
72 return (weights_[e] < threshold_);
73 }
74
75 const EdgeWeightMap& weights_;
77 };
78
79 /** A helper functor to determine if two points are convex with respect
80 * to each other.
81 *
82 * Returns \c false if the point type does not have *curvature* field.
83 * Otherwise the points are assumed to be relatively convex if both
84 * curvature values are positive. */
85 template <typename PointT, typename Enable = void>
86 struct IsConvex
87 {
88 bool
89 operator()(const PointT& p1, const PointT& p2) const
90 {
91 return false;
92 }
93 };
94
95 template <typename PointT>
96 struct IsConvex<PointT,
97 typename std::enable_if<pcl::traits::has_curvature<PointT>>::type>
98 {
99 bool
100 operator()(const PointT& p1, const PointT& p2) const
101 {
102 return (p1.curvature > 0.0f && p2.curvature > 0.0f);
103 }
104 };
105
106 } // namespace detail
107
108 } // namespace graph
109
110} // namespace pcl
111
112template <typename GraphT>
113template <class EdgeWeightMap>
114void
116{
117 typename boost::graph_traits<GraphT>::edge_iterator ei, ee;
118
119 // Step 1: do precomputation for normalized terms (if any).
120 if (g_terms_.size() || l_terms_.size())
121 {
122 for (size_t i = 0; i < g_terms_.size(); ++i)
123 {
124 g_terms_[i].init(boost::num_edges(graph));
125 }
126 for (size_t i = 0; i < l_terms_.size(); ++i)
127 {
128 l_terms_[i].init(boost::num_edges(graph), boost::num_vertices(graph));
129 }
130
131 size_t edge_id = 0;
132 for (boost::tie(ei, ee) = boost::edges(graph); ei != ee; ++ei, ++edge_id)
133 {
134 typename boost::graph_traits<GraphT>::vertex_descriptor v1, v2;
135 v1 = boost::source(*ei, graph), v2 = boost::target(*ei, graph);
136 for (size_t i = 0; i < g_terms_.size(); ++i)
137 {
138 g_terms_[i].round1(graph[v1], graph[v2], edge_id);
139 }
140 for (size_t i = 0; i < l_terms_.size(); ++i)
141 {
142 l_terms_[i].round1(graph[v1], graph[v2], v1, v2, edge_id);
143 }
144 }
145
146 for (size_t i = 0; i < g_terms_.size(); ++i)
147 {
148 g_terms_[i].extract();
149 }
150 for (size_t i = 0; i < l_terms_.size(); ++i)
151 {
152 l_terms_[i].extract();
153 }
154 }
155
156 // Step 2: compute weight for each edge.
157 detail::IsConvex<PointT> is_convex;
158
159 size_t edge_id = 0;
160 for (boost::tie(ei, ee) = boost::edges(graph); ei != ee; ++ei, ++edge_id)
161 {
162 typename boost::graph_traits<GraphT>::vertex_descriptor v1, v2;
163 v1 = boost::source(*ei, graph), v2 = boost::target(*ei, graph);
164 const PointT& p1 = graph[v1];
165 const PointT& p2 = graph[v2];
166 float a = 1.0;
167 for (size_t i = 0; i < terms_.size(); ++i)
168 {
169 a *= balancing_function_(terms_[i].compute_(p1, p2),
170 terms_[i].getInfluence(is_convex(p1, p2)));
171 }
172 for (size_t i = 0; i < g_terms_.size(); ++i)
173 {
174 a *= balancing_function_(g_terms_[i].round2(edge_id),
175 g_terms_[i].getInfluence(is_convex(p1, p2)));
176 }
177 for (size_t i = 0; i < l_terms_.size(); ++i)
178 {
179 a *= balancing_function_(l_terms_[i].round2(v1, v2, edge_id),
180 l_terms_[i].getInfluence(is_convex(p1, p2)));
181 }
182 weights[*ei] = a;
183 }
184
185 // Step 3: find edges with very small weight and modify them according to the
186 // policy set by the user.
187 switch (policy_)
188 {
190 {
191 break;
192 }
194 {
195 typedef typename boost::graph_traits<GraphT>::edge_iterator EdgeIterator;
196 EdgeIterator ei, ee;
197 for (boost::tie(ei, ee) = boost::edges(graph); ei != ee; ++ei)
198 if (weights[*ei] < threshold_)
199 {
200 weights[*ei] = threshold_;
201 }
202 break;
203 }
205 {
206 // Note: it is only okay to remove edges this way before any subgraph
207 // was created.
208 detail::remove_edge_predicate<EdgeWeightMap> predicate(weights, threshold_);
210 re(predicate, graph);
211 break;
212 }
213 }
214}
215
216#endif /* PCL_GRAPH_IMPL_EDGE_WEIGHT_COMPUTER_HPP */
@ SMALL_WEIGHT_COERCE_TO_THRESHOLD
Coerce the weight to the threshold.
@ SMALL_WEIGHT_REMOVE_EDGE
Remove edges with weights below threshold.
@ SMALL_WEIGHT_IGNORE
Do nothing, leave the weights and edges as is.
pcl::graph::point_cloud_graph_traits< GraphT >::point_type PointT
void compute(GraphT &graph, EdgeWeightMap weights)
Compute weights for the edges in a given graph.
Vertex source(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
A helper functor to determine if two points are convex with respect to each other.
bool operator()(const PointT &p1, const PointT &p2) const
A predicate to be used with pcl::graph::remove_edge_if, returns true when the edge wight is below a c...
remove_edge_predicate(const EdgeWeightMap &weights, float threshold)
remove_edge_if structure is an "extended" version of, boost::remove_edge_if that incorporates a worka...
Definition utils.h:62