Instructions to use camstack/camstack-trainer with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- ultralytics
How to use camstack/camstack-trainer with ultralytics:
from huggingface_hub import hf_hub_download from ultralytics import YOLO # pick the weights file from this repo's "Files and versions" tab weights = hf_hub_download("camstack/camstack-trainer", "<weights>.pt") model = YOLO(weights) source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True) - Notebooks
- Google Colab
- Kaggle
camstack-train 0.1.0: YOLOv9 root detector fine-tune (job.json in, result.json + bundle.tar out)
ebeed67 verified Download camstack_train/_vendor/camstack_eval/compare.py from camstack/camstack-trainer: direct link, hf CLI and curl.
- Browser
- Download file 4.03 kB
-
https://huggingface.co/camstack/camstack-trainer/resolve/main/camstack_train/_vendor/camstack_eval/compare.py
- Command line
-
hf download hf://camstack/camstack-trainer/camstack_train/_vendor/camstack_eval/compare.py
-
curl -L -o compare.py https://huggingface.co/camstack/camstack-trainer/resolve/main/camstack_train/_vendor/camstack_eval/compare.py
4.03 kB
| """Baseline vs candidate on one holdout. | |
| Both models are run on the same frames. The candidate's floors come from the | |
| D739 rule against the baseline's shipped floors (`floors.propose_floor`), and | |
| the candidate is reported AT those floors — "same false-alert rate, what more | |
| does it find". Per-camera recall deltas are what a promotion gate reads | |
| (analysis §6: no camera may lose more than 0.01 of person recall). | |
| """ | |
| from __future__ import annotations | |
| from typing import Callable, Iterable, Optional, Sequence | |
| from .classes import DETECTOR_CLASSES, to_macro | |
| from .dataset import EvalFrame | |
| from .floors import FloorPolicy, ScoredDetection, propose_floor | |
| from .metrics import ClassResult, Detection, FrameTruth, average_precision, evaluate_class, scored_detections | |
| Detector = Callable[[bytes], Sequence[Detection]] | |
| def select_holdout( | |
| frames: Iterable[EvalFrame], | |
| cameras: Optional[Sequence[int]] = None, | |
| since: Optional[int] = None, | |
| ) -> list[EvalFrame]: | |
| """Holdout by whole cameras and/or by capture time — never by random frame.""" | |
| wanted = set(cameras) if cameras else None | |
| out = [] | |
| for f in frames: | |
| if wanted is not None and f.truth.camera not in wanted: | |
| continue | |
| if since is not None and (f.captured_at is None or f.captured_at < since): | |
| continue | |
| out.append(f) | |
| return out | |
| def _run(frames: Sequence[EvalFrame], detector: Detector) -> list[tuple[FrameTruth, list[Detection]]]: | |
| return [(f.truth, to_macro(list(detector(f.read())))) for f in frames] | |
| def _summary(result: ClassResult, ap: Optional[float]) -> dict: | |
| return { | |
| "floor": result.floor, | |
| "tp": result.tp, | |
| "fp": result.fp, | |
| "fn": result.fn, | |
| "precision": result.precision, | |
| "recall": result.recall, | |
| "ap50": ap, | |
| "recallByCamera": {str(k): v for k, v in sorted(result.recall_by_camera.items())}, | |
| "recallByLight": dict(sorted(result.recall_by_light.items())), | |
| "fpByCamera": {str(k): v for k, v in sorted(result.fp_by_camera.items())}, | |
| "smallFound": result.small_found, | |
| "smallTotal": result.small_total, | |
| } | |
| def compare_models( | |
| frames: Sequence[EvalFrame], | |
| baseline: Detector, | |
| candidate: Detector, | |
| baseline_floors: dict[str, float], | |
| candidate_floors: Optional[dict[str, float]] = None, | |
| policy: FloorPolicy = FloorPolicy(), | |
| classes: Sequence[str] = DETECTOR_CLASSES, | |
| ) -> dict: | |
| base_runs = _run(frames, baseline) | |
| cand_runs = _run(frames, candidate) | |
| report: dict = {"frames": len(frames), "classes": {}} | |
| for cls in classes: | |
| base_floor = baseline_floors[cls] | |
| base_scored, positives = scored_detections(cls, base_runs) | |
| cand_scored, _ = scored_detections(cls, cand_runs) | |
| proposed = propose_floor( | |
| [ScoredDetection(d.score, d.true_positive) for d in base_scored], | |
| base_floor, | |
| [ScoredDetection(d.score, d.true_positive) for d in cand_scored], | |
| positives, | |
| policy, | |
| ) | |
| cand_floor = (candidate_floors or {}).get(cls, proposed.value) | |
| base = evaluate_class(cls, base_runs, base_floor) | |
| cand = evaluate_class(cls, cand_runs, cand_floor) | |
| deltas = {} | |
| for cam, recall in cand.recall_by_camera.items(): | |
| before = base.recall_by_camera.get(cam) | |
| if recall is not None and before is not None: | |
| deltas[str(cam)] = round(recall - before, 4) | |
| report["classes"][cls] = { | |
| "positives": positives, | |
| "baseline": _summary(base, average_precision(cls, base_runs)), | |
| "candidate": _summary(cand, average_precision(cls, cand_runs)), | |
| "proposedFloor": { | |
| "value": proposed.value, | |
| "reason": proposed.reason, | |
| "fpBudget": proposed.fp_budget, | |
| "fitted": proposed.fitted, | |
| }, | |
| "recallDeltaByCamera": dict(sorted(deltas.items())), | |
| } | |
| return report | |