Sign in

    moonbit-visual-debug

    Visual algorithm debugging overlays and SVG/HTML report generation for MoonBit.

    visual-debug
    overlay
    computer-vision
    svg
    report
    Download zip
    Author
    Version
    0.2.2
    License
    Apache-2.0
    Last updated
    last month
    Downloads
    17

    #moonbit-visual-debug

    Typed visual-debugging reports for MoonBit computer-vision and image-analysis workflows.

    #Project Positioning

    moonbit-visual-debug turns structured algorithm outputs into inspectable visual evidence. It models boxes, masks, keypoints, trajectories, heatmaps, error regions, and detection matches, then renders a deterministic SVG, self-contained HTML report, or PNG snapshot.

    It is a library-first reporting layer, not a detector, segmenter, image decoder, or general SVG engine. The package is intended for CI artifacts, experiments, demos, and reviewable visual regression evidence.

    #Core Capabilities

    • Image-space geometry, intersection, and IoU primitives.
    • Typed overlays for bounding boxes, polygon masks, keypoints, trajectories, heatmaps, and error regions.
    • SVG and standalone HTML reports with layer metadata.
    • Pure MoonBit RGBA canvas and deterministic PNG encoding.
    • Detection comparison with true-positive, false-positive, false-negative, and label-mismatch output.
    • COCO datasets/results plus YOLO and Pascal VOC box adapters.
    • Baseline-versus-candidate document diffs, per-class metrics, and machine-readable manifests.

    #Quick Start

    moon add xlh123jjj/moonbit-visual-debug

    ///|
    test "build a visual inspection report" {
    let layer = Layer::new(id="detections").add(
    BBox(
    rect=Rect::new(x=12.0, y=10.0, width=48.0, height=36.0),
    label=Some(Label::new(text="part", score=0.91)),
    color=Some(Color::rgb(r=39, g=125, b=255)),
    ),
    )
    let doc = DebugDocument::new(
    title="inspection",
    image=ImageSpec::new(width=96, height=64),
    ).add_layer(layer)
    inspect(doc.overlay_count(), content="1")
    inspect(doc.to_svg().contains("<svg"), content="true")
    inspect(doc.to_html_report().contains("<table>"), content="true")
    }

    #CLI

    moon run --target wasm-gc cmd/main > report.html

    The command writes a self-contained HTML report to standard output. Open report.html in a browser, or attach it to a CI job as a review artifact.

    #Dataset Interoperability

    CocoDataset::from_json accepts a COCO object containing annotations, optional categories, and image metadata. It validates required IDs and [x, y, width, height] boxes, then resolves category names when producing Detection values. Scored prediction arrays are handled separately by CocoResults. Unknown category IDs remain usable through a stable category-<id> fallback label.

    ///|
    test "load COCO annotations" {
    let source =
    #|{"categories":[{"id":1,"name":"part"}],
    #|"annotations":[{"id":7,"image_id":1,"category_id":1,
    #|"bbox":[10,12,20,16]}]}
    match CocoDataset::from_json(source) {
    Ok(dataset) => inspect(dataset.to_detections()[0].label, content="part")
    Err(_) => fail("expected valid COCO data")
    }
    }

    #Architecture

    ComponentResponsibility
    geometry.mbt, color.mbtValue types and deterministic presentation primitives.
    overlay.mbt, transform.mbtOverlay document model, composition, transforms, and bounds.
    svg.mbt, report.mbt, raster.mbtSVG, HTML, canvas, and PNG output backends.
    analysis.mbt, validation.mbtDetection matching, error overlays, and input diagnostics.
    dataset.mbt, adapter.mbtCOCO, YOLO, and Pascal VOC interchange.
    diff.mbt, metrics.mbt, manifest.mbtCI-ready diffing, evaluation summaries, and stable exports.

    #Benchmarks

    visual_bench.mbt uses MoonBit's built-in benchmark runner. On the recorded Windows 11 native-release run, rendering 256 labelled overlays averaged 1.04 ms for SVG and 9.09 ms for PNG. See docs/benchmarks.md for the command, environment, and complete measurements.

    Run the same benchmark locally with:

    moon bench visual_bench.mbt --target native --release --deny-warn

    #Testing

    moon fmt --check moon check --target wasm-gc --deny-warn moon test --target wasm-gc --deny-warn moon check --target native --deny-warn moon test --target native --deny-warn moon info --target wasm-gc git diff --exit-code

    The suite covers rendering, polygon rasterization, PNG block boundaries, COCO/YOLO/VOC interchange, malformed annotations, matching thresholds, report diffs, metrics, manifests, and diagnostic behavior.

    #CI

    GitHub Actions installs the current stable MoonBit toolchain, checks formatting and generated interfaces, runs warning-denied wasm-gc tests on Ubuntu, macOS, and Windows, and validates native builds, coverage, and benchmark compilation on Ubuntu.

    #Scope

    The package deliberately has no runtime dependency on an image library, model framework, dataset host, or browser. Polygon detail is retained in SVG and HTML, and the PNG backend uses deterministic even-odd polygon filling for masks.

    #License

    Apache-2.0. See LICENSE.

    AdapterError

    pub(all) enum AdapterError {
    InvalidImageSize(message~ : String)
    InvalidYolo(field~ : String, message~ : String)
    InvalidYoloText(message~ : String)
    MissingClassMapping(class_id~ : Int)
    InvalidVoc(path~ : String, message~ : String)
    } derive(ToJson,
    Debug
    )

    Errors returned by the text-only YOLO and Pascal VOC annotation adapters.

    Affine2D

    pub(all) struct Affine2D {
    sx : Double
    sy : Double
    tx : Double
    ty : Double
    } derive(ToJson,
    Debug
    )

    Affine2D::apply_point

    fn Affine2D::apply_point(self : Affine2D, point : Point) -> Point

    Affine2D::apply_rect

    fn Affine2D::apply_rect(self : Affine2D, rect : Rect) -> Rect

    Affine2D::identity

    fn Affine2D::identity() -> Affine2D

    Affine2D::scale

    fn Affine2D::scale(sx~ : Double, sy~ : Double) -> Affine2D

    Affine2D::then

    fn Affine2D::then(self : Affine2D, next : Affine2D) -> Affine2D

    Affine2D::translate

    fn Affine2D::translate(tx~ : Double, ty~ : Double) -> Affine2D

    AggregateMetrics

    pub(all) struct AggregateMetrics {
    true_positive : Int
    false_positive : Int
    false_negative : Int
    label_mismatch : Int
    precision : Double
    recall : Double
    f1 : Double
    } derive(ToJson,
    Debug
    )

    Counts and derived scores for a single class or aggregate. Aggregate label_mismatch counts each mismatched match record once.

    Canvas

    pub(all) struct Canvas {
    width : Int
    height : Int
    pixels : Array[Byte]
    } derive(
    Debug
    )

    Canvas::draw_point

    fn Canvas::draw_point(self : Canvas, point : Point, color : Color, radius? : Int) -> Unit

    Canvas::fill_polygon

    fn Canvas::fill_polygon(self : Canvas, polygon : Array[Point], color : Color) -> Unit

    Fills one polygon using even-odd containment evaluated at pixel centers.

    An edge contributes only when a pixel center's horizontal ray crosses its half-open vertical range [min_y, max_y), so shared vertices and horizontal edges have deterministic coverage. Polygons with fewer than three points are ignored and all writes are clipped to the canvas.

    Canvas::fill_polygons

    fn Canvas::fill_polygons(self : Canvas, polygons : Array[Array[Point]], color : Color) -> Unit

    Fills polygons with the even-odd rule, allowing nested polygons to form holes.

    Pixels are evaluated at (x + 0.5, y + 0.5). The same half-open edge rule as fill_polygon makes boundary coverage reproducible regardless of edge order.

    Canvas::fill_rect

    fn Canvas::fill_rect(self : Canvas, rect : Rect, color : Color) -> Unit

    Canvas::from_image_spec

    fn Canvas::from_image_spec(image : ImageSpec, background? : Color) -> Canvas

    Canvas::new

    fn Canvas::new(width~ : Int, height~ : Int, background? : Color) -> Canvas

    Canvas::set_pixel

    fn Canvas::set_pixel(self : Canvas, x : Int, y : Int, color : Color) -> Unit

    Canvas::stroke_rect

    fn Canvas::stroke_rect(self : Canvas, rect : Rect, color : Color, width? : Int) -> Unit

    Canvas::to_png

    fn Canvas::to_png(self : Canvas) -> Bytes

    ClassMetrics

    pub(all) struct ClassMetrics {
    label : String
    true_positive : Int
    false_positive : Int
    false_negative : Int
    label_mismatch : Int
    support : Int
    precision : Double
    recall : Double
    f1 : Double
    } derive(ToJson,
    Debug
    )

    Per-label metrics. support is the number of expected detections. A label mismatch contributes a false negative to its expected class and a false positive to its actual class, so it is visible in both affected class rows.

    CocoAnnotation

    pub(all) struct CocoAnnotation {
    id : Int
    image_id : Int
    category_id : Int
    bbox : Rect
    area : Double?
    iscrowd : Int?
    } derive(ToJson,
    Debug
    )

    One ground-truth bounding-box annotation in a COCO dataset. Scores belong in CocoResult records, not annotations.

    CocoAnnotation::new

    fn CocoAnnotation::new(id~ : Int, image_id~ : Int, category_id~ : Int, bbox~ : Rect, area? : Double, iscrowd? : Int) -> CocoAnnotation

    Creates a COCO annotation. Omitted area is derived during export; supplied iscrowd must be 0 or 1.

    CocoCategory

    pub(all) struct CocoCategory {
    id : Int
    name : String
    } derive(ToJson,
    Debug
    )

    CocoCategory::new

    fn CocoCategory::new(id~ : Int, name~ : String) -> CocoCategory

    CocoDataset

    pub(all) struct CocoDataset {
    images : Array[CocoImage]
    categories : Array[CocoCategory]
    annotations : Array[CocoAnnotation]
    } derive(ToJson,
    Debug
    )

    A COCO ground-truth object with image, category, and annotation arrays. Legacy annotation-only objects without images remain accepted.

    CocoDataset::from_json

    fn CocoDataset::from_json(source : String) -> Result[CocoDataset, CocoError]

    Parses a COCO ground-truth object. annotations is required; images and categories may be omitted only for legacy annotation-only input.

    CocoDataset::new

    fn CocoDataset::new(annotations~ : Array[CocoAnnotation], categories? : Array[CocoCategory], images? : Array[CocoImage]) -> CocoDataset

    Creates a COCO dataset without validation for convenient literals. Prefer CocoDataset::try_new when constructed input can be invalid.

    CocoDataset::to_coco_json

    fn CocoDataset::to_coco_json(self : CocoDataset) -> Result[String, CocoError]

    Serializes this ground-truth dataset as a standard COCO object.

    CocoDataset::to_detections

    fn CocoDataset::to_detections(self : CocoDataset) -> Array[Detection]

    Converts ground-truth annotations into visual-debug detections.

    CocoDataset::try_new

    fn CocoDataset::try_new(annotations~ : Array[CocoAnnotation], categories? : Array[CocoCategory], images? : Array[CocoImage]) -> Result[CocoDataset, CocoError]

    Creates and validates a COCO dataset, returning a field-specific error.

    CocoDataset::validate

    fn CocoDataset::validate(self : CocoDataset) -> Result[Unit, CocoError]

    Validates COCO IDs, image dimensions, finite boxes, areas, crowd flags, and referential image IDs in linear time.

    CocoError

    pub(all) enum CocoError {
    InvalidJson(message~ : String)
    InvalidField(path~ : String, message~ : String)
    } derive(ToJson,
    Debug
    )

    CocoImage

    pub(all) struct CocoImage {
    id : Int
    width : Int
    height : Int
    file_name : String?
    } derive(ToJson,
    Debug
    )

    Metadata for one image in a COCO dataset. file_name is optional because COCO image assets can be addressed outside the annotation file.

    CocoImage::new

    fn CocoImage::new(id~ : Int, width~ : Int, height~ : Int, file_name? : String) -> CocoImage

    Creates a COCO image record. Use CocoDataset::try_new to validate it.

    CocoResult

    pub(all) struct CocoResult {
    image_id : Int
    category_id : Int
    bbox : Rect
    score : Double
    } derive(ToJson,
    Debug
    )

    One scored COCO detection result. Standard COCO result JSON is a root array of these records rather than a dataset annotations array.

    CocoResult::new

    fn CocoResult::new(image_id~ : Int, category_id~ : Int, bbox~ : Rect, score~ : Double) -> CocoResult

    Creates a scored COCO result. Use CocoResults::try_new to validate it.

    CocoResults

    pub(all) struct CocoResults {
    results : Array[CocoResult]
    } derive(ToJson,
    Debug
    )

    A root-array COCO prediction/result payload.

    CocoResults::from_json

    fn CocoResults::from_json(source : String) -> Result[CocoResults, CocoError]

    Parses a standard root-array COCO result payload. Each object must contain image_id, category_id, bbox, and a finite score.

    CocoResults::new

    fn CocoResults::new(results~ : Array[CocoResult]) -> CocoResults

    Creates COCO results without validation for convenient literals. Prefer CocoResults::try_new when constructed input can be invalid.

    CocoResults::to_coco_json

    fn CocoResults::to_coco_json(self : CocoResults) -> Result[String, CocoError]

    Serializes these predictions as the standard root-array COCO result format.

    CocoResults::try_new

    fn CocoResults::try_new(results~ : Array[CocoResult]) -> Result[CocoResults, CocoError]

    Creates and validates a COCO result payload, including finite scores.

    CocoResults::validate

    fn CocoResults::validate(self : CocoResults) -> Result[Unit, CocoError]

    Validates every result ID, bounding box, and score in linear time.

    Color

    pub(all) struct Color {
    r : Int
    g : Int
    b : Int
    a : Double
    } derive(ToJson,
    Debug
    )

    Color::rgb

    fn Color::rgb(r~ : Int, g~ : Int, b~ : Int) -> Color

    Color::rgba

    fn Color::rgba(r~ : Int, g~ : Int, b~ : Int, a~ : Double) -> Color

    Color::to_css

    fn Color::to_css(self : Color) -> String

    Color::to_hex

    fn Color::to_hex(self : Color) -> String

    Color::with_alpha

    fn Color::with_alpha(self : Color, alpha : Double) -> Color

    ConfusionCell

    pub(all) struct ConfusionCell {
    expected_label : String?
    actual_label : String?
    count : Int
    } derive(ToJson,
    Debug
    )

    One non-zero, typed cell of a detection confusion matrix. None denotes an unmatched expected or actual detection.

    ConfusionMatrix

    pub(all) struct ConfusionMatrix {
    labels : Array[String]
    cells : Array[ConfusionCell]
    } derive(ToJson,
    Debug
    )

    A stable, sparse confusion matrix ordered by expected label then actual label.

    DebugDocument

    pub(all) struct DebugDocument {
    title : String
    image : ImageSpec
    image_href : String?
    layers : Array[Layer]
    } derive(ToJson,
    Debug
    )

    DebugDocument::add_layer

    fn DebugDocument::add_layer(self : DebugDocument, layer : Layer) -> DebugDocument

    DebugDocument::content_bounds

    fn DebugDocument::content_bounds(self : DebugDocument) -> Rect?

    DebugDocument::is_valid

    fn DebugDocument::is_valid(self : DebugDocument) -> Bool

    DebugDocument::manifest

    Builds a report manifest without changing the document, its layers, or their overlay arrays. Layer entries preserve the document insertion order.

    DebugDocument::new

    fn DebugDocument::new(title~ : String, image~ : ImageSpec, image_href? : String) -> DebugDocument

    DebugDocument::overlay_count

    fn DebugDocument::overlay_count(self : DebugDocument) -> Int

    DebugDocument::resize

    fn DebugDocument::resize(self : DebugDocument, width~ : Int, height~ : Int) -> DebugDocument

    DebugDocument::to_canvas

    fn DebugDocument::to_canvas(self : DebugDocument, background? : Color) -> Canvas

    DebugDocument::to_html_report

    fn DebugDocument::to_html_report(self : DebugDocument) -> String

    DebugDocument::to_html_report_with

    fn DebugDocument::to_html_report_with(self : DebugDocument, options : ReportOptions) -> String

    DebugDocument::to_png

    fn DebugDocument::to_png(self : DebugDocument) -> Bytes

    DebugDocument::to_svg

    fn DebugDocument::to_svg(self : DebugDocument) -> String

    DebugDocument::to_svg_with

    fn DebugDocument::to_svg_with(self : DebugDocument, options : SvgOptions) -> String

    DebugDocument::validate

    fn DebugDocument::validate(self : DebugDocument) -> Array[Diagnostic]

    DebugDocument::visible_layers

    fn DebugDocument::visible_layers(self : DebugDocument) -> Array[Layer]

    Detection

    pub(all) struct Detection {
    id : String
    rect : Rect
    label : String
    score : Double
    } derive(ToJson,
    Debug
    )

    Detection::new

    fn Detection::new(id~ : String, rect~ : Rect, label~ : String, score? : Double) -> Detection

    DetectionMetrics

    pub(all) struct DetectionMetrics {
    iou_threshold : Double
    score_threshold : Double
    matches : MatchSummary
    classes : Array[ClassMetrics]
    confusion : ConfusionMatrix
    micro : AggregateMetrics
    macro_average : AggregateMetrics
    } derive(ToJson,
    Debug
    )

    A deterministic metrics report for one IoU and score threshold pair. Classes are the lexical union of expected and score-filtered actual labels. Macro scores average those class rows; precision, recall, and F1 use 0.0 whenever their denominator is zero.

    DetectionMetrics::to_csv

    fn DetectionMetrics::to_csv(self : DetectionMetrics) -> String

    Renders stable LF-delimited CSV class metrics text for CI logs and artifacts.

    DetectionMetrics::to_html_table

    fn DetectionMetrics::to_html_table(self : DetectionMetrics) -> String

    Renders a compact escaped HTML table suitable for CI artifacts.

    Diagnostic

    pub(all) struct Diagnostic {
    level : DiagnosticLevel
    path : String
    message : String
    } derive(ToJson,
    Debug
    )

    Diagnostic::new

    fn Diagnostic::new(level~ : DiagnosticLevel, path~ : String, message~ : String) -> Diagnostic

    DiagnosticLevel

    pub(all) enum DiagnosticLevel {
    Info
    Warning
    Error
    } derive(ToJson,
    Debug
    )

    DiagnosticSeverityCounts

    pub(all) struct DiagnosticSeverityCounts {
    info : Int
    warning : Int
    error : Int
    } derive(ToJson,
    Debug
    )

    Counts diagnostics produced by document validation.

    DocumentDiff

    pub(all) struct DocumentDiff {
    baseline_title : String
    candidate_title : String
    baseline_image : ImageSpec
    candidate_image : ImageSpec
    baseline_image_href : String?
    candidate_image_href : String?
    title_changed : Bool
    image_size_changed : Bool
    image_href_changed : Bool
    overlay_count_delta : Int
    layer_changes : Array[LayerChange]
    } derive(ToJson,
    Debug
    )

    Summarizes changes between two visual debugging documents.

    DocumentDiff::to_html

    fn DocumentDiff::to_html(self : DocumentDiff) -> String

    Renders a deterministic, self-contained HTML summary of this diff.

    DocumentManifest

    pub(all) struct DocumentManifest {
    title : String
    image_width : Int
    image_height : Int
    layer_count : Int
    visible_layer_count : Int
    total_overlay_count : Int
    visible_overlay_count : Int
    overlays : OverlayKindCounts
    visible_overlays : OverlayKindCounts
    content_bounds : Rect?
    diagnostics : DiagnosticSeverityCounts
    is_valid : Bool
    layers : Array[LayerManifest]
    } derive(ToJson,
    Debug
    )

    A machine-readable, non-mutating summary of a DebugDocument.

    DocumentManifest::to_json_text

    fn DocumentManifest::to_json_text(self : DocumentManifest) -> String

    Serializes this manifest using the core Json encoder with a stable field order. String values are encoded by Json::string, so user input is escaped.

    DocumentManifest::to_markdown

    fn DocumentManifest::to_markdown(self : DocumentManifest) -> String

    Renders a compact CI summary. User-controlled titles and layer IDs are escaped before insertion into Markdown.

    HeatCell

    pub(all) struct HeatCell {
    rect : Rect
    value : Double
    } derive(ToJson,
    Debug
    )

    HeatCell::new

    fn HeatCell::new(rect~ : Rect, value~ : Double) -> HeatCell

    ImageSpec

    pub(all) struct ImageSpec {
    width : Int
    height : Int
    } derive(Eq, ToJson,
    Debug
    )

    ImageSpec::area

    fn ImageSpec::area(self : ImageSpec) -> Int

    ImageSpec::new

    fn ImageSpec::new(width~ : Int, height~ : Int) -> ImageSpec

    ImageSpec::valid

    fn ImageSpec::valid(self : ImageSpec) -> Bool

    Keypoint

    pub(all) struct Keypoint {
    point : Point
    name : String
    visible : Bool
    } derive(ToJson,
    Debug
    )

    Keypoint::new

    fn Keypoint::new(point~ : Point, name~ : String, visible? : Bool) -> Keypoint

    Label

    pub(all) struct Label {
    text : String
    score : Double?
    } derive(ToJson,
    Debug
    )

    Label::new

    fn Label::new(text~ : String, score? : Double) -> Label

    Layer

    pub(all) struct Layer {
    id : String
    visible : Bool
    opacity : Double
    overlays : Array[Overlay]
    } derive(ToJson,
    Debug
    )

    Layer::add

    fn Layer::add(self : Layer, overlay : Overlay) -> Layer

    Layer::bounds

    fn Layer::bounds(self : Layer) -> Rect?

    Layer::hidden

    fn Layer::hidden(self : Layer) -> Layer

    Layer::new

    fn Layer::new(id~ : String, overlays? : Array[Overlay]) -> Layer

    Layer::transform

    fn Layer::transform(self : Layer, affine : Affine2D) -> Layer

    Layer::with_opacity

    fn Layer::with_opacity(self : Layer, opacity : Double) -> Layer

    LayerChange

    pub(all) struct LayerChange {
    id : String
    kind : LayerChangeKind
    baseline_index : Int?
    candidate_index : Int?
    visibility_changed : Bool
    opacity_changed : Bool
    overlay_delta : Int
    } derive(ToJson,
    Debug
    )

    Describes one added, removed, or changed layer.

    LayerChangeKind

    pub(all) enum LayerChangeKind {
    Added
    Removed
    Changed
    } derive(ToJson,
    Debug
    )

    Classifies a layer difference.

    LayerManifest

    pub(all) struct LayerManifest {
    id : String
    visible : Bool
    opacity : Double
    overlay_count : Int
    overlays : OverlayKindCounts
    } derive(ToJson,
    Debug
    )

    A stable summary of a source layer in a document manifest.

    MarkerShape

    pub(all) enum MarkerShape {
    Circle
    Square
    Diamond
    Cross
    } derive(ToJson,
    Debug
    )

    MatchKind

    pub(all) enum MatchKind {
    TruePositive
    FalsePositive
    FalseNegative
    LabelMismatch
    } derive(ToJson,
    Debug
    )

    MatchRecord

    pub(all) struct MatchRecord {
    kind : MatchKind
    expected : Detection?
    actual : Detection?
    iou : Double
    } derive(ToJson,
    Debug
    )

    MatchRecord::is_error

    fn MatchRecord::is_error(self : MatchRecord) -> Bool

    MatchSummary

    pub(all) struct MatchSummary {
    records : Array[MatchRecord]
    true_positive : Int
    false_positive : Int
    false_negative : Int
    label_mismatch : Int
    } derive(ToJson,
    Debug
    )

    MatchSummary::error_count

    fn MatchSummary::error_count(self : MatchSummary) -> Int

    MatchSummary::precision

    fn MatchSummary::precision(self : MatchSummary) -> Double

    MatchSummary::recall

    fn MatchSummary::recall(self : MatchSummary) -> Double

    MatchSummary::to_error_layer

    fn MatchSummary::to_error_layer(self : MatchSummary, id? : String) -> Layer

    MetricsError

    pub(all) enum MetricsError {
    InvalidIouThreshold(value~ : Double)
    InvalidScoreThreshold(value~ : Double)
    InvalidDetectionScore(id~ : String, score~ : Double)
    EmptyThresholdSweep
    } derive(ToJson,
    Debug
    )

    Input validation failures for detection metrics.

    Overlay

    pub(all) enum Overlay {
    BBox(rect~ : Rect, label~ : Label?, color~ : Color?)
    Mask(polygons~ : Array[Array[Point]], label~ : Label?, color~ : Color?)
    Keypoints(points~ : Array[Keypoint], color~ : Color?)
    Trajectory(path~ : Trajectory, color~ : Color?)
    Heatmap(cells~ : Array[HeatCell], low~ : Color?, high~ : Color?)
    ErrorRegion(rect~ : Rect, expected~ : String, actual~ : String, severity~ : Double)
    } derive(ToJson,
    Debug
    )

    Overlay::bounds

    fn Overlay::bounds(self : Overlay) -> Rect?

    Overlay::transform

    fn Overlay::transform(self : Overlay, affine : Affine2D) -> Overlay

    OverlayKindCounts

    pub(all) struct OverlayKindCounts {
    bbox : Int
    mask : Int
    keypoints : Int
    trajectory : Int
    heatmap : Int
    error_region : Int
    } derive(ToJson,
    Debug
    )

    Counts overlays by their concrete rendering kind.

    Point

    pub(all) struct Point {
    x : Double
    y : Double
    } derive(ToJson,
    Debug
    )

    Point::new

    fn Point::new(x~ : Double, y~ : Double) -> Point

    Point::scale

    fn Point::scale(self : Point, sx~ : Double, sy~ : Double) -> Point

    Point::translate

    fn Point::translate(self : Point, dx~ : Double, dy~ : Double) -> Point

    Rect

    pub(all) struct Rect {
    x : Double
    y : Double
    width : Double
    height : Double
    } derive(ToJson,
    Debug
    )

    Rect::area

    fn Rect::area(self : Rect) -> Double

    Rect::bottom

    fn Rect::bottom(self : Rect) -> Double

    Rect::intersection

    fn Rect::intersection(self : Rect, other : Rect) -> Rect?

    Rect::intersects

    fn Rect::intersects(self : Rect, other : Rect) -> Bool

    Rect::iou

    fn Rect::iou(self : Rect, other : Rect) -> Double

    Rect::new

    fn Rect::new(x~ : Double, y~ : Double, width~ : Double, height~ : Double) -> Rect

    Rect::right

    fn Rect::right(self : Rect) -> Double

    Rect::scale

    fn Rect::scale(self : Rect, sx~ : Double, sy~ : Double) -> Rect

    Rect::translate

    fn Rect::translate(self : Rect, dx~ : Double, dy~ : Double) -> Rect

    ReportOptions

    pub(all) struct ReportOptions {
    svg : SvgOptions
    include_metadata : Bool
    theme : String
    } derive(ToJson,
    Debug
    )

    ReportOptions::default

    fn ReportOptions::default() -> ReportOptions

    Size

    pub(all) struct Size {
    width : Double
    height : Double
    } derive(ToJson,
    Debug
    )

    Size::new

    fn Size::new(width~ : Double, height~ : Double) -> Size

    SvgOptions

    pub(all) struct SvgOptions {
    show_labels : Bool
    show_grid : Bool
    background : Color
    } derive(ToJson,
    Debug
    )

    SvgOptions::default

    fn SvgOptions::default() -> SvgOptions

    Trajectory

    pub(all) struct Trajectory {
    id : String
    points : Array[Point]
    } derive(ToJson,
    Debug
    )

    Trajectory::new

    fn Trajectory::new(id~ : String, points~ : Array[Point]) -> Trajectory

    VocAnnotation

    pub(all) struct VocAnnotation {
    filename : String?
    size : ImageSpec
    objects : Array[VocObject]
    } derive(ToJson,
    Debug
    )

    A lightweight Pascal VOC annotation with image dimensions and objects.

    VocAnnotation::from_xml

    fn VocAnnotation::from_xml(source : String) -> Result[VocAnnotation, AdapterError]

    Parses VOC XML containing an optional XML declaration, standard metadata, ordered <size> dimensions, and ordered <object><name><bndbox> entries. Standard metadata is ignored; required geometric fields remain strict.

    VocAnnotation::new

    fn VocAnnotation::new(filename? : String, size~ : ImageSpec, objects~ : Array[VocObject]) -> VocAnnotation

    Creates an unvalidated VOC annotation for convenient literals.

    VocAnnotation::to_xml

    fn VocAnnotation::to_xml(self : VocAnnotation) -> Result[String, AdapterError]

    Exports canonical, escaped Pascal VOC XML. Rectangles are converted from zero-based half-open coordinates to VOC's one-based inclusive convention.

    VocAnnotation::try_new

    fn VocAnnotation::try_new(filename? : String, size~ : ImageSpec, objects~ : Array[VocObject]) -> Result[VocAnnotation, AdapterError]

    Validates a VOC annotation without reading files or touching the runtime.

    VocObject

    pub(all) struct VocObject {
    name : String
    bbox : Rect
    } derive(ToJson,
    Debug
    )

    One object in a Pascal VOC annotation. bbox is pixel-space and uses the library's zero-based, half-open Rect convention.

    VocObject::new

    fn VocObject::new(name~ : String, bbox~ : Rect) -> VocObject

    Creates an unvalidated VOC object. VocAnnotation::try_new and XML import validate names and boxes before returning a fallible result.

    YoloBox

    pub(all) struct YoloBox {
    class_id : Int
    center_x : Double
    center_y : Double
    width : Double
    height : Double
    confidence : Double?
    } derive(ToJson,
    Debug
    )

    A YOLO bounding box whose centre and dimensions are normalized to [0, 1]. confidence is optional because training labels normally omit it.

    YoloBox::from_line

    fn YoloBox::from_line(line : String, image~ : ImageSpec, classes~ : Array[String]) -> Result[YoloBox, AdapterError]

    Parses one deterministic YOLO label line (five fields, or six with score). The caller's class mapping is checked so unknown numeric IDs are rejected.

    YoloBox::from_rect

    fn YoloBox::from_rect(class_id~ : Int, rect~ : Rect, image~ : ImageSpec, confidence? : Double) -> Result[YoloBox, AdapterError]

    Converts a contained pixel-space rectangle into a normalized YOLO record.

    YoloBox::to_line

    fn YoloBox::to_line(self : YoloBox, classes : Array[String]) -> Result[String, AdapterError]

    Serializes one record with single ASCII-space separators. The mapping is validated even though standard YOLO syntax stores the numeric ID.

    YoloBox::to_rect

    fn YoloBox::to_rect(self : YoloBox, image : ImageSpec) -> Result[Rect, AdapterError]

    Converts this normalized box to the library's pixel-space Rect.

    YoloBox::try_new

    fn YoloBox::try_new(class_id~ : Int, center_x~ : Double, center_y~ : Double, width~ : Double, height~ : Double, confidence? : Double) -> Result[YoloBox, AdapterError]

    Creates a validated normalized YOLO record.

    compare_detections

    fn compare_detections(expected : Array[Detection], actual : Array[Detection], iou_threshold? : Double) -> MatchSummary

    compare_documents

    fn compare_documents(baseline : DebugDocument, candidate : DebugDocument) -> DocumentDiff

    Compares documents without mutating either input.

    Unique non-empty layer IDs match by ID. Duplicate and empty IDs match by their occurrence order among layers with the same ID.

    evaluate_detections

    fn evaluate_detections(expected : Array[Detection], actual : Array[Detection], iou_threshold? : Double, score_threshold? : Double) -> Result[DetectionMetrics, MetricsError]

    Evaluates detections after filtering actual detections whose score is below score_threshold. All thresholds and detection scores must be finite values in the inclusive range [0, 1].

    palette

    fn palette(index : Int) -> Color

    sweep_iou_thresholds

    fn sweep_iou_thresholds(expected : Array[Detection], actual : Array[Detection], thresholds : Array[Double], score_threshold? : Double) -> Result[Array[DetectionMetrics], MetricsError]

    Runs the same score-filtered evaluation at every caller-supplied IoU threshold. Results are sorted from the loosest to strictest threshold.