17std::vector<float> CopyTensorView(
const float* values, std::size_t count) {
25 std::vector<BoundingBox> objects;
28 throw std::invalid_argument(
"DecodePbod requires non-null output tensor pointers.");
34 throw std::invalid_argument(
"DecodePbod requires reg_dim >= 7.");
37 throw std::invalid_argument(
"DecodePbod received fewer pillar centers than num_pillars.");
41 const std::size_t num_pillars =
static_cast<std::size_t
>(outputs.
num_pillars);
42 const std::size_t num_classes =
static_cast<std::size_t
>(outputs.
num_classes);
43 const std::size_t reg_dim_size =
static_cast<std::size_t
>(reg_dim);
45 const std::vector<float> focal_logits = CopyTensorView(outputs.
focal_logits, num_pillars);
46 const std::vector<float> size_posterior = CopyTensorView(outputs.
size_posterior, num_pillars * num_classes * 3U);
47 const std::vector<float> class_logits = CopyTensorView(outputs.
class_logits, num_pillars * num_classes);
48 const std::vector<float> reg_logits = CopyTensorView(outputs.
reg_logits, num_pillars * num_classes * reg_dim_size);
50 objects.reserve(
static_cast<std::size_t
>(outputs.
num_pillars));
51 for (
int idx = 0; idx < outputs.
num_pillars; ++idx) {
52 const std::size_t pillar_idx =
static_cast<std::size_t
>(idx);
53 const float score = sigmoid(focal_logits[pillar_idx]);
56 const std::size_t class_base = pillar_idx * num_classes;
57 float best_logit = class_logits[class_base];
59 float logit = class_logits[class_base +
static_cast<std::size_t
>(c)];
60 if (logit > best_logit) {
66 float score_thresh = 0.0F;
68 const std::size_t class_idx =
static_cast<std::size_t
>(best_class);
73 if (score < score_thresh) {
78 const std::size_t class_idx =
static_cast<std::size_t
>(best_class);
79 const std::size_t size_offset = (pillar_idx * num_classes + class_idx) * 3U;
80 const std::size_t reg_offset = (pillar_idx * num_classes + class_idx) * reg_dim_size;
81 const std::size_t center_offset = pillar_idx * 3U;
83 box.
length = std::exp(reg_logits[reg_offset + 3U]) * size_posterior[size_offset + 0U];
84 box.
width = std::exp(reg_logits[reg_offset + 4U]) * size_posterior[size_offset + 1U];
85 box.
height = std::exp(reg_logits[reg_offset + 5U]) * size_posterior[size_offset + 2U];
86 box.
center[0] = reg_logits[reg_offset + 0U] * size_posterior[size_offset + 0U] + grid.
centers[center_offset + 0U];
87 box.
center[1] = reg_logits[reg_offset + 1U] * size_posterior[size_offset + 1U] + grid.
centers[center_offset + 1U];
88 box.
z = reg_logits[reg_offset + 2U] * size_posterior[size_offset + 2U] + grid.
centers[center_offset + 2U];
89 box.
yaw =
wrap_to_range(reg_logits[reg_offset + 6U], -
static_cast<float>(M_PI),
static_cast<float>(M_PI));
90 if (std::isnan(box.
length) || std::isnan(box.
width) || std::isnan(box.
height) || std::isnan(box.
yaw)) {
95 const std::size_t current_class =
static_cast<std::size_t
>(c);
96 box.
classification.push_back({current_class, class_logits[class_base + current_class]});
100 objects.push_back(std::move(box));
std::vector< float > score_thresholds
Per-class thresholds, or one shared threshold.