Skip to content

Commit de49cf8

Browse files
feat: add 3DSC descriptor support to correspondence benchmarks
- Fix 3DSC signature interface compatibility with KNN algorithms - Add data(), size(), value_type, data_type members for KNN interface - Add DSC3DMetric class for proper distance calculations - Add comprehensive 3DSC descriptor benchmarks: - Type comparison (KNN vs brute-force methods) - Quantity scaling tests (50-2000 descriptors) - Dimension impact analysis (1980D comparison) - Add create_test_3dsc_descriptors() helper function - Add bilingual documentation with usage examples - Performance results: ~40ms for 300 descriptors vs ~7ms for SHOT 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 0a53337 commit de49cf8

File tree

2 files changed

+204
-3
lines changed

2 files changed

+204
-3
lines changed

benchmark/pcl/correspondence_benc.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <cpp-toolbox/pcl/descriptors/fpfh_extractor.hpp>
99
#include <cpp-toolbox/pcl/descriptors/pfh_extractor.hpp>
1010
#include <cpp-toolbox/pcl/descriptors/shot_extractor.hpp>
11+
#include <cpp-toolbox/pcl/descriptors/3dsc_extractor.hpp>
1112
#include <cpp-toolbox/pcl/knn/bfknn.hpp>
1213
#include <cpp-toolbox/pcl/knn/kdtree.hpp>
1314
#include <cpp-toolbox/types/point.hpp>
@@ -72,6 +73,25 @@ struct SHOTMetric
7273
}
7374
};
7475

76+
template<typename T>
77+
struct DSC3DMetric
78+
{
79+
using value_type = T;
80+
using result_type = T;
81+
82+
T operator()(const toolbox::pcl::dsc3d_signature_t<T>& a,
83+
const toolbox::pcl::dsc3d_signature_t<T>& b) const
84+
{
85+
return a.distance(b);
86+
}
87+
88+
T distance(const toolbox::pcl::dsc3d_signature_t<T>& a,
89+
const toolbox::pcl::dsc3d_signature_t<T>& b) const
90+
{
91+
return a.distance(b);
92+
}
93+
};
94+
7595
} // namespace toolbox::metrics
7696

7797
using namespace toolbox::pcl;
@@ -188,6 +208,42 @@ create_test_shot_descriptors(size_t num_descriptors, std::mt19937& rng)
188208
return {descriptors, indices};
189209
}
190210

211+
// 创建测试3DSC描述子 / Create test 3DSC descriptors
212+
template<typename T>
213+
std::pair<std::shared_ptr<std::vector<dsc3d_signature_t<T>>>,
214+
std::shared_ptr<std::vector<std::size_t>>>
215+
create_test_3dsc_descriptors(size_t num_descriptors, std::mt19937& rng)
216+
{
217+
auto descriptors = std::make_shared<std::vector<dsc3d_signature_t<T>>>();
218+
auto indices = std::make_shared<std::vector<std::size_t>>();
219+
220+
std::uniform_real_distribution<T> dist(0.0, 1.0);
221+
222+
for (size_t i = 0; i < num_descriptors; ++i) {
223+
dsc3d_signature_t<T> desc;
224+
225+
// 创建随机描述子 / Create random descriptor (1980 dimensions)
226+
for (int j = 0; j < 1980; ++j) {
227+
desc.histogram[j] = dist(rng);
228+
}
229+
230+
// 归一化 / Normalize
231+
T sum = 0;
232+
for (int j = 0; j < 1980; ++j) {
233+
sum += desc.histogram[j];
234+
}
235+
if (sum > 0) {
236+
for (int j = 0; j < 1980; ++j) {
237+
desc.histogram[j] /= sum;
238+
}
239+
}
240+
241+
descriptors->push_back(desc);
242+
indices->push_back(i * 10);
243+
}
244+
245+
return {descriptors, indices};
246+
}
191247

192248
TEST_CASE("对应点生成性能比较 / Correspondence Generation Performance Comparison",
193249
"[pcl][correspondence][benchmark]")
@@ -375,6 +431,57 @@ TEST_CASE("对应点生成性能比较 / Correspondence Generation Performance C
375431
};
376432
}
377433

