DenseCRFFeatureTerms.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ROBDEKON::ArmarXObjects::DenseCRFSegmentationProcessor
17 * @author Christoph Pohl ( christoph dot pohl at kit dot edu )
18 * @date 2019
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23
24#ifndef ROBDEKON_DENSECRFFEATURETERMS_H
25#define ROBDEKON_DENSECRFFEATURETERMS_H
26
27#include <pcl/pcl_macros.h>
28
30
31#include "Common.h"
32
33namespace armarx
34{
35
36
37 template <class GraphT>
39 {
40 typedef typename GraphT::vertex_descriptor VertexId;
41
42 protected:
43 GraphT& _graph;
44 const long unsigned int _num_features = 3;
45
46 public:
47 explicit XYZFeature(GraphT& graph) : _graph(graph){};
48
49 const Eigen::MatrixXf
50 computeFeatures(std::vector<float> sigma)
51 {
53 const int N = boost::num_vertices(_graph);
54 Eigen::MatrixXf features(_num_features, N);
55 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
56 {
57 Eigen::Vector3f xyz = _graph[i].getVector3fMap();
58 features(0, i) = xyz[0] / exp(sigma[0]);
59 features(1, i) = xyz[1] / exp(sigma[1]);
60 features(2, i) = xyz[2] / exp(sigma[2]);
61 }
62 return features;
63 }
64 };
65
66 template <class GraphT>
68 {
69 typedef typename GraphT::vertex_descriptor VertexId;
70
71 protected:
72 GraphT& _graph;
73 const long unsigned int _num_features = 3;
74
75 public:
76 explicit NormalFeature(GraphT& graph) : _graph(graph){};
77
78 const Eigen::MatrixXf
79 computeFeatures(std::vector<float> sigma)
80 {
82 const int N = boost::num_vertices(_graph);
83 Eigen::MatrixXf features(_num_features, N);
84 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
85 {
86 Eigen::Vector3f normal = _graph[i].getNormalVector3fMap();
87 features(0, i) = isfinite(normal[0]) ? normal[0] / exp(sigma[0]) : 0;
88 features(1, i) = isfinite(normal[1]) ? normal[1] / exp(sigma[1]) : 0;
89 features(2, i) = isfinite(normal[2]) ? normal[2] / exp(sigma[2]) : 0;
90 }
91 return features;
92 }
93 };
94
95 template <class GraphT>
97 {
98 typedef typename GraphT::vertex_descriptor VertexId;
99
100 protected:
101 GraphT& _graph;
102 const long unsigned int _num_features = 1;
103
104 public:
105 explicit CurvatureFeature(GraphT& graph) : _graph(graph){};
106
107 const Eigen::MatrixXf
108 computeFeatures(std::vector<float> sigma)
109 {
110 ARMARX_CHECK_EXPRESSION(_num_features == sigma.size());
111 const int N = boost::num_vertices(_graph);
112 Eigen::MatrixXf features(_num_features, N);
113 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
114 {
115 float curv = std::fabs(_graph[i].curvature);
116 ;
117 features(0, i) = curv / exp(sigma[0]);
118 }
119 return features;
120 }
121 };
122
123 template <class GraphT>
125 {
126 typedef typename GraphT::vertex_descriptor VertexId;
127
128 protected:
129 GraphT& _graph;
130 const long unsigned int _num_features = 3;
131
132 public:
133 explicit RGBFeature(GraphT& graph) : _graph(graph){};
134
135 const Eigen::MatrixXf
136 computeFeatures(std::vector<float> sigma)
137 {
138 ARMARX_CHECK_EXPRESSION(_num_features == sigma.size());
139 const int N = boost::num_vertices(_graph);
140 Eigen::MatrixXf features(_num_features, N);
141 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
142 {
143 Eigen::Vector3f rgb = _graph[i].getBGRVector3cMap().template cast<float>() / 255.0f;
144 features(0, i) = rgb[0] / exp(sigma[0]);
145 features(1, i) = rgb[1] / exp(sigma[1]);
146 features(2, i) = rgb[2] / exp(sigma[2]);
147 }
148 return features;
149 }
150 };
151
152 template <class GraphT>
154 {
155 typedef typename GraphT::vertex_descriptor VertexId;
156
157 protected:
158 GraphT& _graph;
159 const long unsigned int _num_features = 11;
160
161 public:
162 explicit CombinedFeature(GraphT& graph) : _graph(graph){};
163
164 const Eigen::MatrixXf
165 computeFeatures(std::vector<float> sigma)
166 {
167 ARMARX_CHECK_EXPRESSION(_num_features == sigma.size());
168 const int N = boost::num_vertices(_graph);
169 Eigen::MatrixXf features(_num_features, N);
170 TimestampMap time = boost::get(boost::vertex_timestamp_t(), _graph.m_graph);
171 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
172 {
173 Eigen::Vector3f rgb = _graph[i].getBGRVector3cMap().template cast<float>() / 255.0f;
174 features(0, i) = rgb[0] / exp(sigma[0]);
175 features(1, i) = rgb[1] / exp(sigma[1]);
176 features(2, i) = rgb[2] / exp(sigma[2]);
177
178 Eigen::Vector3f normal = _graph[i].getNormalVector3fMap();
179 features(3, i) = std::isfinite(normal[0]) ? normal[0] / exp(sigma[3]) : 0.0;
180 features(4, i) = std::isfinite(normal[1]) ? normal[1] / exp(sigma[4]) : 0.0;
181 features(5, i) = std::isfinite(normal[2]) ? normal[2] / exp(sigma[5]) : 0.0;
182
183 Eigen::Vector3f xyz = _graph[i].getVector3fMap();
184 features(6, i) = xyz[0] / exp(sigma[6]);
185 features(7, i) = xyz[1] / exp(sigma[7]);
186 features(8, i) = xyz[2] / exp(sigma[8]);
187
188 // float curv = std::fabs(_graph[i].curvature);
189 float curv = _graph[i].curvature;
190 features(9, i) = std::isfinite(curv) ? curv / exp(sigma[9]) : 0.0;
191
192 features(10, i) = time[i] / exp(sigma[10]);
193 }
194 return features;
195 }
196 };
197
198 template <class GraphT>
200 {
201 typedef typename GraphT::vertex_descriptor VertexId;
202
203 protected:
204 GraphT& _graph;
206 const long unsigned int _num_features = calcNumFeatues();
207
208 public:
209 explicit VariableCombinedFeature(GraphT& graph,
210 bool useRGB,
211 bool useNormals,
212 bool useXYZ,
213 bool useCurvature,
214 bool useTime) :
215 _graph(graph),
216 useRGB(useRGB),
217 useNorm(useNormals),
218 useXYZ(useXYZ),
219 useCurv(useCurvature),
220 useTime(useTime){};
221
222 Eigen::MatrixXf
223 computeFeatures(std::vector<float> sigma)
224 {
225 ARMARX_CHECK_EXPRESSION(_num_features == sigma.size());
226 const int N = boost::num_vertices(_graph);
227 Eigen::MatrixXf features(_num_features, N);
228 TimestampMap time = boost::get(boost::vertex_timestamp_t(), _graph.m_graph);
229 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
230 {
231 int j = 0;
232 if (useRGB)
233 {
234 Eigen::Vector3f rgb =
235 _graph[i].getBGRVector3cMap().template cast<float>() / 255.0f;
236 features(j, i) = rgb[0] / exp(sigma[j]);
237 features(j + 1, i) = rgb[1] / exp(sigma[j + 1]);
238 features(j + 2, i) = rgb[2] / exp(sigma[j + 2]);
239 j += 3;
240 }
241
242 if (useNorm)
243 {
244 Eigen::Vector3f normal = _graph[i].getNormalVector3fMap();
245 features(j, i) = std::isfinite(normal[0]) ? normal[0] / exp(sigma[j]) : 0.0;
246 features(j + 1, i) =
247 std::isfinite(normal[1]) ? normal[1] / exp(sigma[j + 1]) : 0.0;
248 features(j + 2, i) =
249 std::isfinite(normal[2]) ? normal[2] / exp(sigma[j + 2]) : 0.0;
250 j += 3;
251 }
252
253 if (useXYZ)
254 {
255 Eigen::Vector3f xyz = _graph[i].getVector3fMap();
256 features(j, i) = xyz[0] / exp(sigma[j]);
257 features(j + 1, i) = xyz[1] / exp(sigma[j + 1]);
258 features(j + 2, i) = xyz[2] / exp(sigma[j + 2]);
259 j += 3;
260 }
261
262 if (useCurv)
263 {
264 // float curv = std::fabs(_graph[i].curvature);
265 float curv = _graph[i].curvature;
266 features(j, i) = std::isfinite(curv) ? curv / exp(sigma[j]) : 0.0;
267 j++;
268 }
269
270 if (useTime)
271 {
272 features(j, i) = time[i] / exp(sigma[j]);
273 }
274 }
275 return features;
276 }
277
278 private:
279 long unsigned int
280 calcNumFeatues()
281 {
282 long unsigned int _num_feat = 0;
283 _num_feat += useRGB ? 3 : 0;
284 _num_feat += useNorm ? 3 : 0;
285 _num_feat += useXYZ ? 3 : 0;
286 _num_feat += useTime ? 1 : 0;
287 _num_feat += useCurv ? 1 : 0;
288 return _num_feat;
289 }
290 };
291
292 template <class GraphT>
294 {
295 typedef typename GraphT::vertex_descriptor VertexId;
296
297 protected:
298 GraphT& _graph;
300 const long unsigned int _num_features = calcNumFeatues();
301
302 public:
303 explicit VariableCombinedNormalizedFeature(GraphT& graph,
304 bool useRGB,
305 bool useNormals,
306 bool useXYZ,
307 bool useCurvature,
308 bool useTime) :
309 _graph(graph),
310 useRGB(useRGB),
311 useNorm(useNormals),
312 useXYZ(useXYZ),
313 useCurv(useCurvature),
314 useTime(useTime){};
315
316 Eigen::MatrixXf
317 computeFeatures(std::vector<float> sigma)
318 {
319 ARMARX_CHECK_EXPRESSION(_num_features == sigma.size());
320 const int N = boost::num_vertices(_graph);
321 Eigen::MatrixXf features(_num_features, N);
322 TimestampMap time = boost::get(boost::vertex_timestamp_t(), _graph.m_graph);
323 Eigen::MatrixXd meanAndStd(_num_features, 2);
324 meanAndStd = calculateMeanAndStd(_graph);
325 ARMARX_DEBUG << "Mean of Input Values: " << meanAndStd.col(0)
326 << "\n Standard Deviation of Input Values: " << meanAndStd.col(1);
327 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
328 {
329 int j = -1;
330 if (useRGB)
331 {
332 Eigen::Vector3f rgb =
333 _graph[i].getBGRVector3cMap().template cast<float>() / 255.0f;
334 ++j;
335 features(j, i) =
336 ((rgb[0] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j]);
337 ++j;
338 features(j, i) =
339 ((rgb[1] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j]);
340 ++j;
341 features(j, i) =
342 ((rgb[2] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j]);
343 }
344
345 if (useNorm)
346 {
347 Eigen::Vector3f normal = _graph[i].getNormalVector3fMap();
348 ++j;
349 features(j, i) =
350 std::isfinite(normal[0])
351 ? ((normal[0] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j])
352 : 0.0;
353 ++j;
354 features(j, i) =
355 std::isfinite(normal[1])
356 ? ((normal[1] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j])
357 : 0.0;
358 ++j;
359 features(j, i) =
360 std::isfinite(normal[2])
361 ? ((normal[2] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j])
362 : 0.0;
363 }
364
365 if (useXYZ)
366 {
367 Eigen::Vector3f xyz = _graph[i].getVector3fMap();
368 ++j;
369 features(j, i) =
370 ((xyz[0] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j]);
371 ++j;
372 features(j, i) =
373 ((xyz[1] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j]);
374 ++j;
375 features(j, i) =
376 ((xyz[2] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j]);
377 }
378
379 if (useCurv)
380 {
381 // float curv = std::fabs(_graph[i].curvature);
382 float curv = _graph[i].curvature;
383 ++j;
384 features(j, i) =
385 std::isfinite(curv)
386 ? ((curv - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j])
387 : 0.0;
388 }
389
390 if (useTime)
391 {
392 ++j;
393 features(j, i) =
394 ((time[i] - meanAndStd(j, 0)) / meanAndStd(j, 1)) / exp(sigma[j]);
395 }
396 }
397 return features;
398 }
399
400 private:
401 Eigen::MatrixXd
402 calculateMeanAndStd(GraphT& graph)
403 {
404 // this uses Welford's algorithm
405 // k = 0
406 // M = 0
407 // S = 0
408 // for x in x_array:
409 // k += 1
410 // Mnext = M + (x - M) / k
411 // S = S + (x - M)*(x - Mnext)
412 // M = Mnext
413 // return (M, S/(k-1))
414 Eigen::MatrixXd meanAndStd(_num_features, 2);
415 meanAndStd.setZero();
416 TimestampMap time = boost::get(boost::vertex_timestamp_t(), _graph.m_graph);
417 int k = 0;
418 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
419 {
420 // TODO: k might not be needed
421 k++;
422 Eigen::VectorXd x(_num_features);
423
424 int j = 0;
425 if (useRGB)
426 {
427 Eigen::Vector3f rgb =
428 _graph[i].getBGRVector3cMap().template cast<float>() / 255.0f;
429 x(j) = rgb[0];
430 x(j + 1) = rgb[1];
431 x(j + 2) = rgb[2];
432 j += 3;
433 }
434
435 if (useNorm)
436 {
437 Eigen::Vector3f normal = _graph[i].getNormalVector3fMap();
438 x(j) = std::isfinite(normal[0]) ? normal[0] : 0.0;
439 x(j + 1) = std::isfinite(normal[1]) ? normal[1] : 0.0;
440 x(j + 2) = std::isfinite(normal[2]) ? normal[2] : 0.0;
441 j += 3;
442 }
443
444 if (useXYZ)
445 {
446 Eigen::Vector3f xyz = _graph[i].getVector3fMap();
447 x(j) = xyz[0];
448 x(j + 1) = xyz[1];
449 x(j + 2) = xyz[2];
450 j += 3;
451 }
452
453 if (useCurv)
454 {
455 // float curv = std::fabs(_graph[i].curvature);
456 float curv = _graph[i].curvature;
457 x(j) = std::isfinite(curv) ? curv : 0.0;
458 j++;
459 }
460
461 if (useTime)
462 {
463 x(j) = time[i];
464 }
465 Eigen::VectorXd meanNext = meanAndStd.col(0) + (x - meanAndStd.col(0)) / double(k);
466 meanAndStd.col(1) += (x - meanAndStd.col(0)).cwiseProduct(x - meanNext);
467 meanAndStd.col(0) = meanNext;
468 }
469 // for the first image, all the timestamps are the same, resulting in variance of 0 --> breaks things
470 meanAndStd.col(1) = (meanAndStd.col(1) / double(k - 1)).cwiseSqrt().array() + 1e-8;
471 return meanAndStd;
472 }
473
474 long unsigned int
475 calcNumFeatues()
476 {
477 long unsigned int _num_feat = 0;
478 _num_feat += useRGB ? 3 : 0;
479 _num_feat += useNorm ? 3 : 0;
480 _num_feat += useXYZ ? 3 : 0;
481 _num_feat += useTime ? 1 : 0;
482 _num_feat += useCurv ? 1 : 0;
483 return _num_feat;
484 }
485 };
486
488 {
489 typedef typename GraphWithTimestamp::vertex_descriptor VertexId;
490
491 protected:
493 const long unsigned int _num_features = 1;
494
495 public:
496 explicit TimeFeature(GraphWithTimestamp& graph) : _graph(graph){};
497
498 const Eigen::MatrixXf
499 computeFeatures(std::vector<float> sigma)
500 {
501 ARMARX_CHECK_EXPRESSION(_num_features == sigma.size());
502 const int N = boost::num_vertices(_graph);
503 Eigen::MatrixXf features(_num_features, N);
504 TimestampMap time = boost::get(boost::vertex_timestamp_t(), _graph.m_graph);
505 for (VertexId i = 0; i < boost::num_vertices(_graph); i++)
506 {
507 features(0, i) = (time[i]) / exp(sigma[0]);
508 }
509 return features;
510 }
511 };
512} // namespace armarx
513#endif //ROBDEKON_DENSECRFFEATURETERMS_H
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
This file offers overloads of toIce() and fromIce() functions for STL container types.
boost::graph_traits< Graph >::vertex_descriptor VertexId
Definition Common.h:68
boost::property_map< CloudGraphWithTimestamp, boost::vertex_timestamp_t >::type TimestampMap
Definition Common.h:75
boost::subgraph< CloudGraphWithTimestamp > GraphWithTimestamp
Definition Common.h:59
bool isfinite(const std::vector< T, Ts... > &v)
Definition algorithm.h:366
GraphT::vertex_descriptor VertexId
const Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
const long unsigned int _num_features
GraphT::vertex_descriptor VertexId
const Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
const long unsigned int _num_features
GraphT::vertex_descriptor VertexId
const Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
const long unsigned int _num_features
GraphT::vertex_descriptor VertexId
const Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
const long unsigned int _num_features
const Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
GraphWithTimestamp & _graph
GraphWithTimestamp::vertex_descriptor VertexId
const long unsigned int _num_features
TimeFeature(GraphWithTimestamp &graph)
GraphT::vertex_descriptor VertexId
VariableCombinedFeature(GraphT &graph, bool useRGB, bool useNormals, bool useXYZ, bool useCurvature, bool useTime)
const long unsigned int _num_features
Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
VariableCombinedNormalizedFeature(GraphT &graph, bool useRGB, bool useNormals, bool useXYZ, bool useCurvature, bool useTime)
Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
GraphT::vertex_descriptor VertexId
const Eigen::MatrixXf computeFeatures(std::vector< float > sigma)
const long unsigned int _num_features