use crate::params::{IouType, Params};
use super::EvalMode;
use super::mode::FreqGroup;
#[derive(Debug, Clone)]
pub struct MetricDef {
pub name: &'static str,
pub ap: bool,
pub iou_thr: Option<f64>,
pub area_lbl: &'static str,
pub max_det: usize,
pub freq_group: Option<FreqGroup>,
}
impl MetricDef {
const fn ap(name: &'static str, area_lbl: &'static str, max_det: usize) -> Self {
MetricDef {
name,
ap: true,
iou_thr: None,
area_lbl,
max_det,
freq_group: None,
}
}
const fn ar(name: &'static str, area_lbl: &'static str, max_det: usize) -> Self {
MetricDef {
name,
ap: false,
iou_thr: None,
area_lbl,
max_det,
freq_group: None,
}
}
const fn at(mut self, iou_thr: f64) -> Self {
self.iou_thr = Some(iou_thr);
self
}
const fn freq(mut self, group: FreqGroup) -> Self {
self.freq_group = Some(group);
self
}
}
pub(super) fn metrics_bbox_segm(max_d: usize, max_d_s: usize, max_d_m: usize) -> Vec<MetricDef> {
vec![
MetricDef::ap("AP", "all", max_d),
MetricDef::ap("AP50", "all", max_d).at(0.5),
MetricDef::ap("AP75", "all", max_d).at(0.75),
MetricDef::ap("APs", "small", max_d),
MetricDef::ap("APm", "medium", max_d),
MetricDef::ap("APl", "large", max_d),
MetricDef::ar("AR1", "all", max_d_s),
MetricDef::ar("AR10", "all", max_d_m),
MetricDef::ar("AR100", "all", max_d),
MetricDef::ar("ARs", "small", max_d),
MetricDef::ar("ARm", "medium", max_d),
MetricDef::ar("ARl", "large", max_d),
]
}
pub(super) fn metrics_kp(max_d: usize) -> Vec<MetricDef> {
vec![
MetricDef::ap("AP", "all", max_d),
MetricDef::ap("AP50", "all", max_d).at(0.5),
MetricDef::ap("AP75", "all", max_d).at(0.75),
MetricDef::ap("APm", "medium", max_d),
MetricDef::ap("APl", "large", max_d),
MetricDef::ar("AR", "all", max_d),
MetricDef::ar("AR50", "all", max_d).at(0.5),
MetricDef::ar("AR75", "all", max_d).at(0.75),
MetricDef::ar("ARm", "medium", max_d),
MetricDef::ar("ARl", "large", max_d),
]
}
pub(super) fn metrics_lvis(max_d: usize) -> Vec<MetricDef> {
vec![
MetricDef::ap("AP", "all", max_d),
MetricDef::ap("AP50", "all", max_d).at(0.5),
MetricDef::ap("AP75", "all", max_d).at(0.75),
MetricDef::ap("APs", "small", max_d),
MetricDef::ap("APm", "medium", max_d),
MetricDef::ap("APl", "large", max_d),
MetricDef::ap("APr", "all", max_d).freq(FreqGroup::Rare),
MetricDef::ap("APc", "all", max_d).freq(FreqGroup::Common),
MetricDef::ap("APf", "all", max_d).freq(FreqGroup::Frequent),
MetricDef::ar("AR@300", "all", max_d),
MetricDef::ar("ARs@300", "small", max_d),
MetricDef::ar("ARm@300", "medium", max_d),
MetricDef::ar("ARl@300", "large", max_d),
]
}
fn resolve_max_dets(params: &Params) -> (usize, usize, usize) {
let default = params.max_det();
let (small, med) = if params.max_dets.len() >= 3 {
let mut sorted = params.max_dets.clone();
sorted.sort_unstable();
(sorted[0], sorted[1])
} else {
(default, default)
};
(default, small, med)
}
fn metrics_oid(max_d: usize) -> Vec<MetricDef> {
vec![MetricDef::ap("AP", "all", max_d).at(0.5)]
}
pub(super) fn build_metric_defs(params: &Params, eval_mode: EvalMode) -> Vec<MetricDef> {
let (max_d, max_d_s, max_d_m) = resolve_max_dets(params);
match eval_mode {
EvalMode::Lvis => metrics_lvis(max_d),
EvalMode::OpenImages => metrics_oid(max_d),
EvalMode::Coco => {
if params.iou_type == IouType::Keypoints {
metrics_kp(max_d)
} else {
metrics_bbox_segm(max_d, max_d_s, max_d_m)
}
}
}
}