tools.cpp
Go to the documentation of this file.
1#include "tools.h"
2
3#include <SimoxUtility/math/periodic/periodic_diff.h>
4#include <SimoxUtility/math/periodic/periodic_mean.h>
5
6Eigen::Vector3f
7visionx::pointCloudMedian(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud,
8 const pcl::PointIndices& indices)
9{
10 std::vector<float> xs, ys, zs;
11 xs.reserve(cloud.size());
12 ys.reserve(cloud.size());
13 zs.reserve(cloud.size());
14
15 auto processPoint = [&](const auto& p)
16 {
17 xs.push_back(p.x);
18 ys.push_back(p.y);
19 zs.push_back(p.z);
20 };
21
22 if (indices.indices.empty())
23 {
24 for (const auto& p : cloud)
25 {
26 processPoint(p);
27 }
28 }
29 else
30 {
31 for (int i : indices.indices)
32 {
33 processPoint(cloud.at(size_t(i)));
34 }
35 }
36
37 std::sort(xs.begin(), xs.end());
38 std::sort(ys.begin(), ys.end());
39 std::sort(zs.begin(), zs.end());
40
41 size_t index = cloud.size() / 2;
42 return Eigen::Vector3f(xs[index], ys[index], zs[index]);
43}
44
46visionx::fitPlaneSVD(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud, Eigen::Vector3f center)
47{
48 return fitPlaneSVD(cloud, pcl::PointIndices(), center);
49}
50
52visionx::fitPlaneSVD(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud,
53 const pcl::PointIndices& indices,
54 Eigen::Vector3f center)
55{
56 /* Find SVD of A:
57 * [ ]
58 * [ (c1-c) ... (cm-c) ] (3xm)
59 * [ ]
60 *
61 * Best normal is left singular vector of least singular value
62 * according to: https://math.stackexchange.com/a/99317
63 */
64
65 // Build A
67
68 MatT A;
69 if (indices.indices.empty())
70 {
71 // A = Eigen::MatrixXf(3, cloud.size());
72 A = MatT(3, cloud.size());
73 for (size_t i = 0; i < cloud.size(); ++i)
74 {
75 A.col(int(i)) = Eigen::Vector3f(cloud[i].data) - center;
76 }
77 }
78 else
79 {
80 int i = 0;
81 A = MatT(3, indices.indices.size());
82 for (int index : indices.indices)
83 {
84 A.col(i++) = Eigen::Vector3f(cloud.at(size_t(index)).data) - center;
85 }
86 }
87
88 // Compute SVD
89 Eigen::JacobiSVD<MatT> svd(A, Eigen::ComputeFullU);
90
91 // A is 3xm => U is 3x3, V is mxm
92 Eigen::Vector3f normal = svd.matrixU().col(2);
93
94 return Eigen::Hyperplane3f(normal, center);
95}
96
97pcl::PointIndicesPtr
98visionx::getPlaneInliers(const pcl::PointCloud<pcl::PointXYZRGBA>& cloud,
100 float maxDistance)
101{
102 pcl::PointIndicesPtr inliers(new pcl::PointIndices);
103 for (size_t i = 0; i < cloud.size(); ++i)
104 {
105 if (plane.absDistance(Eigen::Vector3f(cloud[i].data)) <= maxDistance)
106 {
107 inliers->indices.push_back(int(i));
108 }
109 }
110 return inliers;
111}
112
113float
114visionx::hsvDistance(const pcl::PointXYZHSV& lhs,
115 const pcl::PointXYZHSV& rhs,
116 const Eigen::Vector3f& hsvWeights)
117{
118 return hsvDistance(
119 Eigen::Vector3f(lhs.h, lhs.s, lhs.v), Eigen::Vector3f(rhs.h, rhs.s, rhs.v), hsvWeights);
120}
121
122float
123visionx::hsvDistance(const Eigen::Vector3f& lhs,
124 const Eigen::Vector3f& rhs,
125 const Eigen::Vector3f& hsvWeights)
126{
127 Eigen::Array3f dists(simox::math::periodic_diff(lhs.x(), rhs.x(), 0.f, 360.f) / 180.f,
128 lhs.y() - rhs.y(),
129 lhs.z() - rhs.z());
130 Eigen::Array3f weighted = hsvWeights.normalized().array() * dists.abs();
131 return weighted.sum();
132}
133
134Eigen::Vector3f
135visionx::hsvMean(const pcl::PointCloud<pcl::PointXYZHSV>& hsvCloud, const std::vector<int>& indices)
136{
137 // Average color.
138 std::vector<float> hues;
139 hues.reserve(indices.size());
140 float s = 0, v = 0;
141 for (int i : indices)
142 {
143 const auto& p = hsvCloud.at(size_t(i));
144 hues.push_back(p.h);
145 s += p.s;
146 v += p.v;
147 }
148 float h = simox::math::periodic_mean(hues, 0.f, 360.f);
149 Eigen::Vector3f hsv(h, s / indices.size(), v / indices.size());
150 return hsv;
151}
152
154visionx::alignPlaneNormal(const Eigen::Hyperplane3f plane, const Eigen::Vector3f normal)
155{
156 return plane.normal().dot(normal) >= 0 ? plane
157 : Eigen::Hyperplane3f(-plane.normal(), -plane.offset());
158}
uint8_t data[1]
uint8_t index
class A(deque< T, A >)) ARMARX_OVERLOAD_STD_HASH_FOR_ITERABLE((class T
Enables hashing of std::list.
Hyperplane< float, 3 > Hyperplane3f
Definition Elements.h:34
pcl::PointIndicesPtr getPlaneInliers(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, Eigen::Hyperplane3f plane, float maxDistance)
Definition tools.cpp:98
Eigen::Hyperplane3f fitPlaneSVD(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, const pcl::PointIndices &indices, Eigen::Vector3f center=Eigen::Vector3f::Zero())
Definition tools.cpp:52
float hsvDistance(const pcl::PointXYZHSV &lhs, const pcl::PointXYZHSV &rhs, const Eigen::Vector3f &hsvWeights=Eigen::Vector3f::Ones())
Definition tools.cpp:114
Eigen::Hyperplane3f alignPlaneNormal(Eigen::Hyperplane3f plane, Eigen::Vector3f normal)
Flip plane if its normal does not point towards normal.
Definition tools.cpp:154
Eigen::Vector3f pointCloudMedian(const pcl::PointCloud< pcl::PointXYZRGBA > &cloud, const pcl::PointIndices &indices={})
Definition tools.cpp:7
Eigen::Vector3f hsvMean(const pcl::PointCloud< pcl::PointXYZHSV > &hsvCloud, const std::vector< int > &indices)
Definition tools.cpp:135