ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
Sam3.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#include "reusex/vision/IData.hpp"
7#include "reusex/vision/IModel.hpp"
8#include "reusex/vision/common/object.hpp"
9#include "reusex/vision/sam3_geometry.hpp"
10#include "reusex/vision/tensor_rt/Data.hpp"
11#include "reusex/vision/tensor_rt/Sam3Type.hpp"
12#include "reusex/vision/tensor_rt/common/memory.hpp"
13#include "reusex/vision/tensor_rt/common/norm.hpp"
14#include "reusex/vision/tensor_rt/common/tensorrt.hpp"
15
16#include <tokenizers_cpp.h>
17
18#include <optional>
19#include <unordered_map>
20#include <vector>
21
23
24/* TensorRTSam3 is an implementation of the SAM3 model using TensorRT for
25efficient inference. It supports batch processing of images and prompts, with
26careful memory management to optimize performance on GPU. The class handles the
27loading of TensorRT engines for the vision encoder, text encoder, geometry
28encoder, and decoder, and provides a forward method to process input data and
29produce segmentation results. The implementation includes preprocessing of
30images, gathering of features from the vision encoder, and post-processing of
31the decoder outputs to generate final masks and bounding boxes. The design
32allows for flexibility in handling different types of prompts (text and
33geometry) and is optimized for use in real-time applications where latency is a
34concern. */
35class TensorRTSam3 : public IModel {
36 private:
38 using InferResultArray =
39 std::vector<::reusex::vision::common::object::DetectionBoxArray>;
40
41 public:
42 /* Constructor for TensorRTSam3 without geometry encoder. Initializes the
43 * model with the specified paths for the vision encoder, text encoder, and
44 * decoder, and sets the GPU ID for inference.
45 * @param vision_encoder_path: Path to the TensorRT engine file for the vision
46 * encoder.
47 * @param text_encoder_path: Path to the TensorRT engine file for the text
48 * encoder.
49 * @param decoder_path: Path to the TensorRT engine file for the decoder.
50 * @param gpu_id: ID of the GPU to use for inference.
51 */
52 TensorRTSam3(const std::string &vision_encoder_path,
53 const std::string &text_encoder_path,
54 const std::string &geometry_encoder_path,
55 const std::string &decoder_path,
56 const std::string &tokenizer_path, int gpu_id);
57
58 /* Destructor for TensorRTSam3. Cleans up any resources used by the model.
59 * @param model_path: Path to the model files (not used in this
60 * implementation).
61 * @return A unique pointer to an instance of TensorRTSam3.
62 */
63 static std::unique_ptr<TensorRTSam3>
64 create(const std::filesystem::path &model_path);
65
66 /* Forward method for TensorRTSam3. Takes a span of input pairs and processes
67 * them through the model to produce output pairs. This method handles the
68 * entire inference pipeline, including preprocessing, feature extraction,
69 * decoding, and post-processing to generate the final segmentation results.
70 * @param input: A span of input pairs containing the data to be processed.
71 * @return A vector of output pairs containing the results of the inference.
72 *
73 * Not reentrant: forward() reuses the model's device buffers and updates
74 * the geometry-failure state (a request whose geometry path fails is re-run
75 * text-only; Sam3GeometryFailures::kFailuresBeforeDisable such requests in
76 * a row turn box and point prompts off). Callers serialise it.
77 */
78 std::vector<IDataset::Pair>
79 forward(const std::span<IDataset::Pair> &input) override;
80
81 protected:
82 // virtual ~TensorRTSam3() = default;
83
84 /* Loads the TensorRT engines for the vision encoder, text encoder, geometry
85 * encoder, and decoder. This method is responsible for initializing the
86 * engines based on the provided model paths and ensuring that they are ready
87 * for inference. It returns true if all engines are loaded successfully, and
88 * false otherwise.
89 * @return A boolean indicating whether the engines were loaded successfully.
90 */
92
93 static std::string load_bytes_from_file(const std::string &file_path);
94
96 const cv::Mat &image, const std::string &label,
97 const std::vector<std::pair<std::string, std::array<float, 4>>> &boxes);
98
99 /*
100 // Core implementation
101 virtual InferResultArray forwards(const std::vector<Sam3Input> &inputs,
102 bool return_mask = false,
103 void *stream = nullptr) override;
104 virtual InferResultArray forwards(const std::vector<Sam3Input> &inputs,
105 const std::string &geom_label,
106 bool return_mask = false,
107 void *stream = nullptr) override;
108 */
109
110 private:
111 // Define internal structure for flattening Prompt
112 struct PromptMeta {
113 int image_idx; // Which image this Prompt belongs to
114 int original_idx; // The index of this Prompt in the original image vector
115 const Sam3PromptUnit *ptr; // Pointer to the original Prompt data
118 float point_frac = 0.f;
119 };
120
121 // Internal processing function
122 void preprocess(const TensorRTData &input, int ibatch, void *stream);
123
124 bool encode_image(int batch_size, void *stream);
125
126 // Modification: Gather features, collect data from Vision features according
127 // to the image index corresponding to the current Prompt Batch
128 void gather_vision_features(const std::vector<PromptMeta> &batch_prompts,
129 int batch_size, void *stream);
130
131 // Modified encoding function, based on the current batch size
132 bool encode_text(const std::vector<PromptMeta> &batch_prompts, int batch_size,
133 void *stream);
139 bool encode_boxes(const std::vector<PromptMeta> &batch_prompts,
140 int batch_size, int slot_boxes, void *stream);
141 bool decode(int batch_size, int prompt_len, void *stream);
142
143 // Post-processing
144 void postprocess(InferResult &image_result, int batch_idx, int image_idx,
145 const std::string &label, const int label_id,
146 float confidence_threshold, bool return_mask, void *stream);
147
148 /* Allocates memory for all the necessary buffers used during inference. This
149 * method is designed to be called only once during the initialization phase
150 * of the model, and it sets up the memory structures based on the maximum
151 * batch sizes and input dimensions defined in the class. It ensures that all
152 * buffers are properly allocated and ready for use during the forward pass,
153 * optimizing memory usage and performance on the GPU.
154 */
155 void allocate_memory_once();
156
159 std::optional<bool> probe_mask_polarity();
160
161 void set_binding_dim(std::shared_ptr<TensorRT::Engine> &engine,
162 int binding_index, const std::vector<int> &dims);
163
164 private:
165 // Configuration
166 bool isdynamic_model_ = true;
167 int input_image_width_ = 1008;
168 int input_image_height_ = 1008;
169 int gpu_id_ = 0;
170
171 // --- Batch processing limit configuration ---
172 // Can be adjusted according to VRAM size
173 const int max_image_batch_ =
174 2; // This Vision Encoder is relatively large, limit the number of images
175 // processed simultaneously
176 const int max_prompt_batch_ =
177 4; // Decoder is smaller, but VRAM is limited, limit the number of Prompts
178 // decoded each time
179 const int max_boxes_per_prompt_ =
180 20; // Preset maximum number of supported Boxes
181
186 int geom_max_boxes_ = 0;
187
189 Sam3GeometryFailures geometry_failures_;
190
194 bool mask_true_is_valid_ = true;
195
196 // State variables
197 std::vector<std::pair<int, int>>
198 original_image_sizes_; // Size: max_image_batch_
199 int num_queries_ = 200;
200 int mask_height_ = 288;
201 int mask_width_ = 288;
202
203 // Model path
204 std::string vision_encoder_path_;
205 std::string text_encoder_path_;
206 std::string geometry_encoder_path_;
207 std::string decoder_path_;
208
209 // TRT engine
210 std::shared_ptr<TensorRT::Engine> vision_encoder_trt_;
211 std::shared_ptr<TensorRT::Engine> text_encoder_trt_;
212 std::shared_ptr<TensorRT::Engine> decoder_trt_;
213 std::shared_ptr<TensorRT::Engine> geometry_encoder_trt_;
214
215 // std::unordered_map<
216 // std::string, std::pair<std::array<int64_t, 32>, std::array<int64_t,
217 // 32>>> text_input_map_;
218 // INFO:
219 // The first array is for input_ids, the second is for attention_mask. The
220 // last int is the prompt ID
221 std::unordered_map<std::string, std::tuple<std::array<int64_t, 32>,
222 std::array<int64_t, 32>, int>>
223 text_input_map_;
224
225 // --- Memory management ---
227 1.0f / 127.5f, -1.0f, norm_image::ChannelType::SwapRB);
228
229 std::vector<int> vision_input_shape_;
230 std::vector<int> fpn_feat_0_shape_;
231 std::vector<int> text_ids_shape_;
232 std::vector<int> geom_box_shape_;
233
234 // Image Batch buffers (Size: max_image_batch_)
235 tensor::Memory<float> preprocessed_images_;
236 std::vector<std::shared_ptr<tensor::Memory<uint8_t>>> original_images_buf_;
237 tensor::Memory<float> affine_matrix_;
238 // Mask post-processing requires the corresponding matrix of the original
239 // image (Size: max_image_batch_)
240 tensor::Memory<float> mask_affine_matrix_;
241
242 // Vision Encoder Outputs (Size: max_image_batch_)
243 tensor::Memory<float> fpn_feat_0_;
244 tensor::Memory<float> fpn_feat_1_;
245 tensor::Memory<float> fpn_feat_2_;
246 tensor::Memory<float> fpn_pos_2_;
247
248 // Decoder Input Buffers (Size: max_prompt_batch_)
249 // These are gathered from Vision Output
250 tensor::Memory<float> fpn_feat_0_gather_;
251 tensor::Memory<float> fpn_feat_1_gather_;
252 tensor::Memory<float> fpn_feat_2_gather_;
253 tensor::Memory<float> fpn_pos_2_gather_;
254
255 // Prompt Inputs (Size: max_prompt_batch_)
256 tensor::Memory<int64_t> text_input_ids_;
257 tensor::Memory<int64_t> text_attention_mask_;
258
259 tensor::Memory<float> geom_boxes_;
260 tensor::Memory<int64_t> geom_labels_;
261
262 tensor::Memory<float> text_features_;
263 tensor::Memory<bool> text_mask_;
264
265 tensor::Memory<float> geom_features_;
266 tensor::Memory<bool> geom_mask_;
272 tensor::Memory<bool> geom_valid_mask_;
273
274 // Used to store the results of pre-set geometry models
275 std::unordered_map<std::string, std::shared_ptr<tensor::Memory<float>>>
276 geom_features_cache_;
277 std::unordered_map<std::string, std::shared_ptr<tensor::Memory<bool>>>
278 geom_mask_cache_;
279
280 tensor::Memory<float> prompt_features_;
281 tensor::Memory<bool> prompt_mask_;
282
283 // Decoder Output (Size: max_prompt_batch_)
284 tensor::Memory<float> pred_masks_;
285 tensor::Memory<float> pred_boxes_;
286 tensor::Memory<float> pred_logits_;
287 tensor::Memory<float> presence_logits_;
288
289 // Postprocess (Size: max_prompt_batch_)
290 tensor::Memory<float> filter_boxes_;
291 tensor::Memory<float> filter_scores_;
292 tensor::Memory<int> filter_indices_;
293 tensor::Memory<int> box_count_;
294 tensor::Memory<uint8_t> mask_buffer_;
296 box_affine_matrices_; // Matrix for each Box during Mask recovery
297
298 // Tokenizer
299 std::unique_ptr<tokenizers::Tokenizer> tokenizer_;
300};
301} // namespace reusex::vision::tensor_rt
When a request's geometry path fails at run time (encode_boxes / decode with a geometry slot),...
static std::unique_ptr< TensorRTSam3 > create(const std::filesystem::path &model_path)
TensorRTSam3(const std::string &vision_encoder_path, const std::string &text_encoder_path, const std::string &geometry_encoder_path, const std::string &decoder_path, const std::string &tokenizer_path, int gpu_id)
std::vector< IDataset::Pair > forward(const std::span< IDataset::Pair > &input) override
bool setup_geometry_input(const cv::Mat &image, const std::string &label, const std::vector< std::pair< std::string, std::array< float, 4 > > > &boxes)
static std::string load_bytes_from_file(const std::string &file_path)
std::vector< DetectionBox > DetectionBoxArray
Convenience alias for a collection of DetectionBox results.
Definition object.hpp:216
static Norm alpha_beta(float alpha, float beta=0, ChannelType channel_type=ChannelType::None)