cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
super_four_pcs_registration_impl.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <numeric>
5#include <optional>
6#include <unordered_set>
7
11
12namespace toolbox::pcl
13{
14
15// Smart Index 实现 / Smart Index implementation
16template<typename DataType>
18 const point_cloud_ptr& cloud, const std::vector<std::size_t>& indices)
19{
20 m_cloud = cloud;
21 m_grid.clear();
22
23 if (indices.empty())
24 return;
25
26 // 计算边界 / Compute bounds
27 m_min_bound = vector3_t(std::numeric_limits<DataType>::max(),
28 std::numeric_limits<DataType>::max(),
29 std::numeric_limits<DataType>::max());
30 m_max_bound = vector3_t(std::numeric_limits<DataType>::lowest(),
31 std::numeric_limits<DataType>::lowest(),
32 std::numeric_limits<DataType>::lowest());
33
34 for (std::size_t idx : indices) {
35 const auto& pt = cloud->points[idx];
36 vector3_t p(pt.x, pt.y, pt.z);
37 m_min_bound = m_min_bound.cwiseMin(p);
38 m_max_bound = m_max_bound.cwiseMax(p);
39 }
40
41 // 添加边界填充 / Add boundary padding
42 m_min_bound -= vector3_t::Constant(m_cell_size);
43 m_max_bound += vector3_t::Constant(m_cell_size);
44
45 // 将点插入网格 / Insert points into grid
46 for (std::size_t idx : indices) {
47 const auto& pt = cloud->points[idx];
48 vector3_t p(pt.x, pt.y, pt.z);
49 auto key = compute_grid_key(p);
50 m_grid[key].point_indices.push_back(idx);
51 }
52}
53
54template<typename DataType>
55std::vector<typename super_four_pcs_registration_t<DataType>::point_pair_t>
57 DataType distance, DataType epsilon, std::size_t max_pairs) const
58{
59 std::vector<point_pair_t> pairs;
60 pairs.reserve(max_pairs);
61
62 const DataType min_dist = distance - epsilon;
63 const DataType max_dist = distance + epsilon;
64 const DataType min_dist_sq = min_dist * min_dist;
65 const DataType max_dist_sq = max_dist * max_dist;
66
67 // 计算搜索半径(网格单元数) / Compute search radius (in grid cells)
68 int search_radius = static_cast<int>(std::ceil(max_dist / m_cell_size));
69
70 // 遍历所有网格单元 / Iterate through all grid cells
71 for (const auto& [center_key, center_cell] : m_grid) {
72 if (center_cell.point_indices.empty())
73 continue;
74
75 // 获取邻域单元 / Get neighborhood cells
76 auto neighbor_keys = get_neighbor_cells(center_key, search_radius);
77
78 // 在邻域内搜索点对 / Search for pairs in neighborhood
79 for (const auto& neighbor_key : neighbor_keys) {
80 auto it = m_grid.find(neighbor_key);
81 if (it == m_grid.end())
82 continue;
83
84 const auto& neighbor_cell = it->second;
85
86 // 检查所有点对 / Check all point pairs
87 for (std::size_t i : center_cell.point_indices) {
88 const auto& pt1 = m_cloud->points[i];
89 vector3_t p1(pt1.x, pt1.y, pt1.z);
90
91 // 确定搜索起点(避免重复) / Determine search start (avoid duplicates)
92 std::size_t start_j = (center_key == neighbor_key)
93 ? std::distance(center_cell.point_indices.begin(),
94 std::find(center_cell.point_indices.begin(),
95 center_cell.point_indices.end(),
96 i))
97 + 1
98 : 0;
99
100 for (std::size_t j_idx = start_j;
101 j_idx < neighbor_cell.point_indices.size();
102 ++j_idx)
103 {
104 std::size_t j = neighbor_cell.point_indices[j_idx];
105 if (i == j)
106 continue;
107
108 const auto& pt2 = m_cloud->points[j];
109 vector3_t p2(pt2.x, pt2.y, pt2.z);
110
111 DataType dist_sq = (p2 - p1).squaredNorm();
112
113 if (dist_sq >= min_dist_sq && dist_sq <= max_dist_sq) {
114 point_pair_t pair;
115 pair.idx1 = i;
116 pair.idx2 = j;
117 pair.distance = std::sqrt(dist_sq);
118 pairs.push_back(pair);
119
120 if (pairs.size() >= max_pairs) {
121 return pairs;
122 }
123 }
124 }
125 }
126 }
127 }
128
129 return pairs;
130}
131
132template<typename DataType>
133std::string
135{
136 std::stringstream ss;
137 ss << "Smart Index Statistics:\n";
138 ss << " Grid cells: " << m_grid.size() << "\n";
139 ss << " Cell size: " << m_cell_size << "\n";
140 ss << " Bounds: [" << m_min_bound.transpose() << "] to ["
141 << m_max_bound.transpose() << "]\n";
142
143 std::size_t total_points = 0;
144 std::size_t max_points_per_cell = 0;
145 for (const auto& [key, cell] : m_grid) {
146 total_points += cell.point_indices.size();
147 max_points_per_cell =
148 std::max(max_points_per_cell, cell.point_indices.size());
149 }
150
151 ss << " Total indexed points: " << total_points << "\n";
152 ss << " Max points per cell: " << max_points_per_cell << "\n";
153 ss << " Avg points per cell: "
154 << static_cast<double>(total_points) / m_grid.size() << "\n";
155
156 return ss.str();
157}
158
159template<typename DataType>
160std::tuple<int, int, int>
162 const vector3_t& pt) const
163{
164 int x = static_cast<int>(std::floor((pt[0] - m_min_bound[0]) / m_cell_size));
165 int y = static_cast<int>(std::floor((pt[1] - m_min_bound[1]) / m_cell_size));
166 int z = static_cast<int>(std::floor((pt[2] - m_min_bound[2]) / m_cell_size));
167 return std::make_tuple(x, y, z);
168}
169
170template<typename DataType>
171std::vector<std::tuple<int, int, int>>
173 const std::tuple<int, int, int>& center_key, int radius) const
174{
175 std::vector<std::tuple<int, int, int>> neighbors;
176
177 auto [cx, cy, cz] = center_key;
178
179 for (int dx = -radius; dx <= radius; ++dx) {
180 for (int dy = -radius; dy <= radius; ++dy) {
181 for (int dz = -radius; dz <= radius; ++dz) {
182 neighbors.emplace_back(cx + dx, cy + dy, cz + dz);
183 }
184 }
185 }
186
187 return neighbors;
188}
189
190// Super4PCS 主实现 / Super4PCS main implementation
191template<typename DataType>
193{
194 // 如果禁用智能索引,使用基类实现 / If smart indexing disabled, use base class
195 // implementation
196 if (!m_use_smart_indexing) {
197 LOG_DEBUG_S << "Super4PCS: 智能索引已禁用,使用标准4PCS / Smart indexing "
198 "disabled, using standard 4PCS";
199 return base_type::align_impl(result);
200 }
201
202 // 初始化结果 / Initialize result
203 result.transformation.setIdentity();
204 result.fitness_score = std::numeric_limits<DataType>::max();
205 result.inliers.clear();
206 result.num_iterations = 0;
207 result.converged = false;
208
209 LOG_DEBUG_S << "Super4PCS: 开始配准(智能索引模式) / Starting registration "
210 "(smart indexing mode)"
211 << ", 源点云大小 / source size: "
212 << this->get_source_cloud()->size()
213 << ", 目标点云大小 / target size: "
214 << this->get_target_cloud()->size();
215
216 // 计时器 / Timer
217 toolbox::utils::stop_watch_timer_t timer("Super4PCS");
218 timer.start();
219
220 // 获取采样点 / Get sampled points
221 const auto& source_samples = this->get_source_samples();
222 const auto& target_samples = this->get_target_samples();
223
224 if (source_samples.empty() || target_samples.empty()) {
225 LOG_ERROR_S << "Super4PCS: 点云采样失败 / Point cloud sampling failed";
226 return false;
227 }
228
229 // 计算网格分辨率 / Compute grid resolution
230 DataType grid_res = m_grid_resolution;
231 if (grid_res <= 0) {
232 grid_res = compute_adaptive_grid_resolution(this->get_source_cloud(),
233 source_samples);
235 << "Super4PCS: 自动计算网格分辨率 / Auto-computed grid resolution: "
236 << grid_res;
237 }
238
239 // 构建智能索引 / Build smart indices
240 m_source_index = std::make_unique<smart_index_t>(grid_res);
241 m_target_index = std::make_unique<smart_index_t>(grid_res);
242
243 m_source_index->build(this->get_source_cloud(), source_samples);
244 m_target_index->build(this->get_target_cloud(), target_samples);
245
246 LOG_DEBUG_S << "Super4PCS: 索引构建完成 / Index building complete";
247 LOG_DEBUG_S << "源索引 / Source index: " << m_source_index->get_statistics();
248 LOG_DEBUG_S << "目标索引 / Target index: "
249 << m_target_index->get_statistics();
250
251 // 提取源点云的共面4点基(使用优化方法) / Extract coplanar bases (using
252 // optimized method)
253 std::vector<base_4pcs_t> source_bases;
254
255 // 计算典型距离 / Compute typical distances
256 std::vector<DataType> base_distances;
257 const std::size_t num_distance_samples = 10;
258 std::mt19937 generator(this->get_random_seed());
259 std::uniform_int_distribution<std::size_t> dist(0, source_samples.size() - 1);
260
261 for (std::size_t i = 0;
262 i < num_distance_samples && i < source_samples.size() / 2;
263 ++i)
264 {
265 std::size_t idx1 = source_samples[dist(generator)];
266 std::size_t idx2 = source_samples[dist(generator)];
267 if (idx1 != idx2) {
268 const auto& pt1 = this->get_source_cloud()->points[idx1];
269 const auto& pt2 = this->get_source_cloud()->points[idx2];
270 DataType d = std::sqrt((pt2.x - pt1.x) * (pt2.x - pt1.x)
271 + (pt2.y - pt1.y) * (pt2.y - pt1.y)
272 + (pt2.z - pt1.z) * (pt2.z - pt1.z));
273 base_distances.push_back(d);
274 }
275 }
276
277 // 使用智能索引构建基 / Build bases using smart indexing
278 for (const DataType& distance : base_distances) {
279 // 提取指定距离的点对 / Extract point pairs at specified distance
280 auto source_pairs = extract_pairs_smart(source_samples,
281 this->get_source_cloud(),
282 distance,
283 m_pair_distance_epsilon);
284
285 // 从点对构建4点基 / Build 4-point bases from pairs
286 for (std::size_t i = 0;
287 i < source_pairs.size() && source_bases.size() < this->get_num_bases();
288 ++i)
289 {
290 for (std::size_t j = i + 1; j < source_pairs.size()
291 && source_bases.size() < this->get_num_bases();
292 ++j)
293 {
294 if (verify_pair_compatibility(source_pairs[i], source_pairs[j])) {
295 auto base_opt = build_base_from_pairs(
296 source_pairs[i], source_pairs[j], this->get_source_cloud());
297 if (base_opt.has_value()) {
298 source_bases.push_back(base_opt.value());
299 }
300 }
301 }
302 }
303 }
304
305 if (source_bases.empty()) {
306 LOG_ERROR_S << "Super4PCS: 无法提取有效的4点基 / Failed to extract valid "
307 "4-point bases";
308 return false;
309 }
310
311 LOG_DEBUG_S << "Super4PCS: 提取了 " << source_bases.size()
312 << " 个4点基 / 4-point bases";
313
314 // 最佳候选 / Best candidate
315 candidate_t best_candidate;
316 best_candidate.lcp_score = std::numeric_limits<DataType>::max();
317 best_candidate.num_inliers = 0;
318
319 // 对每个源基寻找匹配(使用优化方法) / Find matches for each source base
320 // (using optimized method)
321 std::size_t total_candidates = 0;
322
323 for (std::size_t base_idx = 0; base_idx < source_bases.size(); ++base_idx) {
324 result.num_iterations = base_idx + 1;
325 const auto& source_base = source_bases[base_idx];
326
327 // 使用优化方法寻找匹配 / Find matches using optimized method
328 auto target_bases = find_congruent_sets_optimized(source_base);
329 total_candidates += target_bases.size();
330
331 // 评估每个候选 / Evaluate each candidate
332 for (const auto& target_base : target_bases) {
333 candidate_t candidate;
334 candidate.source_base = source_base;
335 candidate.target_base = target_base;
336
337 // 估计变换 / Estimate transformation
338 candidate.transform =
339 this->estimate_transformation(source_base, target_base);
340
341 if (!this->is_valid_transformation(candidate.transform)) {
342 continue;
343 }
344
345 // 计算LCP评分 / Compute LCP score
346 std::vector<std::size_t> inliers;
347 candidate.lcp_score =
348 this->compute_lcp_score(candidate.transform, inliers);
349 candidate.num_inliers = inliers.size();
350
351 // 更新最佳候选 / Update best candidate
352 if (candidate.num_inliers > best_candidate.num_inliers
353 || (candidate.num_inliers == best_candidate.num_inliers
354 && candidate.lcp_score < best_candidate.lcp_score))
355 {
356 best_candidate = candidate;
357 result.inliers = std::move(inliers);
358 }
359 }
360
361 // 早停检查 / Early stopping check
362 if (best_candidate.num_inliers
363 >= source_samples.size() * this->get_overlap() * 0.9)
364 {
365 LOG_DEBUG_S << "Super4PCS: 早停,找到足够好的匹配 / Early stopping, "
366 "found good match";
367 result.converged = true;
368 break;
369 }
370 }
371
372 timer.stop();
373 double elapsed_time = timer.elapsed_time();
374 LOG_DEBUG_S << "Super4PCS: 完成 " << result.num_iterations
375 << " 个基的匹配,共 " << total_candidates
376 << " 个候选,耗时 / bases with candidates in: " << elapsed_time
377 << " 秒/s";
378
379 // 检查是否找到有效的匹配 / Check if valid match found
380 if (best_candidate.num_inliers < this->get_min_inliers()) {
381 LOG_ERROR_S << "Super4PCS: 内点数量不足 / Insufficient inliers: "
382 << best_candidate.num_inliers << " < "
383 << this->get_min_inliers();
384 return false;
385 }
386
387 // 精炼最佳候选 / Refine best candidate
388 this->refine_candidate(best_candidate);
389
390 // 设置结果 / Set result
391 result.transformation = best_candidate.transform;
392 result.fitness_score = best_candidate.lcp_score;
393 result.converged = result.converged
394 || (best_candidate.num_inliers >= this->get_min_inliers());
395
396 LOG_DEBUG_S << "Super4PCS: 配准完成 / Registration complete"
397 << ", 内点 / inliers: " << result.inliers.size()
398 << ", LCP评分 / LCP score: " << result.fitness_score;
399
400 return true;
401}
402
403template<typename DataType>
404std::vector<typename super_four_pcs_registration_t<DataType>::base_4pcs_t>
406 const base_4pcs_t& source_base) const
407{
408 std::vector<base_4pcs_t> congruent_bases;
409
410 // 计算源基的两条对角线长度 / Compute diagonal lengths of source base
411 DataType diag1_len =
412 (source_base.points[2] - source_base.points[0]).norm(); // AC
413 DataType diag2_len =
414 (source_base.points[3] - source_base.points[1]).norm(); // BD
415
416 // 使用智能索引查找匹配的对角线 / Find matching diagonals using smart indexing
417 auto target_diag1_pairs = m_target_index->find_pairs_in_range(
418 diag1_len, m_pair_distance_epsilon, 100);
419 auto target_diag2_pairs = m_target_index->find_pairs_in_range(
420 diag2_len, m_pair_distance_epsilon, 100);
421
422 // 尝试组合匹配的对角线对 / Try combining matching diagonal pairs
423 for (const auto& pair1 : target_diag1_pairs) {
424 for (const auto& pair2 : target_diag2_pairs) {
425 // 检查是否形成有效的4点集 / Check if they form valid 4-point set
426 std::unordered_set<std::size_t> indices_set;
427 indices_set.insert(pair1.idx1);
428 indices_set.insert(pair1.idx2);
429 indices_set.insert(pair2.idx1);
430 indices_set.insert(pair2.idx2);
431
432 if (indices_set.size() != 4) {
433 continue; // 有重复点 / Has duplicate points
434 }
435
436 // 构建目标基 / Build target base
437 base_4pcs_t target_base;
438 target_base.indices = {pair1.idx1, pair2.idx1, pair1.idx2, pair2.idx2};
439
440 auto target_cloud = this->get_target_cloud();
441 for (std::size_t i = 0; i < 4; ++i) {
442 const auto& pt = target_cloud->points[target_base.indices[i]];
443 target_base.points[i] = vector3_t(pt.x, pt.y, pt.z);
444 }
445
446 // 检查是否共面 / Check if coplanar
447 if (!this->are_coplanar(target_base.points, this->get_delta() * 2)) {
448 continue;
449 }
450
451 // 计算不变量并检查匹配 / Compute invariants and check match
452 this->compute_invariants(target_base);
453
454 const DataType invariant_tolerance = 0.1;
455 if (std::abs(source_base.invariant1 - target_base.invariant1)
456 < invariant_tolerance
457 && std::abs(source_base.invariant2 - target_base.invariant2)
458 < invariant_tolerance)
459 {
460 congruent_bases.push_back(target_base);
461 }
462 }
463 }
464
465 return congruent_bases;
466}
467
468template<typename DataType>
469std::vector<typename super_four_pcs_registration_t<DataType>::point_pair_t>
471 const std::vector<std::size_t>& indices,
472 const point_cloud_ptr& cloud,
473 DataType distance,
474 DataType epsilon) const
475{
476 if (m_source_index) {
477 return m_source_index->find_pairs_in_range(distance, epsilon);
478 }
479
480 // 后备方案:暴力搜索 / Fallback: brute force search
481 std::vector<point_pair_t> pairs;
482 const DataType min_dist = distance - epsilon;
483 const DataType max_dist = distance + epsilon;
484
485 for (std::size_t i = 0; i < indices.size(); ++i) {
486 for (std::size_t j = i + 1; j < indices.size(); ++j) {
487 const auto& pt1 = cloud->points[indices[i]];
488 const auto& pt2 = cloud->points[indices[j]];
489
490 DataType d = std::sqrt((pt2.x - pt1.x) * (pt2.x - pt1.x)
491 + (pt2.y - pt1.y) * (pt2.y - pt1.y)
492 + (pt2.z - pt1.z) * (pt2.z - pt1.z));
493
494 if (d >= min_dist && d <= max_dist) {
495 point_pair_t pair;
496 pair.idx1 = indices[i];
497 pair.idx2 = indices[j];
498 pair.distance = d;
499 pairs.push_back(pair);
500 }
501 }
502 }
503
504 return pairs;
505}
506
507template<typename DataType>
508std::optional<typename super_four_pcs_registration_t<DataType>::base_4pcs_t>
509super_four_pcs_registration_t<DataType>::build_base_from_pairs(
510 const point_pair_t& pair1,
511 const point_pair_t& pair2,
512 const point_cloud_ptr& cloud) const
513{
514 // 确保没有重复点 / Ensure no duplicate points
515 std::unordered_set<std::size_t> indices_set;
516 indices_set.insert(pair1.idx1);
517 indices_set.insert(pair1.idx2);
518 indices_set.insert(pair2.idx1);
519 indices_set.insert(pair2.idx2);
520
521 if (indices_set.size() != 4) {
522 return std::nullopt;
523 }
524
525 base_4pcs_t base;
526 base.indices = {pair1.idx1, pair1.idx2, pair2.idx1, pair2.idx2};
527
528 for (std::size_t i = 0; i < 4; ++i) {
529 const auto& pt = cloud->points[base.indices[i]];
530 base.points[i] = vector3_t(pt.x, pt.y, pt.z);
531 }
532
533 // 检查共面性 / Check coplanarity
534 if (!this->are_coplanar(base.points, this->get_delta() * 2)) {
535 return std::nullopt;
536 }
537
538 // 计算平面参数 / Compute plane parameters
539 vector3_t v1 = base.points[1] - base.points[0];
540 vector3_t v2 = base.points[2] - base.points[0];
541 base.normal = v1.cross(v2).normalized();
542 base.d = -base.normal.dot(base.points[0]);
543
544 // 计算不变量 / Compute invariants
545 this->compute_invariants(base);
546
547 return base;
548}
549
550template<typename DataType>
551bool super_four_pcs_registration_t<DataType>::verify_pair_compatibility(
552 const point_pair_t& pair1, const point_pair_t& pair2) const
553{
554 // 检查点对是否共享点 / Check if pairs share points
555 if (pair1.idx1 == pair2.idx1 || pair1.idx1 == pair2.idx2
556 || pair1.idx2 == pair2.idx1 || pair1.idx2 == pair2.idx2)
557 {
558 return true; // 共享点,可能形成有效基 / Share points, may form valid base
559 }
560
561 // 检查点对之间的距离是否合理 / Check if distance between pairs is reasonable
562 // 这里可以添加更多的几何约束 / More geometric constraints can be added here
563
564 return true;
565}
566
567template<typename DataType>
568DataType
569super_four_pcs_registration_t<DataType>::compute_adaptive_grid_resolution(
570 const point_cloud_ptr& cloud, const std::vector<std::size_t>& indices) const
571{
572 if (indices.empty()) {
573 return this->get_delta() * 10;
574 }
575
576 // 估计点云密度 / Estimate point cloud density
577 const std::size_t sample_size =
578 std::min(static_cast<std::size_t>(100), indices.size());
579 std::vector<DataType> nearest_distances;
580 nearest_distances.reserve(sample_size);
581
582 std::mt19937 generator(this->get_random_seed());
583 std::uniform_int_distribution<std::size_t> dist(0, indices.size() - 1);
584
585 for (std::size_t i = 0; i < sample_size; ++i) {
586 std::size_t idx = indices[dist(generator)];
587 const auto& pt = cloud->points[idx];
588
589 // 找最近邻(简化版) / Find nearest neighbor (simplified)
590 DataType min_dist = std::numeric_limits<DataType>::max();
591 for (std::size_t j = 0;
592 j < std::min(static_cast<std::size_t>(10), indices.size());
593 ++j)
594 {
595 if (indices[j] == idx)
596 continue;
597
598 const auto& other_pt = cloud->points[indices[j]];
599 DataType d = std::sqrt((other_pt.x - pt.x) * (other_pt.x - pt.x)
600 + (other_pt.y - pt.y) * (other_pt.y - pt.y)
601 + (other_pt.z - pt.z) * (other_pt.z - pt.z));
602 min_dist = std::min(min_dist, d);
603 }
604
605 if (min_dist < std::numeric_limits<DataType>::max()) {
606 nearest_distances.push_back(min_dist);
607 }
608 }
609
610 if (nearest_distances.empty()) {
611 return this->get_delta() * 10;
612 }
613
614 // 使用中位数作为网格分辨率的基础 / Use median as basis for grid resolution
615 std::sort(nearest_distances.begin(), nearest_distances.end());
616 DataType median_dist = nearest_distances[nearest_distances.size() / 2];
617
618 // 网格单元应该包含几个点 / Grid cell should contain several points
619 return median_dist * 5;
620}
621
622// 显式实例化 / Explicit instantiation
623template class super_four_pcs_registration_t<float>;
624template class super_four_pcs_registration_t<double>;
625
626} // namespace toolbox::pcl
std::size_t get_min_inliers() const
Definition base_coarse_registration.hpp:226
unsigned int get_random_seed() const
Definition base_coarse_registration.hpp:227
const point_cloud_ptr & get_source_cloud() const
获取受保护的成员变量访问 / Get access to protected members
Definition base_coarse_registration.hpp:220
const point_cloud_ptr & get_target_cloud() const
Definition base_coarse_registration.hpp:221
std::shared_ptr< point_cloud > point_cloud_ptr
Definition base_coarse_registration.hpp:34
registration_result_t< DataType > result_type
Definition base_coarse_registration.hpp:36
Eigen::Matrix< DataType, 3, 1 > vector3_t
Definition four_pcs_registration.hpp:51
std::size_t get_num_bases() const
获取基的数量 / Get number of bases
Definition four_pcs_registration.hpp:156
void compute_invariants(base_4pcs_t &base) const
计算4点基的仿射不变量 / Compute affine invariants for 4-point base
Definition four_pcs_registration_impl.hpp:331
DataType get_delta() const
获取配准精度 / Get registration accuracy
Definition four_pcs_registration.hpp:93
bool are_coplanar(const std::array< vector3_t, 4 > &points, DataType tolerance) const
检查4个点是否共面 / Check if 4 points are coplanar
Definition four_pcs_registration_impl.hpp:308
const std::vector< std::size_t > & get_target_samples() const
Definition four_pcs_registration.hpp:194
DataType compute_lcp_score(const transformation_t &transform, std::vector< std::size_t > &inliers) const
计算LCP(最大公共点集)评分 / Compute LCP (Largest Common Pointset) score
Definition four_pcs_registration_impl.hpp:552
transformation_t estimate_transformation(const base_4pcs_t &source_base, const base_4pcs_t &target_base) const
估计两个4点基之间的变换 / Estimate transformation between two 4-point bases
Definition four_pcs_registration_impl.hpp:497
bool align_impl(result_type &result)
派生类实现的配准算法 / Registration algorithm implementation
Definition four_pcs_registration_impl.hpp:16
void refine_candidate(candidate_t &candidate) const
精炼候选变换 / Refine candidate transformation
Definition four_pcs_registration_impl.hpp:590
const std::vector< std::size_t > & get_source_samples() const
Definition four_pcs_registration.hpp:193
bool is_valid_transformation(const transformation_t &transform) const
验证变换的有效性 / Verify transformation validity
Definition four_pcs_registration_impl.hpp:603
void build(const point_cloud_ptr &cloud, const std::vector< std::size_t > &indices)
构建索引 / Build index
Definition super_four_pcs_registration_impl.hpp:17
std::vector< point_pair_t > find_pairs_in_range(DataType distance, DataType epsilon, std::size_t max_pairs=1000) const
查找指定距离范围内的所有点对 / Find all point pairs within distance range
Definition super_four_pcs_registration_impl.hpp:56
std::string get_statistics() const
获取网格统计信息 / Get grid statistics
Definition super_four_pcs_registration_impl.hpp:134
Super4PCS 粗配准算法 / Super4PCS coarse registration algorithm.
Definition super_four_pcs_registration.hpp:44
Eigen::Matrix< DataType, 3, 1 > vector3_t
Definition four_pcs_registration.hpp:51
bool align_impl(result_type &result)
派生类实现的配准算法 / Registration algorithm implementation
Definition super_four_pcs_registration_impl.hpp:192
std::vector< base_4pcs_t > find_congruent_sets_optimized(const base_4pcs_t &source_base) const
寻找匹配的4点集(优化版本) / Find congruent sets (optimized version)
Definition super_four_pcs_registration_impl.hpp:405
A high-resolution stopwatch timer for measuring elapsed time.
Definition timer.hpp:41
void stop()
Stop (pause) the timer and accumulate the duration.
auto elapsed_time() const -> double
Get the total elapsed time in seconds.
void start()
Start or resume the timer.
#define LOG_DEBUG_S
DEBUG级别流式日志的宏 / Macro for DEBUG level stream logging.
Definition thread_logger.hpp:1329
#define LOG_ERROR_S
ERROR级别流式日志的宏 / Macro for ERROR level stream logging.
Definition thread_logger.hpp:1332
Definition base_correspondence_generator.hpp:18
4点基结构 / 4-point base structure
Definition four_pcs_registration.hpp:59
std::array< std::size_t, 4 > indices
点索引 / Point indices
Definition four_pcs_registration.hpp:60
DataType invariant2
第二个仿射不变量 / Second affine invariant
Definition four_pcs_registration.hpp:63
DataType invariant1
第一个仿射不变量 / First affine invariant
Definition four_pcs_registration.hpp:62
std::array< vector3_t, 4 > points
点坐标 / Point coordinates
Definition four_pcs_registration.hpp:61
候选匹配结构 / Candidate match structure
Definition four_pcs_registration.hpp:72
std::size_t num_inliers
内点数量 / Number of inliers
Definition four_pcs_registration.hpp:77
base_4pcs_t source_base
源点云基 / Source base
Definition four_pcs_registration.hpp:73
DataType lcp_score
LCP(最大公共点集)评分 / LCP score.
Definition four_pcs_registration.hpp:76
transformation_t transform
估计的变换 / Estimated transformation
Definition four_pcs_registration.hpp:75
base_4pcs_t target_base
目标点云基 / Target base
Definition four_pcs_registration.hpp:74
点对结构 / Point pair structure
Definition super_four_pcs_registration.hpp:63
std::size_t idx1
第一个点的索引 / First point index
Definition super_four_pcs_registration.hpp:64
std::size_t idx2
第二个点的索引 / Second point index
Definition super_four_pcs_registration.hpp:65
DataType distance
点对之间的距离 / Distance between points
Definition super_four_pcs_registration.hpp:66