cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
semantic_kitti_pair_dataset_impl.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <cmath>
7
8namespace toolbox::io {
9
10template<typename DataType>
12 const std::string& sequence_path,
13 std::size_t skip)
14 : base_dataset_(sequence_path), skip_(skip) {
15
16 if (skip_ == 0) {
17 throw std::invalid_argument("Skip must be at least 1");
18 }
19
20 LOG_INFO_S << "Created Semantic KITTI pair dataset with skip=" << skip_
21 << ", " << size_impl() << " pairs available"
22 << (base_dataset_.has_labels() ? " (with labels)" : " (no labels)");
23}
24
25template<typename DataType>
26std::optional<semantic_kitti_frame_pair_t<DataType>>
28
29 // Check if pair is valid
30 if (index >= size_impl()) {
31 return std::nullopt;
32 }
33
34 // Note: Caching disabled for pair datasets due to unique_ptr ownership
35 // Each access creates a new pair with fresh point cloud copies
36
37 // Compute frame indices
38 const std::size_t source_idx = get_source_frame_index(index);
39 const std::size_t target_idx = get_target_frame_index(index);
40
41 // Load source frame
42 auto source_frame = base_dataset_[source_idx];
43 if (!source_frame) {
44 LOG_ERROR_S << "Failed to load source frame " << source_idx;
45 return std::nullopt;
46 }
47
48 // Load target frame
49 auto target_frame = base_dataset_[target_idx];
50 if (!target_frame) {
51 LOG_ERROR_S << "Failed to load target frame " << target_idx;
52 return std::nullopt;
53 }
54
55 // Create pair
56 pair_type pair;
57 pair.source_cloud = std::move(source_frame->cloud);
58 pair.target_cloud = std::move(target_frame->cloud);
59 pair.source_labels = std::move(source_frame->labels);
60 pair.target_labels = std::move(target_frame->labels);
61 pair.source_pose = source_frame->pose;
62 pair.target_pose = target_frame->pose;
63 pair.source_index = source_idx;
64 pair.target_index = target_idx;
65
66 // Compute relative transform
68 pair.source_pose, pair.target_pose);
69
70 // Check motion criteria if filtering is enabled
71 if (filter_by_motion_ && !meets_motion_criteria(pair.relative_transform)) {
72 LOG_DEBUG_S << "Pair " << index << " filtered out due to insufficient motion";
73 return std::nullopt;
74 }
75
76 return pair;
77}
78
79template<typename DataType>
81 const Eigen::Matrix<DataType, 4, 4>& relative_transform) const {
82
83 // Extract translation
84 Eigen::Vector3<DataType> translation =
85 relative_transform.template block<3, 1>(0, 3);
86 DataType trans_norm = translation.norm();
87
88 // Extract rotation angle
89 Eigen::Matrix3<DataType> R =
90 relative_transform.template block<3, 3>(0, 0);
91 DataType trace = R.trace();
92 DataType angle = std::acos(std::min(std::max((trace - 1) / 2,
93 DataType(-1)),
94 DataType(1)));
95
96 return trans_norm >= min_translation_ || angle >= min_rotation_;
97}
98
99template<typename DataType>
100std::vector<std::size_t>
102 const std::vector<uint16_t>& require_labels,
103 std::size_t min_points) const {
104
105 std::vector<std::size_t> result;
106
107 // Convert to set for faster lookup
108 std::set<uint16_t> label_set(require_labels.begin(), require_labels.end());
109
110 for (std::size_t i = 0; i < size_impl(); ++i) {
111 auto pair = at_impl(i);
112 if (!pair) continue;
113
114 // Check if both frames have required labels
115 bool source_has_labels = true;
116 bool target_has_labels = true;
117
118 for (const auto& label : require_labels) {
119 // Count points with this label in source
120 std::size_t source_count = 0;
121 for (const auto& l : pair->source_labels) {
122 if (get_kitti_label_id(l) == label) {
123 source_count++;
124 }
125 }
126
127 // Count points with this label in target
128 std::size_t target_count = 0;
129 for (const auto& l : pair->target_labels) {
130 if (get_kitti_label_id(l) == label) {
131 target_count++;
132 }
133 }
134
135 if (source_count < min_points) source_has_labels = false;
136 if (target_count < min_points) target_has_labels = false;
137
138 if (!source_has_labels || !target_has_labels) break;
139 }
140
141 if (source_has_labels && target_has_labels) {
142 result.push_back(i);
143 }
144 }
145
146 return result;
147}
148
149template<typename DataType>
150std::map<std::string, DataType>
152
153 std::map<std::string, DataType> stats;
154 std::vector<DataType> translations;
155 std::vector<DataType> rotations;
156
157 for (std::size_t i = 0; i < size_impl(); ++i) {
158 auto pair = at_impl(i);
159 if (!pair) continue;
160
161 // Extract translation
162 Eigen::Vector3<DataType> translation =
163 pair->relative_transform.template block<3, 1>(0, 3);
164 translations.push_back(translation.norm());
165
166 // Extract rotation angle
167 Eigen::Matrix3<DataType> R =
168 pair->relative_transform.template block<3, 3>(0, 0);
169 DataType trace = R.trace();
170 DataType angle = std::acos(std::min(std::max((trace - 1) / 2,
171 DataType(-1)),
172 DataType(1)));
173 rotations.push_back(angle);
174 }
175
176 if (!translations.empty()) {
177 // Compute translation statistics
178 DataType trans_sum = 0;
179 DataType trans_sq_sum = 0;
180 DataType trans_min = translations[0];
181 DataType trans_max = translations[0];
182
183 for (const auto& t : translations) {
184 trans_sum += t;
185 trans_sq_sum += t * t;
186 trans_min = std::min(trans_min, t);
187 trans_max = std::max(trans_max, t);
188 }
189
190 DataType trans_mean = trans_sum / translations.size();
191 DataType trans_var = (trans_sq_sum / translations.size()) - (trans_mean * trans_mean);
192 DataType trans_std = std::sqrt(std::max(DataType(0), trans_var));
193
194 stats["translation_mean"] = trans_mean;
195 stats["translation_std"] = trans_std;
196 stats["translation_min"] = trans_min;
197 stats["translation_max"] = trans_max;
198
199 // Compute rotation statistics
200 DataType rot_sum = 0;
201 DataType rot_sq_sum = 0;
202 DataType rot_min = rotations[0];
203 DataType rot_max = rotations[0];
204
205 for (const auto& r : rotations) {
206 rot_sum += r;
207 rot_sq_sum += r * r;
208 rot_min = std::min(rot_min, r);
209 rot_max = std::max(rot_max, r);
210 }
211
212 DataType rot_mean = rot_sum / rotations.size();
213 DataType rot_var = (rot_sq_sum / rotations.size()) - (rot_mean * rot_mean);
214 DataType rot_std = std::sqrt(std::max(DataType(0), rot_var));
215
216 stats["rotation_mean_rad"] = rot_mean;
217 stats["rotation_std_rad"] = rot_std;
218 stats["rotation_min_rad"] = rot_min;
219 stats["rotation_max_rad"] = rot_max;
220 stats["rotation_mean_deg"] = rot_mean * 180.0 / M_PI;
221 stats["rotation_std_deg"] = rot_std * 180.0 / M_PI;
222 }
223
224 stats["num_pairs"] = static_cast<DataType>(translations.size());
225 stats["skip"] = static_cast<DataType>(skip_);
226
227 return stats;
228}
229
230} // namespace toolbox::io
Semantic KITTI frame pair dataset loader.
Definition semantic_kitti_pair_dataset.hpp:39
semantic_kitti_pair_dataset_t(const std::string &sequence_path, std::size_t skip=1)
Constructor.
Definition semantic_kitti_pair_dataset_impl.hpp:11
std::map< std::string, DataType > compute_motion_statistics() const
Compute motion statistics for the dataset.
Definition semantic_kitti_pair_dataset_impl.hpp:151
std::size_t size_impl() const
Get number of frame pairs.
Definition semantic_kitti_pair_dataset.hpp:106
std::vector< std::size_t > get_pairs_with_labels(const std::vector< uint16_t > &require_labels, std::size_t min_points=100) const
Get pairs with specific semantic constraints.
Definition semantic_kitti_pair_dataset_impl.hpp:101
std::optional< pair_type > at_impl(std::size_t index) const
Load frame pair at specific index.
Definition semantic_kitti_pair_dataset_impl.hpp:27
#define LOG_DEBUG_S
DEBUG级别流式日志的宏 / Macro for DEBUG level stream logging.
Definition thread_logger.hpp:1329
#define LOG_INFO_S
INFO级别流式日志的宏 / Macro for INFO level stream logging.
Definition thread_logger.hpp:1330
#define LOG_ERROR_S
ERROR级别流式日志的宏 / Macro for ERROR level stream logging.
Definition thread_logger.hpp:1332
< 用于列出目录下的文件/For listing files in a directory
Definition dataloader.hpp:15
uint16_t get_kitti_label_id(uint32_t full_label)
Extract label ID from full label (ignoring instance ID)
Definition kitti_extended.hpp:289
Eigen::Matrix< DataType, 4, 4 > compute_relative_transform(const Eigen::Matrix< DataType, 4, 4 > &from_pose, const Eigen::Matrix< DataType, 4, 4 > &to_pose)
Compute relative transformation between two poses.
Definition kitti_extended_impl.hpp:291
Frame pair data from Semantic KITTI dataset.
Definition kitti_types.hpp:159
Eigen::Matrix< DataType, 4, 4 > relative_transform
Relative transformation.
Definition kitti_types.hpp:179
std::size_t target_index
Target frame index.
Definition kitti_types.hpp:185
std::unique_ptr< point_cloud_t< DataType > > target_cloud
Target point cloud.
Definition kitti_types.hpp:164
std::size_t source_index
Source frame index.
Definition kitti_types.hpp:182
Eigen::Matrix< DataType, 4, 4 > source_pose
Source global pose.
Definition kitti_types.hpp:173
std::vector< uint32_t > source_labels
Source point labels.
Definition kitti_types.hpp:167
std::unique_ptr< point_cloud_t< DataType > > source_cloud
Source point cloud.
Definition kitti_types.hpp:161
std::vector< uint32_t > target_labels
Target point labels.
Definition kitti_types.hpp:170
Eigen::Matrix< DataType, 4, 4 > target_pose
Target global pose.
Definition kitti_types.hpp:176