ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
BackendFactory.hpp
Go to the documentation of this file.
1#pragma once
2#include "reusex/core/logging.hpp"
3#include "reusex/vision/IMLBackend.hpp"
4
5#ifdef REUSEX_USE_LIBTORCH
6#include "reusex/vision/libtorch/Backend.hpp"
7#endif
8
9#ifdef REUSEX_USE_TENSORRT
10#include "reusex/vision/tensor_rt/Backend.hpp"
11#endif
12
13#ifdef REUSEX_USE_ONNX
14#include "reusex/vision/onnx/Backend.hpp"
15#endif
16
17#ifdef REUSEX_USE_OPENVINO
18#include "reusex/vision/openvino/Backend.hpp"
19#endif
20
21#include <fmt/std.h>
22
23#include <algorithm>
24#include <cctype>
25#include <filesystem>
26
27namespace reusex::vision {
37
39 public:
40 /* Detects the model type from the model path.
41 *
42 * Inspects the path stem and, for directories, contained file names.
43 * Detection is case-insensitive:
44 * - "sam3" or "sam2" in the name -> Model::sam3
45 * - directory containing "vision-encoder.*" -> Model::sam3
46 * - otherwise -> Model::yolo
47 *
48 * @param model_path: The file or directory path of the model.
49 * @return The detected model type.
50 */
51 static Model detect_model(const std::filesystem::path &model_path) {
52 auto to_lower = [](std::string s) {
53 std::transform(s.begin(), s.end(), s.begin(),
54 [](unsigned char c) { return std::tolower(c); });
55 return s;
56 };
57
58 // Check directory/file name itself
59 auto name = to_lower(model_path.stem().string());
60 if (name.find("sam3") != std::string::npos ||
61 name.find("sam2") != std::string::npos) {
62 reusex::info("Detected SAM3 model from path name: {}", model_path);
63 return Model::sam3;
64 }
65
66 // For directories, check contained filenames for SAM3 sub-models
67 if (std::filesystem::is_directory(model_path)) {
68 for (const auto &entry :
69 std::filesystem::directory_iterator(model_path)) {
70 auto stem = to_lower(entry.path().stem().string());
71 if (stem.find("vision-encoder") != std::string::npos) {
72 reusex::info("Detected SAM3 model from sub-model file: {}",
73 entry.path());
74 return Model::sam3;
75 }
76 }
77 }
78
79 reusex::info("Defaulting to YOLO model type for path: {}", model_path);
80 return Model::yolo;
81 }
82
83 /* Detects the appropriate backend based on the model path.
84 * @param model_path: The file or directory path of the model.
85 * @return The detected backend type.
86 */
87 static Backend detect_backend(const std::filesystem::path &model_path) {
88 using namespace std::filesystem;
89
90 if (is_regular_file(model_path))
91 return detect_backend_from_file(model_path);
92
93 if (is_directory(model_path))
94 for (const auto &entry : directory_iterator(model_path))
95 if (entry.is_regular_file())
96 if (auto backend = detect_backend_from_file(entry.path());
97 backend != Backend::unknown)
98 return backend;
99
100 return Backend::unknown;
101 }
102
103 /* Creates an instance of the specified backend type.
104 * @param type: The backend type to create.
105 * @return A unique pointer to the created backend instance.
106 * @throws std::runtime_error if the backend type is not implemented or
107 * unsupported.
108 */
109 static std::unique_ptr<IMLBackend> create(Backend type) {
110 switch (type) {
111 case Backend::opencv:
112 reusex::error("OpenCV backend is not implemented yet.");
113 throw std::runtime_error("OpenCV backend not implemented");
114
116#ifdef REUSEX_USE_TENSORRT
117 return std::make_unique<reusex::vision::tensor_rt::TensorRTBackend>();
118#else
119 reusex::error("TensorRT backend not compiled in this build. "
120 "Rebuild with -DML_BACKENDS=TensorRT or AUTO.");
121 throw std::runtime_error("TensorRT backend not available");
122#endif
123
125#ifdef REUSEX_USE_LIBTORCH
126 return std::make_unique<reusex::vision::libtorch::LibTorchBackend>();
127#else
128 reusex::error("LibTorch backend not compiled in this build. "
129 "Rebuild with -DML_BACKENDS=LibTorch or AUTO.");
130 throw std::runtime_error("LibTorch backend not available");
131#endif
132
133 case Backend::dnn:
134 reusex::error("DNN backend is not implemented yet.");
135 throw std::runtime_error("DNN backend not implemented");
136
138#ifdef REUSEX_USE_ONNX
139 return std::make_unique<reusex::vision::onnx::ONNXBackend>();
140#else
141 reusex::error("ONNX Runtime backend is not implemented yet.");
142 throw std::runtime_error("ONNX Runtime backend not implemented");
143#endif
144
146#ifdef REUSEX_USE_OPENVINO
147 return std::make_unique<reusex::vision::openvino::OpenVINOBackend>();
148#else
149 reusex::error("OpenVINO backend is not implemented yet.");
150 throw std::runtime_error("OpenVINO backend not implemented");
151#endif
152
153 default:
154 reusex::error("Unsupported backend type: {}", static_cast<int>(type));
155 throw std::runtime_error("Unsupported backend");
156 }
157 }
158
159 private:
160 /* Helper function to detect backend type from a single file based on its
161 * extension.
162 * @param file_path: The path of the file to analyze.
163 * @return The detected backend type or unknown if the extension is not
164 * recognized.
165 */
166 static Backend
167 detect_backend_from_file(const std::filesystem::path &file_path) {
168 auto ext = file_path.extension();
169
170 if (ext.empty()) {
171 reusex::warn("File {} has no extension. Unable to detect backend.",
172 file_path);
173 return Backend::unknown;
174 }
175
176 else if (ext == ".engine") {
177 reusex::info("Detected TensorRT engine file: {}", file_path);
178#ifndef REUSEX_USE_TENSORRT
179 reusex::warn("TensorRT detected but not compiled in this build. Backend "
180 "unavailable.");
181#endif
182 return Backend::tensor_rt;
183 } else if (ext == ".pt" || ext == ".pth" || ext == ".torchscript") {
184 reusex::info("Detected PyTorch model file: {}", file_path);
185#ifndef REUSEX_USE_LIBTORCH
186 reusex::warn("LibTorch detected but not compiled in this build. Backend "
187 "unavailable.");
188#endif
189 return Backend::libtorch;
190 } else if (ext == ".onnx") {
191 reusex::info("Detected ONNX model file: {}", file_path);
192#ifndef REUSEX_USE_ONNX
193 reusex::warn("ONNX Runtime detected but not compiled in this build. "
194 "Backend unavailable.");
195#endif
197 } else if (ext == ".xml" || ext == ".bin") {
198 reusex::info("Detected OpenVINO model files: {}", file_path);
199#ifndef REUSEX_USE_OPENVINO
200 reusex::warn("OpenVINO detected but not compiled in this build. Backend "
201 "unavailable.");
202#endif
203 return Backend::openvino;
204 }
205
206 reusex::warn("Unknown model file extension: {}. Unable to detect backend; "
207 "returning Backend::unknown.",
208 ext);
209 return Backend::unknown;
210 }
211};
212} // namespace reusex::vision
static Model detect_model(const std::filesystem::path &model_path)
static Backend detect_backend(const std::filesystem::path &model_path)
static std::unique_ptr< IMLBackend > create(Backend type)
void warn(fmt::format_string< Args... > format, Args &&...args)
Definition logging.hpp:93
void error(fmt::format_string< Args... > format, Args &&...args)
Definition logging.hpp:100
void info(fmt::format_string< Args... > format, Args &&...args)
Definition logging.hpp:86