1use std::collections::HashMap;
5use std::fmt::Display;
6
7use serde::{Deserialize, Serialize};
8
9pub fn deserialize_dshape<'de, D>(deserializer: D) -> Result<Vec<(DimName, usize)>, D::Error>
15where
16 D: serde::Deserializer<'de>,
17{
18 #[derive(Deserialize)]
19 #[serde(untagged)]
20 enum DShapeItem {
21 Tuple(DimName, usize),
22 Map(HashMap<DimName, usize>),
23 }
24
25 let items: Vec<DShapeItem> = Vec::deserialize(deserializer)?;
26 items
27 .into_iter()
28 .map(|item| match item {
29 DShapeItem::Tuple(name, size) => Ok((name, size)),
30 DShapeItem::Map(map) => {
31 if map.len() != 1 {
32 return Err(serde::de::Error::custom(
33 "dshape map entry must have exactly one key",
34 ));
35 }
36 let (name, size) = map.into_iter().next().unwrap();
37 Ok((name, size))
38 }
39 })
40 .collect()
41}
42
43#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]
44pub struct QuantTuple(pub f32, pub i32);
45impl From<QuantTuple> for (f32, i32) {
46 fn from(value: QuantTuple) -> Self {
47 (value.0, value.1)
48 }
49}
50
51impl From<(f32, i32)> for QuantTuple {
52 fn from(value: (f32, i32)) -> Self {
53 QuantTuple(value.0, value.1)
54 }
55}
56
57#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
58pub struct Segmentation {
59 #[serde(default)]
60 pub decoder: DecoderType,
61 #[serde(default)]
62 pub quantization: Option<QuantTuple>,
63 #[serde(default)]
64 pub shape: Vec<usize>,
65 #[serde(default, deserialize_with = "deserialize_dshape")]
66 pub dshape: Vec<(DimName, usize)>,
67}
68
69#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
70pub struct Protos {
71 #[serde(default)]
72 pub decoder: DecoderType,
73 #[serde(default)]
74 pub quantization: Option<QuantTuple>,
75 #[serde(default)]
76 pub shape: Vec<usize>,
77 #[serde(default, deserialize_with = "deserialize_dshape")]
78 pub dshape: Vec<(DimName, usize)>,
79}
80
81#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
82pub struct MaskCoefficients {
83 #[serde(default)]
84 pub decoder: DecoderType,
85 #[serde(default)]
86 pub quantization: Option<QuantTuple>,
87 #[serde(default)]
88 pub shape: Vec<usize>,
89 #[serde(default, deserialize_with = "deserialize_dshape")]
90 pub dshape: Vec<(DimName, usize)>,
91}
92
93#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
94pub struct Mask {
95 #[serde(default)]
96 pub decoder: DecoderType,
97 #[serde(default)]
98 pub quantization: Option<QuantTuple>,
99 #[serde(default)]
100 pub shape: Vec<usize>,
101 #[serde(default, deserialize_with = "deserialize_dshape")]
102 pub dshape: Vec<(DimName, usize)>,
103}
104
105#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
106pub struct Detection {
107 #[serde(default)]
108 pub anchors: Option<Vec<[f32; 2]>>,
109 #[serde(default)]
110 pub decoder: DecoderType,
111 #[serde(default)]
112 pub quantization: Option<QuantTuple>,
113 #[serde(default)]
114 pub shape: Vec<usize>,
115 #[serde(default, deserialize_with = "deserialize_dshape")]
116 pub dshape: Vec<(DimName, usize)>,
117 #[serde(default)]
124 pub normalized: Option<bool>,
125}
126
127#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
128pub struct Scores {
129 #[serde(default)]
130 pub decoder: DecoderType,
131 #[serde(default)]
132 pub quantization: Option<QuantTuple>,
133 #[serde(default)]
134 pub shape: Vec<usize>,
135 #[serde(default, deserialize_with = "deserialize_dshape")]
136 pub dshape: Vec<(DimName, usize)>,
137}
138
139#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
140pub struct Boxes {
141 #[serde(default)]
142 pub decoder: DecoderType,
143 #[serde(default)]
144 pub quantization: Option<QuantTuple>,
145 #[serde(default)]
146 pub shape: Vec<usize>,
147 #[serde(default, deserialize_with = "deserialize_dshape")]
148 pub dshape: Vec<(DimName, usize)>,
149 #[serde(default)]
156 pub normalized: Option<bool>,
157}
158
159#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
160pub struct Classes {
161 #[serde(default)]
162 pub decoder: DecoderType,
163 #[serde(default)]
164 pub quantization: Option<QuantTuple>,
165 #[serde(default)]
166 pub shape: Vec<usize>,
167 #[serde(default, deserialize_with = "deserialize_dshape")]
168 pub dshape: Vec<(DimName, usize)>,
169}
170
171#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy, Hash, Eq)]
172pub enum DimName {
173 #[serde(rename = "batch")]
174 Batch,
175 #[serde(rename = "height")]
176 Height,
177 #[serde(rename = "width")]
178 Width,
179 #[serde(rename = "num_classes")]
180 NumClasses,
181 #[serde(rename = "num_features")]
182 NumFeatures,
183 #[serde(rename = "num_boxes")]
184 NumBoxes,
185 #[serde(rename = "num_protos")]
186 NumProtos,
187 #[serde(rename = "num_anchors_x_features")]
188 NumAnchorsXFeatures,
189 #[serde(rename = "padding")]
190 Padding,
191 #[serde(rename = "box_coords")]
192 BoxCoords,
193 #[serde(other)]
200 Unknown,
201}
202
203impl Display for DimName {
204 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
214 match self {
215 DimName::Batch => write!(f, "batch"),
216 DimName::Height => write!(f, "height"),
217 DimName::Width => write!(f, "width"),
218 DimName::NumClasses => write!(f, "num_classes"),
219 DimName::NumFeatures => write!(f, "num_features"),
220 DimName::NumBoxes => write!(f, "num_boxes"),
221 DimName::NumProtos => write!(f, "num_protos"),
222 DimName::NumAnchorsXFeatures => write!(f, "num_anchors_x_features"),
223 DimName::Padding => write!(f, "padding"),
224 DimName::BoxCoords => write!(f, "box_coords"),
225 DimName::Unknown => write!(f, "unknown"),
226 }
227 }
228}
229
230#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy, Hash, Eq, Default)]
231pub enum DecoderType {
232 #[serde(rename = "modelpack")]
233 ModelPack,
234 #[default]
235 #[serde(rename = "ultralytics", alias = "yolov8")]
236 Ultralytics,
237}
238
239#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy, Hash, Eq)]
251#[serde(rename_all = "lowercase")]
252pub enum DecoderVersion {
253 #[serde(rename = "yolov5")]
255 Yolov5,
256 #[serde(rename = "yolov8")]
258 Yolov8,
259 #[serde(rename = "yolo11")]
261 Yolo11,
262 #[serde(rename = "yolo26")]
265 Yolo26,
266}
267
268impl DecoderVersion {
269 pub fn is_end_to_end(&self) -> bool {
272 matches!(self, DecoderVersion::Yolo26)
273 }
274}
275
276#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy, Hash, Eq, Default)]
286#[serde(rename_all = "snake_case")]
287pub enum Nms {
288 Auto,
294 #[default]
297 ClassAgnostic,
298 ClassAware,
300}
301
302#[derive(Debug, Clone, PartialEq)]
303pub enum ModelType {
304 ModelPackSegDet {
305 boxes: Boxes,
306 scores: Scores,
307 segmentation: Segmentation,
308 },
309 ModelPackSegDetSplit {
310 detection: Vec<Detection>,
311 segmentation: Segmentation,
312 },
313 ModelPackDet {
314 boxes: Boxes,
315 scores: Scores,
316 },
317 ModelPackDetSplit {
318 detection: Vec<Detection>,
319 },
320 ModelPackSeg {
321 segmentation: Segmentation,
322 },
323 YoloDet {
324 boxes: Detection,
325 },
326 YoloSegDet {
327 boxes: Detection,
328 protos: Protos,
329 },
330 YoloSplitDet {
331 boxes: Boxes,
332 scores: Scores,
333 },
334 YoloSplitSegDet {
335 boxes: Boxes,
336 scores: Scores,
337 mask_coeff: MaskCoefficients,
338 protos: Protos,
339 },
340 YoloSegDet2Way {
347 boxes: Detection,
348 mask_coeff: MaskCoefficients,
349 protos: Protos,
350 },
351 YoloEndToEndDet {
355 boxes: Detection,
356 },
357 YoloEndToEndSegDet {
361 boxes: Detection,
362 protos: Protos,
363 },
364 YoloSplitEndToEndDet {
368 boxes: Boxes,
369 scores: Scores,
370 classes: Classes,
371 },
372 YoloSplitEndToEndSegDet {
375 boxes: Boxes,
376 scores: Scores,
377 classes: Classes,
378 mask_coeff: MaskCoefficients,
379 protos: Protos,
380 },
381 PerScale,
387}