outline/config.rs
1#[cfg(any(feature = "backend-ort", feature = "backend-rten"))]
2use std::path::{Path, PathBuf};
3
4#[cfg(any(feature = "backend-ort", feature = "backend-rten"))]
5use image::imageops::FilterType;
6
7/// Environment variable name for specifying the model path.
8pub const ENV_MODEL_PATH: &str = "OUTLINE_MODEL_PATH";
9
10/// Default model path used when no explicit path is provided.
11///
12/// This is the fallback when neither `--model` nor `OUTLINE_MODEL_PATH` is set.
13/// By default it points to `model.onnx` in the current working directory.
14pub const DEFAULT_MODEL_PATH: &str = "model.onnx";
15
16/// Inference backend used to execute the model.
17#[cfg(any(feature = "backend-ort", feature = "backend-rten"))]
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
19#[non_exhaustive]
20pub enum InferenceBackend {
21 /// Use ONNX Runtime through the `ort` crate.
22 #[cfg(feature = "backend-ort")]
23 #[default]
24 Ort,
25 /// Use the pure Rust RTen backend.
26 #[cfg(feature = "backend-rten")]
27 #[cfg_attr(not(feature = "backend-ort"), default)]
28 Rten,
29}
30
31/// Height and width used to override the model-declared input size.
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct ModelInputSize {
34 height: usize,
35 width: usize,
36}
37
38impl ModelInputSize {
39 /// Creates a height/width override for model input tensors.
40 ///
41 /// # Panics
42 ///
43 /// Panics if either dimension is zero.
44 pub fn new(height: usize, width: usize) -> Self {
45 assert!(height > 0 && width > 0, "model input size must be non-zero");
46 Self { height, width }
47 }
48
49 /// Input height in pixels.
50 pub fn height(&self) -> usize {
51 self.height
52 }
53
54 /// Input width in pixels.
55 pub fn width(&self) -> usize {
56 self.width
57 }
58}
59
60/// Configuration for ONNX model inference and image preprocessing.
61///
62/// Controls the model path, image resize filters for input/output, and threading behavior.
63/// Use builder methods like [`with_input_resize_filter`](InferenceSettings::with_input_resize_filter)
64/// to customize settings.
65///
66/// This struct is non-exhaustive; use [`new`](InferenceSettings::new) to construct it.
67#[cfg(any(feature = "backend-ort", feature = "backend-rten"))]
68#[derive(Debug, Clone)]
69#[non_exhaustive]
70pub struct InferenceSettings {
71 /// Path to the ONNX model file.
72 model_path: PathBuf,
73 /// Backend used to execute the model.
74 backend: InferenceBackend,
75 /// Filter to use when resizing the input image for the model.
76 input_resize_filter: FilterType,
77 /// Filter to use when resizing the output matte to the original image size.
78 output_resize_filter: FilterType,
79 /// Override for the image size used as model input.
80 ///
81 /// When set, callers are responsible for choosing a size the model supports.
82 model_input_size: Option<ModelInputSize>,
83 /// Number of intra-op threads for the inference (ORT backend).
84 intra_threads: Option<usize>,
85}
86
87#[cfg(any(feature = "backend-ort", feature = "backend-rten"))]
88impl InferenceSettings {
89 /// Create new inference settings with default values.
90 pub fn new(model_path: impl Into<PathBuf>) -> Self {
91 Self {
92 model_path: model_path.into(),
93 backend: InferenceBackend::default(),
94 input_resize_filter: FilterType::Triangle,
95 output_resize_filter: FilterType::Lanczos3,
96 model_input_size: None,
97 intra_threads: None,
98 }
99 }
100
101 /// Path to the ONNX model file.
102 pub fn model_path(&self) -> &Path {
103 &self.model_path
104 }
105
106 /// Backend used to execute the model.
107 pub fn backend(&self) -> InferenceBackend {
108 self.backend
109 }
110
111 /// Filter to use when resizing the input image for the model.
112 pub fn input_resize_filter(&self) -> FilterType {
113 self.input_resize_filter
114 }
115
116 /// Filter to use when resizing the output matte to the original image size.
117 pub fn output_resize_filter(&self) -> FilterType {
118 self.output_resize_filter
119 }
120
121 /// Override for the image size used as model input.
122 ///
123 /// When set, callers are responsible for choosing a size the model supports.
124 pub fn model_input_size(&self) -> Option<ModelInputSize> {
125 self.model_input_size
126 }
127
128 /// Number of intra-op threads for the inference (ORT backend).
129 pub fn intra_threads(&self) -> Option<usize> {
130 self.intra_threads
131 }
132
133 /// Set the inference backend.
134 pub fn with_backend(mut self, backend: InferenceBackend) -> Self {
135 self.backend = backend;
136 self
137 }
138
139 /// Override the image size used as model input.
140 ///
141 /// This bypasses the size inferred from the model; callers are responsible for choosing a
142 /// size the model supports.
143 ///
144 /// # Panics
145 ///
146 /// Panics if either dimension is zero.
147 pub fn with_model_input_size(mut self, height: usize, width: usize) -> Self {
148 self.model_input_size = Some(ModelInputSize::new(height, width));
149 self
150 }
151
152 /// Set the model resize filter.
153 pub fn with_input_resize_filter(mut self, filter: FilterType) -> Self {
154 self.input_resize_filter = filter;
155 self
156 }
157
158 /// Set the matte resize filter.
159 pub fn with_output_resize_filter(mut self, filter: FilterType) -> Self {
160 self.output_resize_filter = filter;
161 self
162 }
163
164 /// Set the number of intra-op threads for the inference (ORT backend).
165 pub fn with_intra_threads(mut self, intra_threads: Option<usize>) -> Self {
166 self.intra_threads = intra_threads;
167 self
168 }
169}
170
171/// How erosion treats pixels outside the image bounds.
172#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
173pub enum ErosionBorderMode {
174 /// Treat pixels outside the image as background, allowing edge-touching foreground to shrink.
175 #[default]
176 OutsideIsBackground,
177 /// Treat pixels outside the image as unknown, so erosion only uses visible in-image background.
178 OutsideIsUnknown,
179}
180
181/// Default parameters used by no-argument mask processing methods.
182///
183/// This does not define which operations run. Use [`MaskPipeline`](crate::MaskPipeline) or the
184/// chained methods on [`MatteHandle`](crate::MatteHandle) and [`MaskHandle`](crate::MaskHandle)
185/// to choose an explicit operation order.
186///
187/// This struct is non-exhaustive; start with [`Default`] and then adjust fields as needed.
188#[derive(Debug, Clone, PartialEq)]
189#[non_exhaustive]
190pub struct MaskProcessingDefaults {
191 /// Standard deviation (sigma) for Gaussian blur.
192 pub blur_sigma: f32,
193 /// Threshold value (0–255) used for binary conversion and hole-filling.
194 pub mask_threshold: u8,
195 /// Radius in pixels for the dilation operation.
196 pub dilation_radius: f32,
197 /// Radius in pixels for the erosion operation.
198 pub erosion_radius: f32,
199 /// How erosion treats pixels outside the image bounds.
200 pub erosion_border_mode: ErosionBorderMode,
201}
202
203impl Default for MaskProcessingDefaults {
204 fn default() -> Self {
205 Self {
206 blur_sigma: 6.0,
207 mask_threshold: 120,
208 dilation_radius: 5.0,
209 erosion_radius: 5.0,
210 erosion_border_mode: ErosionBorderMode::default(),
211 }
212 }
213}