Expand description
Per-image evaluation orchestrator.
The bridge between the dataset layer (crate::CocoDataset /
crate::CocoDetections) and the IoU-type-agnostic spine
(crate::matching → crate::accumulate). Pycocotools fuses
these in evaluate() (cocoeval.py 174-216); we keep the layers
separate so the spine stays untouchable per ADR-0005.
The pass is generic over EvalKernel — a Similarity supertrait
that adds the dataset-bridging methods that turn a (image, category)
cell into kernel-typed annotations. Bbox and segm reuse the same
orchestrator with BboxIou and SegmIou respectively; future
kernels (OKS, Boundary IoU) plug in by adding one
impl EvalKernel for FooIou block — match_image, accumulate,
and summarize_* stay untouched.
§What this layer does
For each (image, category) cell:
- Gather GTs and DTs from the dataset indices.
- Pre-filter DTs to the top
max_dets_per_imageby score (the matching engine and accumulator both rely on this cap; smallermax_detsvalues are sliced downstream byaccumulate). - Build the kernel’s annotation slices via
EvalKernel::build_gt_anns/EvalKernel::build_dt_annsand compute the GT × DT IoU matrix once viaSimilarity::compute. - For each area range, build the per-call
_ignorevector (quirk D3) from the dataset’s base ignore (D1) plus the area filter (D6/D7), run thecrate::matchingengine, apply quirk B7 by flippingdt_ignorefor unmatched DTs whose area is outside the active range, and pack the result as acrate::accumulate::PerImageEvalat[k][a][i].
§Quirk dispositions handled here
- D3 (
aligned): per-call_ignorecomputed without mutating the dataset. - D6/D7 (
strict): area filter uses non-strict<=/>=on both bounds (mirrorscocoeval.py:251’sg['area'] < aRng[0] or g['area'] > aRng[1]exclusion). An annotation whose area equals a bucket boundary lands in both adjacent buckets. Inequality direction matches the eval-time filter in pycocotools, notgetAnnIds(areaRng=...). - B7 (
strict): unmatched DTs whose area is out of range getdt_ignore=trueso they do not contribute to the precision/recall curve in this area cell. - AA3 (
strict, ADR-0026): when the dataset carries LVIS federated metadata and the current(image, category)cell is innot_exhaustive_category_ids[image], every unmatched DT in the cell has itsdt_ignoreset totrue. Mirrors lvis-apieval.py:269-278’s OR into the area-bucketdt_ig_mask. The matching engine is unchanged: the flag piggybacks on the samedt_ignorefield B7 already drives. - AA4 (
strict, ADR-0026): on a federated dataset and withuse_cats=true, a cell(image I, category C)is evaluated only whenC ∈ pos[I] ∪ neg[I]. Cells with no GT (soC ∉ pos[I]) and noneglisting produce noeval_imgsentry — the existingOption<PerImageEval>distinction (Nonevs an empty cell) is the same one lvis-api’seval.py:336filter relies on. - L4 (
aligned):use_cats=falsecollapses every category onto a single virtualk=0bucket, withcategory_idcarried through matching as a no-op. - E2 / J4 (
strict): DTs never carry anis_crowdflag — thecrate::dataset::CocoDetectiontype lacks the field. Only GT crowdness drives the E1 asymmetry inside the kernel. - J3 (
strict): DT areas are read fromcrate::dataset::CocoDetection::area, which the dataset layer derives from the bbox at construction. - J2 (
strict): underParityMode::Strict, a DT lacking asegmentationfield underiouType="segm"has its bbox synthesized into a 4-point rectangle polygon[[x1,y1, x1,y2, x2,y2, x2,y1]]and rasterized — bit-for-bit the pathpycocotools/coco.py:341follows. UnderParityMode::Corrected(the default for net-new users) the synthesis is refused withEvalError::InvalidAnnotation: silent coercion of bbox results to rectangle masks is a footgun, and users who want strict parity opt in. - J6 (
corrected): per-entry dispatch — every detection is inspected independently for the segm/bbox kind. UnderParityMode::Correctedheterogeneous DT lists (some entries withsegmentation, some without) are rejected up-front rather than silently routed through the first-entry-decides dispatch pycocotools follows atcoco.py:330-363.
Structs§
- Archived
Area Range - An archived
AreaRange - Archived
Owned Evaluate Params - An archived
OwnedEvaluateParams - Area
Range - Closed
[lo, hi]area bucket — both bounds are inclusive per quirks D6/D7, so an annotation with area exactly equal to a bound lands in this bucket (and in the adjacent one when the boundary is shared). - Area
Range Resolver - The resolver for an archived
AreaRange - Boundary
IouCached - Kernel used by
evaluate_boundaryandevaluate_boundary_cached— same semantics asBoundaryIoubut threads a singleBoundaryComputeScratchacross everycomputecall (so the dataset-wide pass amortizes per-mask + per-cell allocations) and optionally consults aBoundaryGtCachefor cross-call GT band reuse. - Eval
Grid - Output of
evaluate_bbox/evaluate_segm/evaluate_boundary— the flat(K, A, I)grid ofPerImageEvalcells the accumulator consumes, plus the dimensions needed to constructcrate::accumulate::AccumulateParams. - Eval
Image Meta - Pycocotools-shaped per-cell bookkeeping that the matching engine
strips out when packing
PerImageEval. Surfaced separately so the accumulator stays narrow per ADR-0005, and FFI /COCOevaldrop-in consumers can reconstructevalImgsdicts without re-running eval. - Evaluate
Params - Inputs to
evaluate_bbox/evaluate_segm/evaluate_boundary/evaluate_with. IoU-agnostic — kernel-specific configuration (sigmas, prefilter thresholds, …) lives on theEvalKernelpassed alongside. - Owned
Evaluate Params - Owned counterpart to
EvaluateParams. - Owned
Evaluate Params Resolver - The resolver for an archived
OwnedEvaluateParams - Segm
IouCached - Kernel used by
evaluate_segmandevaluate_segm_cached— same semantics asSegmIoubut threads a singleSegmComputeScratchacross everycomputecall (so the dataset-wide pass amortizes per-cellVecallocations across the ~36 k anns of a val2017 pass) and optionally consults aSegmGtCachefor cross-call GT bbox+area reuse.
Enums§
- Archived
Kernel Kind - An archived
KernelKind - GtCache
Ref - Either a borrowed or
Arc-owned reference to a per-kernel GT cache. - Kernel
Kind - Discriminator for the four kernel families on the IoU axis (per ADR-0012’s iou-type taxonomy). Carried in distributed-eval partials (ADR-0031) so a head-rank reconstruction refuses to merge bbox and segm partials silently.
- Kernel
Kind Resolver - The resolver for an archived
KernelKind
Constants§
- AREA_
UNBOUNDED - Sentinel upper bound for “unbounded” area buckets, mirroring the
1e10pycocotools uses forall/large. - COLLAPSED_
CATEGORY_ SENTINEL - Sentinel
category_idemitted on every cell whenuse_cats=false. Mirrors pycocotools’p.catIds = [-1]collapse (quirk L4).
Traits§
- Eval
Kernel - Bridges a
CocoDataset/CocoDetectionscell to a kernel’s annotation type.
Functions§
- evaluate_
bbox - Run the per-image bbox evaluation pass. Thin wrapper over
evaluate_withwith theBboxIoukernel. - evaluate_
boundary - Run the per-image boundary-IoU evaluation pass (ADR-0010). Thin
wrapper over
evaluate_withwith theBoundaryIoukernel. - evaluate_
boundary_ cached - Cached variant of
evaluate_boundary: reuses GT bands across calls via a caller-ownedBoundaryGtCache. - evaluate_
keypoints - Run the per-image OKS (
iouType="keypoints") evaluation pass per ADR-0012. Thin wrapper overevaluate_withwith theOksSimilaritykernel. - evaluate_
segm - Run the per-image segmentation-mask evaluation pass. Thin wrapper
over
evaluate_withwith theSegmIoukernel. - evaluate_
segm_ cached - Cached variant of
evaluate_segm: reuses GT bbox + area across calls via a caller-ownedSegmGtCache. - evaluate_
with - Run the per-image evaluation pass with the given
EvalKernel.