434+
SECTION("3DSC描述子性能 / 3DSC descriptor performance")
435+
{
436+
auto src_data = create_test_3dsc_descriptors<T>(num_desc, rng);
437+
auto dst_data = create_test_3dsc_descriptors<T>(num_desc, rng);
438+
auto src_descriptors = src_data.first;
439+
auto src_indices = src_data.second;
440+
auto dst_descriptors = dst_data.first;
441+
auto dst_indices = dst_data.second;
442+
443+
BENCHMARK("3DSC - KNN方法 / 3DSC - KNN method")
444+
{
445+
using CorrespondenceGen = knn_correspondence_generator_t<
446+
T,
447+
dsc3d_signature_t<T>,
448+
bfknn_generic_t<dsc3d_signature_t<T>,
449+
toolbox::metrics::DSC3DMetric<T>>>;
450+
CorrespondenceGen corr_gen;
451+
452+
auto knn = std::make_shared<
453+
bfknn_generic_t<dsc3d_signature_t<T>,
454+
toolbox::metrics::DSC3DMetric<T>>>();
455+
corr_gen.set_knn(knn);
456+
corr_gen.set_source(src_cloud, src_descriptors, src_indices);
457+
corr_gen.set_destination(dst_cloud, dst_descriptors, dst_indices);
458+
corr_gen.set_ratio(0.8f);
459+
corr_gen.set_mutual_verification(true);
460+
461+
std::vector<correspondence_t> correspondences;
462+
corr_gen.compute(correspondences);
463+
464+
return correspondences.size();
465+
};
466+
467+
BENCHMARK("3DSC - 暴力搜索(并行) / 3DSC - Brute-force (parallel)")
468+
{
469+
brute_force_correspondence_generator_t<T, dsc3d_signature_t<T>>
470+
corr_gen;
471+
472+
corr_gen.enable_parallel(true);
473+
corr_gen.set_source(src_cloud, src_descriptors, src_indices);
474+
corr_gen.set_destination(dst_cloud, dst_descriptors, dst_indices);
475+
corr_gen.set_ratio(0.8f);
476+
corr_gen.set_mutual_verification(true);
477+
478+
std::vector<correspondence_t> correspondences;
479+
corr_gen.compute(correspondences);
480+
481+
return correspondences.size();
482+
};
483+
}
484+
378485
}
379486

380487
SECTION("不同描述子数量的性能影响 / Performance impact of different descriptor counts")
@@ -509,6 +616,39 @@ TEST_CASE("对应点生成性能比较 / Correspondence Generation Performance C
509616
return correspondences.size();
510617
};
511618
}
619+
620+
DYNAMIC_SECTION("3DSC描述子数量 / 3DSC descriptor count: " << num_desc)
621+
{
622+
std::mt19937 rng(42);
623+
auto src_data = create_test_3dsc_descriptors<T>(num_desc, rng);
624+
auto dst_data = create_test_3dsc_descriptors<T>(num_desc, rng);
625+
auto src_descriptors = src_data.first;
626+
auto src_indices = src_data.second;
627+
auto dst_descriptors = dst_data.first;
628+
auto dst_indices = dst_data.second;
629+
630+
auto src_cloud = std::make_shared<point_cloud_t<T>>();
631+
auto dst_cloud = std::make_shared<point_cloud_t<T>>();
632+
src_cloud->points.resize(num_desc * 10);
633+
dst_cloud->points.resize(num_desc * 10);
634+
635+
BENCHMARK("3DSC - 暴力搜索(并行) / 3DSC - Brute-force (parallel)")
636+
{
637+
brute_force_correspondence_generator_t<T, dsc3d_signature_t<T>>
638+
corr_gen;
639+
640+
corr_gen.enable_parallel(true);
641+
corr_gen.set_source(src_cloud, src_descriptors, src_indices);
642+
corr_gen.set_destination(dst_cloud, dst_descriptors, dst_indices);
643+
corr_gen.set_ratio(0.8f);
644+
corr_gen.set_mutual_verification(true);
645+
646+
std::vector<correspondence_t> correspondences;
647+
corr_gen.compute(correspondences);
648+
649+
return correspondences.size();
650+
};
651+
}
512652
}
513653
}
514654

