use serde::{Deserialize, Deserializer, Serialize};
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct Dataset {
#[serde(default)]
pub info: Option<Info>,
#[serde(default)]
pub images: Vec<Image>,
#[serde(default)]
pub annotations: Vec<Annotation>,
#[serde(default)]
pub categories: Vec<Category>,
#[serde(default)]
pub licenses: Vec<License>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Info {
#[serde(default)]
pub year: Option<u32>,
#[serde(default)]
pub version: Option<String>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub contributor: Option<String>,
#[serde(default)]
pub url: Option<String>,
#[serde(default)]
pub date_created: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Image {
pub id: u64,
#[serde(default)]
pub file_name: String,
pub height: u32,
pub width: u32,
#[serde(default)]
pub license: Option<u64>,
#[serde(default)]
pub coco_url: Option<String>,
#[serde(default)]
pub flickr_url: Option<String>,
#[serde(default)]
pub date_captured: Option<String>,
#[serde(default)]
pub neg_category_ids: Vec<u64>,
#[serde(default)]
pub not_exhaustive_category_ids: Vec<u64>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Annotation {
#[serde(default)]
pub id: u64,
pub image_id: u64,
pub category_id: u64,
#[serde(default)]
pub bbox: Option<[f64; 4]>,
#[serde(default)]
pub area: Option<f64>,
#[serde(default)]
pub segmentation: Option<Segmentation>,
#[serde(default, deserialize_with = "deserialize_iscrowd")]
pub iscrowd: bool,
#[serde(default)]
pub keypoints: Option<Vec<f64>>,
#[serde(default)]
pub num_keypoints: Option<u32>,
#[serde(default)]
pub obb: Option<[f64; 5]>,
#[serde(default)]
pub score: Option<f64>,
#[serde(default)]
pub is_group_of: Option<bool>,
}
fn deserialize_iscrowd<'de, D>(deserializer: D) -> Result<bool, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum IsCrowd {
Bool(bool),
Int(u8),
}
match IsCrowd::deserialize(deserializer)? {
IsCrowd::Bool(b) => Ok(b),
IsCrowd::Int(i) => Ok(i != 0),
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Segmentation {
Polygon(Vec<Vec<f64>>),
CompressedRle { size: [u32; 2], counts: String },
UncompressedRle { size: [u32; 2], counts: Vec<u32> },
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Category {
pub id: u64,
pub name: String,
#[serde(default)]
pub supercategory: Option<String>,
#[serde(default)]
pub skeleton: Option<Vec<[u32; 2]>>,
#[serde(default)]
pub keypoints: Option<Vec<String>>,
#[serde(default)]
pub frequency: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct License {
#[serde(default)]
pub id: u64,
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub url: Option<String>,
}
#[derive(Debug, Clone)]
pub struct SummaryStats {
pub min: f64,
pub max: f64,
pub mean: f64,
pub median: f64,
}
#[derive(Debug, Clone)]
pub struct CategoryStats {
pub id: u64,
pub name: String,
pub ann_count: usize,
pub img_count: usize,
pub crowd_count: usize,
}
#[derive(Debug, Clone)]
pub struct DatasetStats {
pub image_count: usize,
pub annotation_count: usize,
pub category_count: usize,
pub crowd_count: usize,
pub per_category: Vec<CategoryStats>,
pub image_width: SummaryStats,
pub image_height: SummaryStats,
pub annotation_area: SummaryStats,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Rle {
pub h: u32,
pub w: u32,
pub counts: Vec<u32>,
}
impl Rle {
pub fn new(h: u32, w: u32, counts: Vec<u32>) -> Self {
let sum: u64 = counts.iter().map(|&c| c as u64).sum();
let expected = h as u64 * w as u64;
debug_assert_eq!(
sum, expected,
"RLE counts must sum to h*w ({h} * {w} = {expected}), got {sum}",
);
Self { h, w, counts }
}
}