cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
vfh_extractor.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cmath>
5#include <vector>
6
12
13namespace toolbox::pcl
14{
15
16template<typename DataType>
17struct vfh_signature_t : public base_signature_t<DataType, vfh_signature_t<DataType>>
18{
19 static constexpr std::size_t HISTOGRAM_SIZE = 308; // 4*45 + 128
20 std::array<DataType, HISTOGRAM_SIZE> histogram {};
21
22 DataType distance_impl(const vfh_signature_t& other) const
23 {
24 DataType dist = 0;
25 for (std::size_t i = 0; i < HISTOGRAM_SIZE; ++i) {
26 DataType diff = histogram[i] - other.histogram[i];
27 dist += diff * diff;
28 }
29 return std::sqrt(dist);
30 }
31};
32
33template<typename DataType,
34 typename KNN = kdtree_generic_t<point_t<DataType>, toolbox::metrics::L2Metric<DataType>>>
36 : public base_descriptor_extractor_t<vfh_extractor_t<DataType, KNN>,
37 DataType,
38 vfh_signature_t<DataType>>
39{
40public:
41 vfh_extractor_t() = default;
42
44 {
45 cloud_ = &cloud;
46 return cloud.size();
47 }
48
49 std::size_t set_knn(KNN& knn)
50 {
51 knn_ = &knn;
52 return cloud_ ? cloud_->size() : 0;
53 }
54
55 std::size_t set_search_radius(DataType radius)
56 {
57 search_radius_ = radius;
58 return cloud_ ? cloud_->size() : 0;
59 }
60
61 std::size_t set_num_neighbors(std::size_t num_neighbors)
62 {
63 num_neighbors_ = num_neighbors;
64 return cloud_ ? cloud_->size() : 0;
65 }
66
67 void enable_parallel_impl(bool enable) { enable_parallel_ = enable; }
68
70 const std::vector<std::size_t>& keypoint_indices,
71 std::vector<vfh_signature_t<DataType>>& descriptors) const
72 {
73 descriptors.clear();
74
75 // VFH is a global descriptor - compute for the entire cloud
76 // Ignore keypoint_indices and process all points
77
78 // Compute centroid
79 toolbox::types::point_t<DataType> centroid(0, 0, 0);
80 for (const auto& point : cloud.points) {
81 centroid.x += point.x;
82 centroid.y += point.y;
83 centroid.z += point.z;
84 }
85 centroid.x /= cloud.points.size();
86 centroid.y /= cloud.points.size();
87 centroid.z /= cloud.points.size();
88
89 // Compute normals if not provided
90 std::vector<toolbox::types::point_t<DataType>> normals;
91 compute_normals(cloud, normals);
92
93 // Compute viewpoint vector (from centroid to viewpoint)
95 0, 0, 100); // Default viewpoint
96
97 // Compute VFH
99 compute_vfh(cloud, normals, centroid, viewpoint, vfh);
100
101 descriptors.push_back(vfh);
102 }
103
106 const std::vector<std::size_t>& keypoint_indices,
107 std::unique_ptr<std::vector<vfh_signature_t<DataType>>> descriptors) const
108 {
109 descriptors->clear();
110 compute_impl(cloud, keypoint_indices, *descriptors);
111 }
112
113private:
114 void compute_normals(
116 std::vector<toolbox::types::point_t<DataType>>& normals) const
117 {
118 if (!knn_)
119 return;
120
122 normal_estimator.set_input(cloud);
123 normal_estimator.set_knn(*knn_);
124 normal_estimator.set_num_neighbors(num_neighbors_);
125 normal_estimator.enable_parallel(enable_parallel_);
126
127 auto normal_cloud = normal_estimator.extract();
128 normals.clear();
129 normals.reserve(normal_cloud.size());
130 for (const auto& pt : normal_cloud.points) {
131 normals.push_back(pt);
132 }
133 }
134
135 void compute_vfh(
137 const std::vector<toolbox::types::point_t<DataType>>& normals,
138 const toolbox::types::point_t<DataType>& centroid,
139 const toolbox::types::point_t<DataType>& viewpoint,
140 vfh_signature_t<DataType>& vfh) const
141 {
142 const std::size_t nr_bins_f1 = 45;
143 const std::size_t nr_bins_f2 = 45;
144 const std::size_t nr_bins_f3 = 45;
145 const std::size_t nr_bins_f4 = 45;
146 const std::size_t nr_bins_vp = 128;
147
148 // Initialize histogram
149 std::fill(vfh.histogram.begin(), vfh.histogram.end(), 0);
150
151 // Viewpoint direction from centroid
152 auto vp_dir = viewpoint;
153 vp_dir.x -= centroid.x;
154 vp_dir.y -= centroid.y;
155 vp_dir.z -= centroid.z;
156 auto vp_norm = vp_dir.normalize();
157
158 // Compute extended FPFH for all point pairs
159 for (std::size_t i = 0; i < cloud.points.size(); ++i) {
160 const auto& pi = cloud.points[i];
161 const auto& ni = normals[i];
162
163 // Compute angle between normal and viewpoint direction
164 DataType vp_angle = std::acos(std::min<DataType>(
165 1.0,
166 std::max<DataType>(
167 -1.0, ni.x * vp_norm.x + ni.y * vp_norm.y + ni.z * vp_norm.z)));
168
169 // Add to viewpoint component histogram
170 std::size_t vp_bin =
171 static_cast<std::size_t>(vp_angle / M_PI * nr_bins_vp);
172 if (vp_bin >= nr_bins_vp)
173 vp_bin = nr_bins_vp - 1;
174 vfh.histogram[180 + vp_bin] += 1.0;
175
176 // Compute FPFH features with other points
177 for (std::size_t j = i + 1; j < cloud.points.size(); ++j) {
178 const auto& pj = cloud.points[j];
179 const auto& nj = normals[j];
180
181 // Compute features between points i and j
182 auto d = pj;
183 d.x -= pi.x;
184 d.y -= pi.y;
185 d.z -= pi.z;
186 DataType dist = std::sqrt(d.x * d.x + d.y * d.y + d.z * d.z);
187
188 if (dist < 1e-8)
189 continue;
190
191 d.x /= dist;
192 d.y /= dist;
193 d.z /= dist;
194
195 // Compute angles
196 DataType f1 = ni.x * d.x + ni.y * d.y + ni.z * d.z;
197 DataType f2 = (d.x * nj.x + d.y * nj.y + d.z * nj.z) - f1;
198 DataType f3 = std::atan2(ni.y * d.z - ni.z * d.y,
199 ni.x * d.x + ni.y * d.y + ni.z * d.z);
200 DataType f4 = std::atan2(nj.y * d.z - nj.z * d.y,
201 nj.x * d.x + nj.y * d.y + nj.z * d.z)
202 - f3;
203
204 // Normalize angles
205 f1 = (f1 + 1.0) * 0.5; // [0, 1]
206 f2 = (f2 + 1.0) * 0.5; // [0, 1]
207 f3 = (f3 + M_PI) / (2.0 * M_PI); // [0, 1]
208 f4 = (f4 + M_PI) / (2.0 * M_PI); // [0, 1]
209
210 // Compute bins
211 std::size_t bin_f1 = static_cast<std::size_t>(f1 * nr_bins_f1);
212 std::size_t bin_f2 = static_cast<std::size_t>(f2 * nr_bins_f2);
213 std::size_t bin_f3 = static_cast<std::size_t>(f3 * nr_bins_f3);
214 std::size_t bin_f4 = static_cast<std::size_t>(f4 * nr_bins_f4);
215
216 if (bin_f1 >= nr_bins_f1)
217 bin_f1 = nr_bins_f1 - 1;
218 if (bin_f2 >= nr_bins_f2)
219 bin_f2 = nr_bins_f2 - 1;
220 if (bin_f3 >= nr_bins_f3)
221 bin_f3 = nr_bins_f3 - 1;
222 if (bin_f4 >= nr_bins_f4)
223 bin_f4 = nr_bins_f4 - 1;
224
225 // Update histogram
226 vfh.histogram[bin_f1] += 1.0;
227 vfh.histogram[45 + bin_f2] += 1.0;
228 vfh.histogram[90 + bin_f3] += 1.0;
229 vfh.histogram[135 + bin_f4] += 1.0;
230 }
231 }
232
233 // Normalize histogram
234 DataType sum = 0;
235 for (auto& val : vfh.histogram) {
236 sum += val;
237 }
238 if (sum > 0) {
239 for (auto& val : vfh.histogram) {
240 val /= sum;
241 }
242 }
243 }
244
245private:
246 const toolbox::types::point_cloud_t<DataType>* cloud_ = nullptr;
247 KNN* knn_ = nullptr;
248 DataType search_radius_ = 0.1;
249 std::size_t num_neighbors_ = 10;
250 bool enable_parallel_ = true;
251};
252
253} // namespace toolbox::pcl
Definition vector_metrics.hpp:18
描述子提取器的基类(CRTP模式) / Base class for descriptor extractors (CRTP pattern)
Definition base_descriptor_extractor.hpp:91
基于PCA的法向量提取器 / PCA-based normal extractor
Definition pca_norm.hpp:56
void enable_parallel(bool enable)
启用或禁用并行计算 / Enable or disable parallel computation
Definition pca_norm.hpp:120
Definition vfh_extractor.hpp:39
void compute_impl(const toolbox::types::point_cloud_t< DataType > &cloud, const std::vector< std::size_t > &keypoint_indices, std::unique_ptr< std::vector< vfh_signature_t< DataType > > > descriptors) const
Definition vfh_extractor.hpp:104
std::size_t set_knn(KNN &knn)
Definition vfh_extractor.hpp:49
std::size_t set_search_radius(DataType radius)
Definition vfh_extractor.hpp:55
std::size_t set_input(const toolbox::types::point_cloud_t< DataType > &cloud)
Definition vfh_extractor.hpp:43
void enable_parallel_impl(bool enable)
Definition vfh_extractor.hpp:67
std::size_t set_num_neighbors(std::size_t num_neighbors)
Definition vfh_extractor.hpp:61
void compute_impl(const toolbox::types::point_cloud_t< DataType > &cloud, const std::vector< std::size_t > &keypoint_indices, std::vector< vfh_signature_t< DataType > > &descriptors) const
Definition vfh_extractor.hpp:69
包含点和相关数据的点云类 / A point cloud class containing points and associated data
Definition point.hpp:268
std::vector< point_t< T > > points
点坐标 / Point coordinates
Definition point.hpp:270
auto size() const -> std::size_t
获取点云中的点数 / Get number of points in cloud
Definition point_impl.hpp:293
TContainer::value_type sum(const TContainer &data)
计算容器中元素的总和(返回容器元素类型)/Compute the sum of elements in the container (returns container element type)
Definition statistics.hpp:288
Definition base_correspondence_generator.hpp:18
描述子签名的基类 / Base class for descriptor signatures
Definition base_descriptor_extractor.hpp:38
Definition vfh_extractor.hpp:18
std::array< DataType, HISTOGRAM_SIZE > histogram
Definition vfh_extractor.hpp:20
DataType distance_impl(const vfh_signature_t &other) const
Definition vfh_extractor.hpp:22
static constexpr std::size_t HISTOGRAM_SIZE
Definition vfh_extractor.hpp:19
3D点/向量模板类 / A 3D point/vector template class
Definition point.hpp:48
T x
X坐标 / X coordinate.
Definition point.hpp:51
T z
Z坐标 / Z coordinate.
Definition point.hpp:53
T y
Y坐标 / Y coordinate.
Definition point.hpp:52