1#ifndef LIGHTLY_EDGE_SDK_H
2#define LIGHTLY_EDGE_SDK_H
5#include "lightly_edge_cxx.rs.h"
6#include "lightly_edge_error.h"
7#include "lightly_edge_rs_bindings.h"
8#include "lightly_edge_rs_bindings_ext.h"
9#include "tl/expected.hpp"
18const size_t BUFFER_MAX_LENGTH = 3000;
19const uint32_t MAX_CLASSIFICATIONS_DEFAULT = 5;
20const int CPP_SDK_ERROR_CODE = 30;
52 Frame(
size_t width,
size_t height,
void *rgbImageData)
56using lightly_edge_cxx::InferenceDeviceType;
57using lightly_edge_cxx::LightlyEdgeConfig;
59using lightly_edge_rs::CStatus;
65inline auto default_config() -> LightlyEdgeConfig {
66 LightlyEdgeConfig config{};
67 config.detector_config.object_detector_enable =
false;
68 config.detector_config.classifiers_enable =
false;
69 config.detector_config.max_classifications = MAX_CLASSIFICATIONS_DEFAULT;
70 config.inference_device_type = InferenceDeviceType::Auto;
75inline auto cxx_status_to_unexpected(lightly_edge_cxx::CxxStatus &status)
76 -> tl::unexpected<Error> {
77 return tl::make_unexpected(
125 if (this->lightly_edge !=
nullptr) {
126 lightly_edge_rs::destroy(this->lightly_edge);
134 : lightly_edge(other.lightly_edge), lightly_edge_cxx(other.lightly_edge_cxx) {
135 other.lightly_edge =
nullptr;
136 other.lightly_edge_cxx =
nullptr;
143 if (
this != &other) {
144 if (this->lightly_edge !=
nullptr) {
145 lightly_edge_rs::destroy(this->lightly_edge);
147 this->lightly_edge = other.lightly_edge;
148 this->lightly_edge_cxx = other.lightly_edge_cxx;
149 other.lightly_edge =
nullptr;
150 other.lightly_edge_cxx =
nullptr;
171 [[nodiscard]]
static auto new_from_tar(
const std::string &archive_path,
183 LightlyEdgeConfig config)
noexcept
184 -> tl::expected<LightlyEdge, Error> {
185 lightly_edge_cxx::LightlyEdge *lightly_edge =
nullptr;
186 lightly_edge_cxx::CxxStatus status =
187 lightly_edge_cxx::new_from_tar(archive_path, config, &lightly_edge);
188 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
189 return cxx_status_to_unexpected(status);
201 LightlyEdgeConfig config) {
212 [[nodiscard]]
static auto
214 LightlyEdgeConfig config)
noexcept
215 -> tl::expected<LightlyEdge, Error> {
216 lightly_edge_cxx::LightlyEdge *lightly_edge =
nullptr;
219 lightly_edge_cxx::new_from_directory(model_directory, config, &lightly_edge);
220 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
221 return cxx_status_to_unexpected(status);
243 -> tl::expected<std::vector<float>,
Error> {
245 lightly_edge_rs::embedding_dimension(this->lightly_edge);
248 auto status = lightly_edge_rs::embed_frame(
249 this->lightly_edge,
static_cast<uint8_t *
>(frame.rgbImageData_),
250 frame.width_ * frame.height_ * 3, frame.width_, frame.height_,
251 embedding_buffer.data());
252 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
253 return status_to_unexpected(&status);
256 return std::move(embedding_buffer);
265 return lightly_edge_rs::embedding_dimension(this->lightly_edge);
279 [[nodiscard]]
auto embed_texts(
const std::vector<std::string> &texts)
const
280 -> std::vector<std::vector<float>> {
297 -> tl::expected<std::vector<std::vector<float>>,
Error> {
299 rust::Vec<lightly_edge_cxx::Embedding> rust_embeddings{};
302 lightly_edge_cxx::embed_texts(*this->lightly_edge_cxx, texts, rust_embeddings);
305 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
306 return cxx_status_to_unexpected(status);
309 std::vector<std::vector<float>> embeddings;
310 embeddings.resize(rust_embeddings.size());
311 for (
size_t i = 0; i < rust_embeddings.size(); ++i) {
312 embeddings[i] = std::vector<float>(rust_embeddings[i].data.begin(),
313 rust_embeddings[i].data.end());
365 const std::vector<float> &embedding)
const noexcept -> tl::expected<void, Error> {
366 auto status = lightly_edge_rs::insert_into_embedding_database(
367 this->lightly_edge, embedding.data(), embedding.size());
368 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
369 return status_to_unexpected(&status);
391 -> tl::expected<
void,
Error> {
392 auto status = lightly_edge_cxx::clear_embedding_database(*this->lightly_edge_cxx);
393 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
394 return cxx_status_to_unexpected(status);
405 return lightly_edge_rs::num_diversity_strategies(this->lightly_edge);
414 return lightly_edge_rs::num_similarity_strategies(this->lightly_edge);
423 return lightly_edge_rs::num_adaptive_diversity_strategies(this->lightly_edge);
432 return lightly_edge_rs::num_detection_strategies(this->lightly_edge);
519 -> tl::expected<void, Error> {
521 lightly_edge_rs::register_diversity_strategy(this->lightly_edge, min_distance);
522 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
523 return status_to_unexpected(&status);
568 float max_distance)
const ->
void {
623 float max_distance)
const noexcept
624 -> tl::expected<void, Error> {
625 auto status = lightly_edge_rs::register_similarity_strategy(
626 this->lightly_edge, query_embedding.data(), query_embedding.size(),
628 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
629 return status_to_unexpected(&status);
666 float target_ratio,
size_t buffer_max_length = BUFFER_MAX_LENGTH)
const ->
void {
706 float target_ratio,
size_t buffer_max_length = BUFFER_MAX_LENGTH)
const noexcept
707 -> tl::expected<void, Error> {
708 auto status = lightly_edge_rs::register_adaptive_diversity_strategy(
709 this->lightly_edge, target_ratio, buffer_max_length);
710 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
711 return status_to_unexpected(&status);
750 float threshold)
const ->
void {
791 float threshold)
const noexcept
792 -> tl::expected<void, Error> {
793 auto status = lightly_edge_rs::register_detection_strategy(
794 this->lightly_edge, class_id, subclass_id, threshold);
795 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
796 return status_to_unexpected(&status);
833 -> std::vector<std::vector<float>> {
863 -> tl::expected<std::vector<std::vector<float>>,
Error> {
865 lightly_edge_rs::embedding_dimension(this->lightly_edge);
866 size_t num_patches = lightly_edge_rs::num_patches(this->lightly_edge);
869 std::vector<std::vector<float>> embeddings(num_patches,
871 std::vector<float *> embeddings_ptrs;
872 embeddings_ptrs.reserve(num_patches);
873 for (
auto &embedding : embeddings) {
874 embeddings_ptrs.push_back(embedding.data());
878 auto status = lightly_edge_rs::embed_patches(
879 this->lightly_edge,
static_cast<uint8_t *
>(frame.rgbImageData_),
880 frame.width_ * frame.height_ * 3, frame.width_, frame.height_,
881 embeddings_ptrs.data());
883 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
884 return status_to_unexpected(&status);
943 const std::vector<PatchCoordsRel> &patches)
const noexcept
944 -> tl::expected<void, Error> {
945 auto status = lightly_edge_rs::set_embedding_patches(
946 this->lightly_edge, patches.data(), patches.size());
947 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
948 return status_to_unexpected(&status);
957 lightly_edge_cxx::reset_embedding_patches(*this->lightly_edge_cxx);
1002 const std::vector<ObjectDetection> &detections)
const
1052 const std::vector<ObjectDetection> &detections)
const noexcept
1053 -> tl::expected<SelectInfo, Error> {
1055 CStatus status = {};
1056 auto select_info_buffers = SelectInfoBuffers(this->lightly_edge);
1057 auto out_info = select_info_buffers.to_c_select_info();
1059 status = lightly_edge_rs::should_select(this->lightly_edge, embedding.data(),
1060 embedding.size(), detections.data(),
1061 detections.size(), &out_info);
1062 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
1063 return status_to_unexpected(&status);
1067 auto select_info = select_info_buffers.to_select_info();
1117 const std::vector<ObjectDetection> &detections)
const
1171 const std::vector<std::vector<float>> &embeddings,
1172 const std::vector<ObjectDetection> &detections)
const noexcept
1173 -> tl::expected<SelectInfo, Error> {
1175 CStatus status = {};
1176 auto select_info_buffers = SelectInfoBuffers(this->lightly_edge);
1177 auto out_info = select_info_buffers.to_c_select_info();
1183 size_t embedding_dim = embeddings.empty() ? 0 : embeddings[0].size();
1186 for (
const auto &embedding : embeddings) {
1187 if (embedding.size() != embedding_dim) {
1189 CPP_SDK_ERROR_CODE,
"All patch embeddings must have the same dimension"));
1194 std::vector<const float *> embeddings_ptrs;
1195 embeddings_ptrs.reserve(embeddings.size());
1196 for (
const auto &embedding : embeddings) {
1197 embeddings_ptrs.push_back(embedding.data());
1200 status = lightly_edge_rs::should_select_with_patches(
1201 this->lightly_edge, embeddings_ptrs.data(), embeddings_ptrs.size(),
1202 embedding_dim, detections.data(), detections.size(), &out_info);
1203 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
1204 return status_to_unexpected(&status);
1208 auto select_info = select_info_buffers.to_select_info();
1219 -> tl::expected<std::vector<ObjectDetection>,
Error> {
1220 std::vector<ObjectDetection> detections;
1223 const auto capacity = 1000;
1224 detections.resize(capacity);
1225 size_t detections_count = detections.size();
1226 auto status = lightly_edge_rs::detect(
1227 this->lightly_edge,
static_cast<uint8_t *
>(frame.rgbImageData_),
1228 frame.width_ * frame.height_ * 3, frame.width_, frame.height_,
1229 detections.data(), &detections_count);
1230 detections.resize(detections_count);
1231 if (status.code != lightly_edge_rs::SUCCESS_CODE) {
1232 return status_to_unexpected(&status);
1242 [[nodiscard]]
auto detect(
const Frame &frame)
const -> std::vector<ObjectDetection> {
1259 -> std::vector<std::
string> {
1262 const auto capacity = 1000;
1263 size_t classes_count = capacity;
1264 std::vector<const char *> cstr_class_labels(classes_count);
1265 auto status = lightly_edge_rs::detection_class_labels(
1266 this->lightly_edge, cstr_class_labels.data(), &classes_count);
1270 assert(status.code == lightly_edge_rs::SUCCESS_CODE);
1273 std::vector<std::string> class_labels(classes_count);
1274 for (
size_t i = 0; i < classes_count; ++i) {
1275 class_labels[i] = cstr_class_labels[i];
1277 return class_labels;
1297 -> std::vector<std::string> {
1300 const auto capacity = 1000;
1301 size_t subclasses_count = capacity;
1302 std::vector<const char *> cstr_subclass_labels(subclasses_count);
1303 auto status = lightly_edge_rs::detection_subclass_labels(
1304 this->lightly_edge, class_id, cstr_subclass_labels.data(), &subclasses_count);
1308 assert(status.code == lightly_edge_rs::SUCCESS_CODE);
1311 std::vector<std::string> subclass_labels(subclasses_count);
1312 for (
size_t i = 0; i < subclasses_count; ++i) {
1313 subclass_labels[i] = cstr_subclass_labels[i];
1315 return subclass_labels;
1320 explicit LightlyEdge(lightly_edge_rs::LightlyEdge *lightly_edge_)
1321 : lightly_edge(lightly_edge_),
1323 reinterpret_cast<lightly_edge_cxx::
LightlyEdge *>(lightly_edge_)) {}
1325 explicit LightlyEdge(lightly_edge_cxx::LightlyEdge *lightly_edge_cxx_)
1327 reinterpret_cast<lightly_edge_rs::
LightlyEdge *>(lightly_edge_cxx_)),
1328 lightly_edge_cxx(lightly_edge_cxx_) {}
1329 lightly_edge_cxx::LightlyEdge *lightly_edge_cxx{};
1330 lightly_edge_rs::LightlyEdge *lightly_edge{};
1335 class SelectInfoBuffers {
1337 explicit SelectInfoBuffers(lightly_edge_rs::LightlyEdge *lightly_edge)
1340 out_adaptive_diversity_size(
1342 out_detection_selection_size(
1345 resize_buffers_to_match_sizes();
1352 [[nodiscard]]
auto to_c_select_info()
1353 -> lightly_edge_rs::SelectionStrategiesSelectInfo {
1354 lightly_edge_rs::SelectionStrategiesSelectInfo out_info{};
1355 out_info.out_diversity_buffer = diversity.data();
1356 out_info.diversity_buffer_size = diversity.size();
1357 out_info.out_diversity_size = &out_diversity_size;
1359 out_info.out_similarity_buffer = similarity.data();
1360 out_info.similarity_buffer_size = similarity.size();
1361 out_info.out_similarity_size = &out_similarity_size;
1363 out_info.out_adaptive_diversity_buffer = adaptive_diversity.data();
1364 out_info.adaptive_diversity_buffer_size = adaptive_diversity.size();
1365 out_info.out_adaptive_diversity_size = &out_adaptive_diversity_size;
1367 out_info.out_detection_buffer = detection.data();
1368 out_info.detection_buffer_size = detection.size();
1369 out_info.out_detection_size = &out_detection_selection_size;
1381 resize_buffers_to_match_sizes();
1384 select_info.
diversity = std::move(diversity);
1385 select_info.
similarity = std::move(similarity);
1387 select_info.
detection = std::move(detection);
1392 size_t out_diversity_size;
1393 size_t out_similarity_size;
1394 size_t out_adaptive_diversity_size;
1395 size_t out_detection_selection_size;
1396 std::vector<lightly_edge_rs::DiversitySelectInfo> diversity;
1397 std::vector<lightly_edge_rs::SimilaritySelectInfo> similarity;
1398 std::vector<lightly_edge_rs::AdaptiveDiversitySelectInfo> adaptive_diversity;
1399 std::vector<lightly_edge_rs::DetectionSelectInfo> detection;
1401 void resize_buffers_to_match_sizes() {
1402 diversity.resize(out_diversity_size);
1403 similarity.resize(out_similarity_size);
1404 adaptive_diversity.resize(out_adaptive_diversity_size);
1405 detection.resize(out_detection_selection_size);
LightlyEdge.
Definition lightly_edge_sdk.h:119
auto embed_texts(const std::vector< std::string > &texts) const -> std::vector< std::vector< float > >
Embed a list of text strings.
Definition lightly_edge_sdk.h:279
auto register_similarity_strategy_noexcept(const std::vector< float > &query_embedding, float max_distance) const noexcept -> tl::expected< void, Error >
Register a similarity strategy, noexcept version.
Definition lightly_edge_sdk.h:622
auto embed_frame_noexcept(const Frame &frame) const noexcept -> tl::expected< std::vector< float >, Error >
Embed an RGB image.
Definition lightly_edge_sdk.h:242
static auto new_from_tar(const std::string &archive_path, LightlyEdgeConfig config) -> LightlyEdge
Initialize LightlyEdge with an ort embedding inference backend.
Definition lightly_edge_sdk.h:171
auto num_diversity_strategies() const noexcept -> size_t
Get the number of registered diversity strategies.
Definition lightly_edge_sdk.h:404
LightlyEdge(LightlyEdge &&other) noexcept
Move constructor.
Definition lightly_edge_sdk.h:133
auto clear_embedding_database() const -> void
Clear the embedding database.
Definition lightly_edge_sdk.h:381
auto register_diversity_strategy(float min_distance) const -> void
Register a diversity strategy.
Definition lightly_edge_sdk.h:471
LightlyEdge(const LightlyEdge &other)=delete
Copy constructor (disallowed).
auto register_adaptive_diversity_strategy_noexcept(float target_ratio, size_t buffer_max_length=BUFFER_MAX_LENGTH) const noexcept -> tl::expected< void, Error >
Register an adaptive diversity strategy, no except version.
Definition lightly_edge_sdk.h:705
void reset_embedding_patches()
Reset the embedding patches to full image patch.
Definition lightly_edge_sdk.h:956
auto num_similarity_strategies() const noexcept -> size_t
Get the number of registered similarity strategies.
Definition lightly_edge_sdk.h:413
auto should_select_with_patches(const std::vector< std::vector< float > > &embeddings, const std::vector< ObjectDetection > &detections) const -> SelectInfo
Check if a frame should be selected taking patches into account.
Definition lightly_edge_sdk.h:1116
auto set_embedding_patches(const std::vector< PatchCoordsRel > &patches) const -> void
Set the embedding patches.
Definition lightly_edge_sdk.h:917
auto register_detection_strategy_noexcept(uint32_t class_id, int32_t subclass_id, float threshold) const noexcept -> tl::expected< void, Error >
Register a detection strategy, noexcept version.
Definition lightly_edge_sdk.h:790
auto register_detection_strategy(uint32_t class_id, int32_t subclass_id, float threshold) const -> void
Register a detection strategy.
Definition lightly_edge_sdk.h:749
auto detect(const Frame &frame) const -> std::vector< ObjectDetection >
Run object detection on a frame.
Definition lightly_edge_sdk.h:1242
auto register_similarity_strategy(const std::vector< float > &query_embedding, float max_distance) const -> void
Register a similarity strategy.
Definition lightly_edge_sdk.h:567
auto insert_into_embedding_database_noexcept(const std::vector< float > &embedding) const noexcept -> tl::expected< void, Error >
Insert an embedding into the database.
Definition lightly_edge_sdk.h:364
auto register_diversity_strategy_noexcept(float min_distance) const noexcept -> tl::expected< void, Error >
Register a diversity strategy, noexcept version.
Definition lightly_edge_sdk.h:518
auto operator=(const LightlyEdge &other) -> LightlyEdge &=delete
Copy assignment operator (disallowed).
void insert_into_embedding_database(const std::vector< float > &embedding) const
Insert an embedding into the database.
Definition lightly_edge_sdk.h:340
~LightlyEdge()
Deallocate the memory associated with a LightlyEdge.
Definition lightly_edge_sdk.h:124
auto detect_noexcept(const Frame &frame) const noexcept -> tl::expected< std::vector< ObjectDetection >, Error >
Run object detection on a frame.
Definition lightly_edge_sdk.h:1218
auto embed_texts_noexcept(const std::vector< std::string > &texts) const noexcept -> tl::expected< std::vector< std::vector< float > >, Error >
Embed a list of text strings.
Definition lightly_edge_sdk.h:296
auto should_select(const std::vector< float > &embedding, const std::vector< ObjectDetection > &detections) const -> SelectInfo
Check if a frame should be selected.
Definition lightly_edge_sdk.h:1001
auto detection_class_labels() const noexcept -> std::vector< std::string >
Get labels of object detection classes.
Definition lightly_edge_sdk.h:1258
auto clear_embedding_database_noexcept() const noexcept -> tl::expected< void, Error >
Clear the embedding database.
Definition lightly_edge_sdk.h:390
static auto new_from_tar_noexcept(const std::string &archive_path, LightlyEdgeConfig config) noexcept -> tl::expected< LightlyEdge, Error >
Initialize LightlyEdge with an ort inference backend.
Definition lightly_edge_sdk.h:182
auto should_select_with_patches_noexcept(const std::vector< std::vector< float > > &embeddings, const std::vector< ObjectDetection > &detections) const noexcept -> tl::expected< SelectInfo, Error >
Check if a frame should be selected taking patches into account.
Definition lightly_edge_sdk.h:1170
void clear_strategies()
Clear all registered selection strategies.
Definition lightly_edge_sdk.h:804
auto detection_subclass_labels(uint32_t class_id) const noexcept -> std::vector< std::string >
Get the subclass labels for a specified detection class.
Definition lightly_edge_sdk.h:1296
auto embed_patches_noexcept(const Frame &frame) const noexcept -> tl::expected< std::vector< std::vector< float > >, Error >
Embed patches of an image, noexcept version.
Definition lightly_edge_sdk.h:862
auto operator=(LightlyEdge &&other) noexcept -> LightlyEdge &
Move assignment operator.
Definition lightly_edge_sdk.h:142
static auto new_from_directory(const std::string &model_directory, LightlyEdgeConfig config)
Initialize LightlyEdge with an ort inference backend.
Definition lightly_edge_sdk.h:200
auto num_adaptive_diversity_strategies() const noexcept -> size_t
Get the number of registered adaptive diversity strategies.
Definition lightly_edge_sdk.h:422
auto embed_patches(const Frame &frame) const -> std::vector< std::vector< float > >
Embed patches of an image.
Definition lightly_edge_sdk.h:832
auto num_detection_strategies() const noexcept -> size_t
Get the number of registered detection strategies.
Definition lightly_edge_sdk.h:431
auto register_adaptive_diversity_strategy(float target_ratio, size_t buffer_max_length=BUFFER_MAX_LENGTH) const -> void
Register an adaptive diversity strategy.
Definition lightly_edge_sdk.h:665
auto set_embedding_patches_noexcept(const std::vector< PatchCoordsRel > &patches) const noexcept -> tl::expected< void, Error >
Set the embedding patches, noexcept version.
Definition lightly_edge_sdk.h:942
auto should_select_noexcept(const std::vector< float > &embedding, const std::vector< ObjectDetection > &detections) const noexcept -> tl::expected< SelectInfo, Error >
Check if a frame should be selected.
Definition lightly_edge_sdk.h:1051
auto embed_frame(const Frame &frame) const -> std::vector< float >
Embed an RGB image.
Definition lightly_edge_sdk.h:232
auto embedding_dimension() const noexcept -> size_t
Get the embedding dimension.
Definition lightly_edge_sdk.h:264
static auto new_from_directory_noexcept(const std::string &model_directory, LightlyEdgeConfig config) noexcept -> tl::expected< LightlyEdge, Error >
Initialize LightlyEdge with an ort inference backend.
Definition lightly_edge_sdk.h:213
Namespace with core LightlyEdge SDK functionality.
Definition lightly_edge_error.h:15
auto value_or_throw(tl::expected< T, lightly_edge_sdk::Error > &&result) -> T
Convenience function to unwrap a result of lightly_edge_sdk::LightlyEdge functions.
Definition lightly_edge_error.h:79
Holds information whether a frame should be selected or not.
Definition lightly_edge_rs_bindings.h:54
Definition lightly_edge_rs_bindings.h:59
Holds information whether a frame should be selected or not.
Definition lightly_edge_rs_bindings.h:42
Definition lightly_edge_rs_bindings.h:31
A patch specified by relative coordinates.
Definition lightly_edge_rs_bindings.h:82
Holds information whether a frame should be selected or not.
Definition lightly_edge_rs_bindings.h:48
Error struct to hold error code and message.
Definition lightly_edge_error.h:20
Frame data for LightlyEdge.
Definition lightly_edge_sdk.h:25
size_t width_
Width of the image.
Definition lightly_edge_sdk.h:29
void * rgbImageData_
Pointer to the RGB image data.
Definition lightly_edge_sdk.h:42
size_t height_
Height of the image.
Definition lightly_edge_sdk.h:34
Frame(size_t width, size_t height, void *rgbImageData)
Construct a new Frame object.
Definition lightly_edge_sdk.h:52
Selection information about a processed frame.
Definition lightly_edge_sdk.h:84
std::vector< DiversitySelectInfo > diversity
The diversity selection info for each diversity strategy in the order of registration.
Definition lightly_edge_sdk.h:89
std::vector< SimilaritySelectInfo > similarity
The similarity selection info for each similarity strategy in the order of registration.
Definition lightly_edge_sdk.h:95
std::vector< AdaptiveDiversitySelectInfo > adaptive_diversity
The adaptive diversity selection info for each adaptive diversity strategy in the order of registrati...
Definition lightly_edge_sdk.h:101
std::vector< DetectionSelectInfo > detection
The detection selection info for each detection strategy in the order of registration.
Definition lightly_edge_sdk.h:107