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) {
73 "Detected SAM3 model from sub-model file: {}", entry.path());
74 return Model::sam3;
75 }
76 }
77 }
78
79 reusex::info("Defaulting to YOLO model type for path: {}",
80 model_path);
81 return Model::yolo;
82 }
83
84 /* Detects the appropriate backend based on the model path.
85 * @param model_path: The file or directory path of the model.
86 * @return The detected backend type.
87 */
88 static Backend detect_backend(const std::filesystem::path &model_path) {
89 using namespace std::filesystem;
90
91 if (is_regular_file(model_path))
92 return detect_backend_from_file(model_path);
93
94 if (is_directory(model_path))
95 for (const auto &entry : directory_iterator(model_path))
96 if (entry.is_regular_file())
97 if (auto backend = detect_backend_from_file(entry.path());
98 backend != Backend::unknown)
99 return backend;
100
101 return Backend::unknown;
102 }
103
104 /* Creates an instance of the specified backend type.
105 * @param type: The backend type to create.
106 * @return A unique pointer to the created backend instance.
107 * @throws std::runtime_error if the backend type is not implemented or
108 * unsupported.
109 */
110 static std::unique_ptr<IMLBackend> create(Backend type) {
111 switch (type) {
112 case Backend::opencv:
113 reusex::error("OpenCV backend is not implemented yet.");
114 throw std::runtime_error("OpenCV backend not implemented");
115
117#ifdef REUSEX_USE_TENSORRT
118 return std::make_unique<reusex::vision::tensor_rt::TensorRTBackend>();
119#else
120 reusex::error("TensorRT backend not compiled in this build. "
121 "Rebuild with -DML_BACKENDS=TensorRT or AUTO.");
122 throw std::runtime_error("TensorRT backend not available");
123#endif
124
126#ifdef REUSEX_USE_LIBTORCH
127 return std::make_unique<reusex::vision::libtorch::LibTorchBackend>();
128#else
129 reusex::error("LibTorch backend not compiled in this build. "
130 "Rebuild with -DML_BACKENDS=LibTorch or AUTO.");
131 throw std::runtime_error("LibTorch backend not available");
132#endif
133
134 case Backend::dnn:
135 reusex::error("DNN backend is not implemented yet.");
136 throw std::runtime_error("DNN backend not implemented");
137
139#ifdef REUSEX_USE_ONNX
140 return std::make_unique<reusex::vision::onnx::ONNXBackend>();
141#else
142 reusex::error("ONNX Runtime backend is not implemented yet.");
143 throw std::runtime_error("ONNX Runtime backend not implemented");
144#endif
145
147#ifdef REUSEX_USE_OPENVINO
148 return std::make_unique<reusex::vision::openvino::OpenVINOBackend>();
149#else
150 reusex::error("OpenVINO backend is not implemented yet.");
151 throw std::runtime_error("OpenVINO backend not implemented");
152#endif
153
154 default:
155 reusex::error("Unsupported backend type: {}",
156 static_cast<int>(type));
157 throw std::runtime_error("Unsupported backend");
158 }
159 }
160
161 private:
162 /* Helper function to detect backend type from a single file based on its
163 * extension.
164 * @param file_path: The path of the file to analyze.
165 * @return The detected backend type or unknown if the extension is not
166 * recognized.
167 */
168 static Backend
169 detect_backend_from_file(const std::filesystem::path &file_path) {
170 auto ext = file_path.extension();
171
172 if (ext.empty()) {
173 reusex::warn("File {} has no extension. Unable to detect backend.",
174 file_path);
175 return Backend::unknown;
176 }
177
178 else if (ext == ".engine") {
179 reusex::info("Detected TensorRT engine file: {}", file_path);
180#ifndef REUSEX_USE_TENSORRT
181 reusex::warn("TensorRT detected but not compiled in this build. Backend unavailable.");
182#endif
183 return Backend::tensor_rt;
184 } else if (ext == ".pt" || ext == ".pth" || ext == ".torchscript") {
185 reusex::info("Detected PyTorch model file: {}", file_path);
186#ifndef REUSEX_USE_LIBTORCH
187 reusex::warn("LibTorch detected but not compiled in this build. Backend 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. Backend unavailable.");
194#endif
196 } else if (ext == ".xml" || ext == ".bin") {
197 reusex::info("Detected OpenVINO model files: {}", file_path);
198#ifndef REUSEX_USE_OPENVINO
199 reusex::warn("OpenVINO detected but not compiled in this build. Backend unavailable.");
200#endif
201 return Backend::openvino;
202 }
203
205 "Unknown model file extension: {}. Unable to detect backend; returning Backend::unknown.",
206 ext);
207 return Backend::unknown;
208 }
209};
210} // 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