Skip to content

Commit 58b1722

Browse files
authored
feat(sam3-image): add TensorRT support (#166)
1 parent c86d18b commit 58b1722

6 files changed

Lines changed: 675 additions & 127 deletions

File tree

examples/sam3/README.md

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,51 @@
11

2-
### Quick Start
2+
## Usage
33

44
```bash
5-
# Text prompt
6-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --dtype q4f16 --source ./assets/sam3-demo.jpg -p shoe
7-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --dtype bnb4 --source ./assets/sam3-demo.jpg -p "person in red vest"
8-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --dtype q8 --source ./assets/sam3-demo.jpg -p "boy in blue vest"
9-
10-
# Visual prompt: a single bbox
11-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --source ./assets/sam3-demo.jpg -p "visual;pos:480,290,110,360"
5+
# Basic text prompt
6+
cargo run -r -F sam3,cuda --example sam3 -- \
7+
--device cuda --dtype q4f16 --source assets/sam3-demo.jpg \
8+
-p shoe
9+
10+
# Multiple prompts
11+
cargo run -r -F sam3,cuda --example sam3 -- \
12+
--device cuda --dtype fp16 --source assets/sam3-demo.jpg \
13+
-p "person in red vest" --show-mask
14+
15+
# Multiple prompts on multiple images
16+
cargo run -r -F sam3,cuda --example sam3 -- \
17+
--device cuda --dtype q4f16 --batch 2 \
18+
--source assets/sam3-demo.jpg --source assets/bus.jpg \
19+
-p bus -p cat -p shoe -p cellphone -p person -p "short hair"
20+
21+
# Visual prompt (bbox)
22+
cargo run -r -F sam3,cuda --example sam3 -- \
23+
--device cuda --dtype fp16 --source assets/sam3-demo.jpg \
24+
-p "visual;pos:480,290,110,360"
1225

1326
# Visual prompt: multi-boxes prompting(with positive and negative boxes)
14-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --source ./assets/sam3-demo.jpg -p "visual;pos:480,290,110,360;neg:370,280,115,375"
27+
cargo run -r -F sam3 -F cuda --example sam3 -- \
28+
--device cuda --source ./assets/sam3-demo.jpg \
29+
-p "visual;pos:480,290,110,360;neg:370,280,115,375"
1530

1631
# Text + negative box
17-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --dtype fp16 --source ./assets/000000136466.jpg -p "handle"
18-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --dtype fp16 --source ./assets/000000136466.jpg -p "handle;neg:40,183,278,21"
32+
cargo run -r -F sam3,cuda --example sam3 -- \
33+
--device cuda --source assets/000000136466.jpg \
34+
-p "handle;neg:40,183,278,21"
1935

20-
# Multiple prompts (Queries)
21-
cargo run -r -F sam3 -F cuda --example sam3 -- --device cuda --dtype fp16 --source ./assets/sam3-demo.jpg --source ./assets/bus.jpg -p shoe -p face -p person
2236
```
2337

24-
25-
26-
### Prompt Format
38+
## Prompt Format
2739

2840
```
29-
"text;pos:x,y,w,h;neg:x,y,w,h"
41+
text;pos:x,y,w,h;neg:x,y,w,h
3042
```
3143

32-
- `text`: Text description
33-
- `pos:x,y,w,h`: Positive box (find similar)
34-
- `neg:x,y,w,h`: Negative box (exclude region)
44+
- `text` - Text description
45+
- `pos:x,y,w,h` - Positive box (include region)
46+
- `neg:x,y,w,h` - Negative box (exclude region)
3547

48+
## Results
3649

37-
### Results
38-
39-
![](https://github.com/jamjamjon/assets/releases/download/sam3/demo.jpg)
4050
![](https://github.com/jamjamjon/assets/releases/download/sam3/demo2.jpg)
51+
![](https://github.com/jamjamjon/assets/releases/download/sam3/demo.jpg)

examples/sam3/main.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,30 @@ struct Args {
2929
#[argh(option, default = "0.5")]
3030
conf: f32,
3131

32-
/// batch size min (default: 1)
32+
/// image batch size min
3333
#[argh(option, default = "1")]
3434
batch_min: usize,
3535

36-
/// batch size (default: 1)
36+
/// image batch size
3737
#[argh(option, default = "1")]
3838
batch: usize,
3939

40-
/// batch size max (default: 4)
41-
#[argh(option, default = "4")]
40+
/// image batch size max
41+
#[argh(option, default = "8")]
4242
batch_max: usize,
4343

44+
/// text batch size min
45+
#[argh(option, default = "1")]
46+
text_batch_min: usize,
47+
48+
/// text batch size
49+
#[argh(option, default = "4")]
50+
text_batch: usize,
51+
52+
/// text batch size max
53+
#[argh(option, default = "16")]
54+
text_batch_max: usize,
55+
4456
/// dtype
4557
#[argh(option, default = "String::from(\"q4f16\")")]
4658
dtype: String,
@@ -55,7 +67,6 @@ fn main() -> Result<()> {
5567
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
5668
.with_timer(tracing_subscriber::fmt::time::ChronoLocal::rfc_3339())
5769
.init();
58-
5970
let args: Args = argh::from_env();
6071

6172
// Parse prompts
@@ -71,11 +82,20 @@ fn main() -> Result<()> {
7182

7283
// Build model
7384
let config = Config::sam3_image_predictor()
74-
.with_batch_size_all_min_opt_max(args.batch_min, args.batch, args.batch_max)
75-
.with_device_all(args.device.parse()?)
7685
.with_dtype_all(args.dtype.parse()?)
7786
.with_class_confs(&[args.conf])
78-
.with_num_dry_run_all(1)
87+
.with_batch_size_all_min_opt_max(args.batch_min, args.batch, args.batch_max)
88+
.with_textual_encoder_batch_min_opt_max(
89+
args.text_batch_min,
90+
args.text_batch,
91+
args.text_batch_max,
92+
)
93+
// => If your GPU memory is insufficient, you can place some modules on CPU
94+
// .with_visual_encoder_device(args.device.parse()?)
95+
// .with_textual_encoder_device(args.device.parse()?)
96+
// .with_encoder_device(args.device.parse()?) // geometry-encoder
97+
// .with_decoder_device(args.device.parse()?)
98+
.with_device_all(args.device.parse()?)
7999
.commit()?;
80100
let mut model = SAM3::new(config)?;
81101

@@ -105,6 +125,11 @@ fn main() -> Result<()> {
105125
}
106126
}
107127

128+
// Cache info
129+
let (cached_count, mem_mb) = model.cache_stats();
130+
println!("Cache: {} texts, ~{}MB", cached_count, mem_mb);
131+
108132
usls::perf(false);
133+
109134
Ok(())
110135
}

src/core/config.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,46 @@ impl Config {
236236
self
237237
}
238238

239+
pub fn with_textual_encoder_batch_min_opt_max(
240+
mut self,
241+
min: usize,
242+
opt: usize,
243+
max: usize,
244+
) -> Self {
245+
self.textual_encoder = self.textual_encoder.with_ixx(0, 0, (min, opt, max).into());
246+
self
247+
}
248+
249+
pub fn with_visual_encoder_batch_min_opt_max(
250+
mut self,
251+
min: usize,
252+
opt: usize,
253+
max: usize,
254+
) -> Self {
255+
self.visual_encoder = self.visual_encoder.with_ixx(0, 0, (min, opt, max).into());
256+
self
257+
}
258+
259+
pub fn with_encoder_encoder_batch_min_opt_max(
260+
mut self,
261+
min: usize,
262+
opt: usize,
263+
max: usize,
264+
) -> Self {
265+
self.encoder = self.encoder.with_ixx(0, 0, (min, opt, max).into());
266+
self
267+
}
268+
269+
pub fn with_decoder_batch_min_opt_max(mut self, min: usize, opt: usize, max: usize) -> Self {
270+
self.decoder = self.decoder.with_ixx(0, 0, (min, opt, max).into());
271+
self
272+
}
273+
274+
pub fn with_model_batch_min_opt_max(mut self, min: usize, opt: usize, max: usize) -> Self {
275+
self.model = self.model.with_ixx(0, 0, (min, opt, max).into());
276+
self
277+
}
278+
239279
pub fn with_batch_size_all(mut self, batch_size: usize) -> Self {
240280
self.visual = self.visual.with_ixx(0, 0, batch_size.into());
241281
self.textual = self.textual.with_ixx(0, 0, batch_size.into());

src/models/sam3/README.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,101 @@ A powerful multimodal segmentation model supporting text, bounding box, and comb
55
## References
66

77
- Official: [facebookresearch/sam3](https://github.com/facebookresearch/sam3)
8+
- ONNX Models: [Download](https://github.com/jamjamjon/assets/releases/tag/sam3)
9+
10+
## ONNX Model Specifications
11+
12+
All models support dynamic batch processing.
13+
14+
### Vision Encoder
15+
```
16+
Inputs:
17+
images [batch, 3, 1008, 1008] FLOAT
18+
19+
Outputs:
20+
fpn_feat_0 [batch, 256, 288, 288] FLOAT
21+
fpn_feat_1 [batch, 256, 144, 144] FLOAT
22+
fpn_feat_2 [batch, 256, 72, 72] FLOAT
23+
fpn_feat_3 [batch, 256, 36, 36] FLOAT
24+
fpn_pos_0 [batch, 256, 288, 288] FLOAT
25+
fpn_pos_1 [batch, 256, 144, 144] FLOAT
26+
fpn_pos_2 [batch, 256, 72, 72] FLOAT
27+
fpn_pos_3 [batch, 256, 36, 36] FLOAT
28+
```
29+
30+
### Text Encoder
31+
```
32+
Inputs:
33+
input_ids [batch, 32] INT64
34+
attention_mask [batch, 32] INT64
35+
36+
Outputs:
37+
text_features [batch, 32, 256] FLOAT
38+
text_mask [batch, 32] BOOL
39+
```
40+
41+
### Geometry Encoder
42+
```
43+
Inputs:
44+
input_boxes [batch, num_boxes, 4] FLOAT
45+
input_boxes_labels [batch, num_boxes] INT64
46+
fpn_feat [batch, 256, 72, 72] FLOAT
47+
fpn_pos [batch, 256, 72, 72] FLOAT
48+
49+
Outputs:
50+
geometry_features [batch, num_boxes+1, 256] FLOAT
51+
geometry_mask [batch, num_boxes+1] BOOL
52+
```
53+
54+
### Decoder
55+
```
56+
Inputs:
57+
fpn_feat_0 [batch, 256, 288, 288] FLOAT
58+
fpn_feat_1 [batch, 256, 144, 144] FLOAT
59+
fpn_feat_2 [batch, 256, 72, 72] FLOAT
60+
fpn_pos_2 [batch, 256, 72, 72] FLOAT
61+
prompt_features [batch, prompt_len, 256] FLOAT
62+
prompt_mask [batch, prompt_len] BOOL
63+
64+
Outputs:
65+
pred_masks [batch, 200, 288, 288] FLOAT
66+
pred_boxes [batch, 200, 4] FLOAT
67+
pred_logits [batch, 200] FLOAT
68+
presence_logits [batch, 1] FLOAT
69+
```
70+
71+
## TensorRT Conversion
72+
73+
```bash
74+
# Vision Encoder
75+
trtexec --onnx=sam3_vision_encoder.onnx \
76+
--minShapes=images:1x3x1008x1008 \
77+
--optShapes=images:4x3x1008x1008 \
78+
--maxShapes=images:8x3x1008x1008 \
79+
--saveEngine=sam3_vision_encoder.engine
80+
81+
# Text Encoder
82+
trtexec --onnx=sam3_text_encoder.onnx \
83+
--minShapes=input_ids:1x32,attention_mask:1x32 \
84+
--optShapes=input_ids:4x32,attention_mask:4x32 \
85+
--maxShapes=input_ids:8x32,attention_mask:8x32 \
86+
--saveEngine=sam3_text_encoder.engine
87+
88+
# Geometry Encoder
89+
trtexec --onnx=sam3_geometry_encoder.onnx \
90+
--minShapes=input_boxes:1x1x4,input_boxes_labels:1x1,fpn_feat:1x256x72x72,fpn_pos:1x256x72x72 \
91+
--optShapes=input_boxes:1x5x4,input_boxes_labels:1x5,fpn_feat:1x256x72x72,fpn_pos:1x256x72x72 \
92+
--maxShapes=input_boxes:8x20x4,input_boxes_labels:8x20,fpn_feat:8x256x72x72,fpn_pos:8x256x72x72 \
93+
--saveEngine=sam3_geometry_encoder.engine
94+
95+
# Decoder
96+
trtexec --onnx=sam3_decoder.onnx \
97+
--minShapes=fpn_feat_0:1x256x288x288,fpn_feat_1:1x256x144x144,fpn_feat_2:1x256x72x72,fpn_pos_2:1x256x72x72,prompt_features:1x1x256,prompt_mask:1x1 \
98+
--optShapes=fpn_feat_0:1x256x288x288,fpn_feat_1:1x256x144x144,fpn_feat_2:1x256x72x72,fpn_pos_2:1x256x72x72,prompt_features:1x33x256,prompt_mask:1x33 \
99+
--maxShapes=fpn_feat_0:8x256x288x288,fpn_feat_1:8x256x144x144,fpn_feat_2:8x256x72x72,fpn_pos_2:8x256x72x72,prompt_features:8x60x256,prompt_mask:8x60 \
100+
--saveEngine=sam3_decoder.engine
101+
```
102+
8103

9104
## Example
10105

src/models/sam3/config.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ impl Config {
1111
pub fn sam3() -> Self {
1212
Self::default()
1313
.with_name("sam3")
14-
.with_batch_size_all_min_opt_max(1, 1, 4)
15-
.with_visual_encoder_ixx(0, 1, 3.into())
16-
.with_visual_encoder_ixx(0, 2, 1008.into())
17-
.with_visual_encoder_ixx(0, 3, 1008.into())
18-
.with_textual_encoder_ixx(0, 1, 32.into())
14+
.with_num_dry_run_all(1)
15+
.with_batch_size_all_min_opt_max(1, 1, 10)
16+
.with_visual_encoder_ixx(0, 1, 3.into()) // vision-encoder: channels
17+
.with_visual_encoder_ixx(0, 2, 1008.into()) // vision-encoder: height
18+
.with_visual_encoder_ixx(0, 3, 1008.into()) // vision-encoder: width
19+
.with_textual_encoder_ixx(0, 1, 32.into()) // text-encoder: text sequence length
20+
.with_encoder_ixx(0, 1, (1, 2, 8).into()) // geometry-encoder: input_boxes, num_boxes
21+
.with_encoder_ixx(1, 1, (1, 2, 8).into()) // geometry-encoder: input_boxes_labels, num_boxes
22+
.with_decoder_ixx(4, 1, (1, 34, 60).into()) // decoder: prompt_features prompt_len
23+
.with_decoder_ixx(5, 1, (1, 34, 60).into()) // decoder: prompt_mask prompt_len
1924
.with_resize_mode(crate::ResizeMode::FitExact)
2025
.with_resize_filter("Bilinear")
2126
.with_image_mean(&[0.5, 0.5, 0.5])

0 commit comments

Comments
 (0)