ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
label_semantics.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 Povl Filip Sonne-Frederiksen
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#pragma once
6
7#include <cstdint>
8#include <stdexcept>
9#include <string>
10
11#include <opencv2/core.hpp>
12
29
30namespace reusex::core {
31
34inline constexpr uint32_t kUnlabeled = 0;
35
38inline constexpr int kBackgroundApi = -1;
39
43inline constexpr uint16_t kMaxStorableLabel = 65534;
44
46inline constexpr bool is_valid_label(uint32_t label) noexcept {
47 return label != kUnlabeled;
48}
49
54inline constexpr bool is_out_of_contract_label(uint32_t label) noexcept {
55 return label > 0x7FFFFFFFu;
56}
57
64inline size_t label_to_index(uint32_t label) {
65 if (!is_valid_label(label))
66 throw std::out_of_range(
67 "label_to_index: label 0 is unlabeled and has no index");
68 return static_cast<size_t>(label) - 1;
69}
70
71// ── Scalar conversions ────────────────────────────────────────────────────
72
81inline uint32_t api_to_point_label(int api_label) {
82 if (api_label == kBackgroundApi)
83 return kUnlabeled;
84 if (api_label < 0)
85 throw std::out_of_range("api_to_point_label: negative label " +
86 std::to_string(api_label) +
87 " is not the background sentinel (-1)");
88 return static_cast<uint32_t>(api_label);
89}
90
93inline int point_label_to_api(uint32_t point_label) {
94 if (point_label == kUnlabeled)
95 return kBackgroundApi;
96 return static_cast<int>(point_label);
97}
98
104inline uint16_t api_to_storage(int api_label) {
105 if (api_label < kBackgroundApi)
106 throw std::out_of_range("api_to_storage: label " +
107 std::to_string(api_label) + " is below -1");
108 if (api_label > static_cast<int>(kMaxStorableLabel))
109 throw std::out_of_range(
110 "api_to_storage: label " + std::to_string(api_label) +
111 " exceeds maximum storable label " +
112 std::to_string(static_cast<int>(kMaxStorableLabel)) +
113 " (would wrap CV_16U storage)");
114 return static_cast<uint16_t>(api_label + 1);
115}
116
119inline int storage_to_api(uint16_t storage_value) {
120 return static_cast<int>(storage_value) - 1;
121}
122
123// ── Whole-cv::Mat converters ──────────────────────────────────────────────
124
130inline cv::Mat storage_mat_to_api(const cv::Mat &storage) {
131 if (storage.empty())
132 return cv::Mat();
133 if (storage.type() != CV_16UC1)
134 throw std::invalid_argument(
135 "storage_mat_to_api: expected CV_16UC1 storage image");
136 cv::Mat api;
137 storage.convertTo(api, CV_32S);
138 api -= 1;
139 return api;
140}
141
148inline cv::Mat api_mat_to_storage(const cv::Mat &api) {
149 if (api.empty())
150 throw std::invalid_argument("api_mat_to_storage: empty label image");
151 if (api.type() != CV_32SC1)
152 throw std::invalid_argument(
153 "api_mat_to_storage: expected CV_32SC1 API image");
154
155 double min_val = 0.0;
156 double max_val = 0.0;
157 cv::minMaxLoc(api, &min_val, &max_val);
158 if (min_val < static_cast<double>(kBackgroundApi))
159 throw std::out_of_range("api_mat_to_storage: label " +
160 std::to_string(static_cast<int>(min_val)) +
161 " is below -1");
162 if (max_val > static_cast<double>(kMaxStorableLabel))
163 throw std::out_of_range(
164 "api_mat_to_storage: label " +
165 std::to_string(static_cast<int>(max_val)) +
166 " exceeds maximum storable label " +
167 std::to_string(static_cast<int>(kMaxStorableLabel)) +
168 " (would wrap CV_16U storage)");
169
170 cv::Mat offset = api + 1;
171 cv::Mat storage;
172 offset.convertTo(storage, CV_16U);
173 return storage;
174}
175
176} // namespace reusex::core
Wire form of one stored report PDF version — the ReportPdfVersion schema in ruxd's API contract (docs...
constexpr uint16_t kMaxStorableLabel
Largest label that can be stored in the CV_16U PNG layer.
size_t label_to_index(uint32_t label)
Convert a point label to a zero-based vector index, replacing the error-prone bare label - 1 idiom us...
uint16_t api_to_storage(int api_label)
API label (CV_32S, -1 = background) → storage value (CV_16U, 0 = bg, label + 1).
int storage_to_api(uint16_t storage_value)
Storage value (CV_16U, 0 = bg, label + 1) → API label (CV_32S, -1 = background).
cv::Mat storage_mat_to_api(const cv::Mat &storage)
Convert a storage label image (CV_16U, 0 = bg) to an API label image (CV_32S, -1 = background) by sub...
constexpr int kBackgroundApi
ProjectDB segmentation API convention: -1 marks background/unlabeled in the CV_32S label images retur...
cv::Mat api_mat_to_storage(const cv::Mat &api)
Convert an API label image (CV_32S, -1 = background) to a storage label image (CV_16U,...
uint32_t api_to_point_label(int api_label)
API (CV_32S, -1 = background) → point label (uint32_t, 0 = unlabeled).
constexpr uint32_t kUnlabeled
Point-cloud convention: 0 means "unlabeled" in every CloudL (labels, planes, rooms,...
int point_label_to_api(uint32_t point_label)
Point label (uint32_t, 0 = unlabeled) → API (CV_32S, -1 = background).
constexpr bool is_valid_label(uint32_t label) noexcept
constexpr bool is_out_of_contract_label(uint32_t label) noexcept