@@ -684,6 +824,26 @@ TEST_CASE("描述子维度对性能的影响 / Impact of descriptor dimensions o
684824
};
685825
}
686826

827+
// 3DSC (1980维) / 3DSC (1980 dimensions)
828+
{
829+
auto src_data = create_test_3dsc_descriptors<T>(num_desc, rng);
830+
auto dst_data = create_test_3dsc_descriptors<T>(num_desc, rng);
831+
832+
BENCHMARK("3DSC (1980维) - 暴力搜索 / 3DSC (1980D) - Brute-force")
833+
{
834+
brute_force_correspondence_generator_t<T, dsc3d_signature_t<T>> corr_gen;
835+
corr_gen.enable_parallel(true);
836+
corr_gen.set_source(src_cloud, src_data.first, src_data.second);
837+
corr_gen.set_destination(dst_cloud, dst_data.first, dst_data.second);
838+
corr_gen.set_ratio(0.8f);
839+
corr_gen.set_mutual_verification(true);
840+
841+
std::vector<correspondence_t> correspondences;
842+
corr_gen.compute(correspondences);
843+
return correspondences.size();
844+
};
845+
}
846+
687847
}
688848
}
689849

src/include/cpp-toolbox/pcl/descriptors/3dsc_extractor.hpp

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,53 @@
1414
namespace toolbox::pcl
1515
{
1616

17+
/**
18+
* @brief 3D形状上下文描述子签名 / 3D Shape Context descriptor signature
19+
*
20+
* @tparam DataType 数据类型(float或double) / Data type (float or double)
21+
*
22+
* @details 3DSC描述子使用1980维直方图(11径向×12方位×15仰角)来描述局部3D形状
23+
* The 3DSC descriptor uses a 1980-bin histogram (11 radial × 12 azimuth × 15 elevation) to describe local 3D shape
24+
*
25+
* @code
26+
* // 基本使用 / Basic usage
27+
* dsc3d_signature_t<float> desc1, desc2;
28+
*
29+
* // 计算距离 / Compute distance
30+
* float dist = desc1.distance(desc2);
31+
*
32+
* // 用于KNN搜索 / For KNN search
33+
* std::vector<dsc3d_signature_t<float>> descriptors = {...};
34+
* bfknn_generic_t<dsc3d_signature_t<float>, DSC3DMetric<float>> knn;
35+
* knn.set_input(descriptors);
36+
* @endcode
37+
*/
1738
template<typename DataType>
1839
struct dsc3d_signature_t : public base_signature_t<DataType, dsc3d_signature_t<DataType>>
1940
{
20-
static constexpr std::size_t HISTOGRAM_SIZE = 1980; // 11 * 12 * 15
21-
std::array<DataType, HISTOGRAM_SIZE> histogram {};
22-
41+
using value_type = DataType; ///< 为了兼容KNN接口 / For KNN interface compatibility
42+
using data_type = DataType; ///< 为了兼容描述子匹配接口 / For descriptor matching interface compatibility
43+
static constexpr std::size_t HISTOGRAM_SIZE = 1980; ///< 直方图大小:11 × 12 × 15 / Histogram size: 11 × 12 × 15
44+
std::array<DataType, HISTOGRAM_SIZE> histogram {}; ///< 直方图数据 / Histogram data
45+
46+
/**
47+
* @brief 提供data()方法以兼容IMetric接口 / Provide data() method for IMetric interface compatibility
48+
* @return 直方图数据指针 / Pointer to histogram data
49+
*/
50+
const DataType* data() const { return histogram.data(); }
51+
DataType* data() { return histogram.data(); }
52+
53+
/**
54+
* @brief 获取直方图大小 / Get histogram size
55+
* @return 直方图维度 / Histogram dimensions
56+
*/
57+
constexpr std::size_t size() const { return HISTOGRAM_SIZE; }
58+
59+
/**
60+
* @brief 计算与另一个描述子的欧氏距离 / Compute Euclidean distance to another descriptor
61+
* @param other 另一个描述子 / Another descriptor
62+
* @return 欧氏距离 / Euclidean distance
63+
*/
2364
DataType distance_impl(const dsc3d_signature_t& other) const
2465
{
2566
DataType dist = 0;

0 commit comments

Comments
 (0)