stormbreaker20/quirofano-dataset-clean
Quirofano Synthetic Surgical-Scrub Detection Dataset Synthetic, CCTV-style hospital corridor/OR imagery for a 2-class person detector: does a visible person wear the target mustard/orange surgical scrub set, or not. Every image is AI-generated (no real people, no real hospital footage) and every box is machine-annotated then human-curated (see Annotation pipeline below). Classes category_id (COCO, this file) class id (YOLO, 0-indexed) name description 1… See the full description on the dataset page: https://huggingface.co/datasets/stormbreaker20/quirofano-dataset-clean.
Quirofano Synthetic Surgical-Scrub Detection Dataset
Synthetic, CCTV-style hospital corridor/OR imagery for a 2-class person detector: does a visible person wear the target mustard/orange surgical scrub set, or not. Every image is AI-generated (no real people, no real hospital footage) and every box is machine-annotated then human-curated (see Annotation pipeline below).
Classes
Classification is by visible garment color only — never by role, profession, location, or authorization. See classes.yaml for the YOLO-training class map.
Dataset structure
annotations.json COCO-format detections for all images (see schema below)
classes.yaml YOLO nc/names map
dataset_policy.md scope and split policy this dataset follows
data.yaml Ultralytics data descriptor (path + train/val/test)
data/{train,val,test}-*.parquet HF parquet sidecar (rich schema, viewer-ready)
images/{train,val,test}/*.png 319 PNGs physically split for YOLO training
labels/{train,val,test}/*.txt YOLO-format .txt labels (cls + normalized cx/cy/w/h)
raw/generated/ 319 synthetic PNG images ← local-only
audit/ stats.txt + audit_grid.png ← local-only
scripts/ annotate.py, audit.py, curate.py ← local-onlyNote on splits: the splits in this repo are the materialized form of the logical splits stored inannotations.json(images[].splitfield).raw/stays flat on the dataset author's machine; this HF repo ships the YOLO layout directly so it can be trained with Ultralytics without any extra step.
Dataset Viewer
The HF Dataset Viewer reads the data/*.parquet sidecar with this rich schema:
The two classes are surgical_equipped_person (target mustard scrub set) and non_surgical_equipped_person (any other visible clothing).
Loading the dataset
from datasets import load_dataset
ds = load_dataset("stormbreaker20/quirofano-dataset-clean")
print(ds["train"][0])
# -> {"image": <PIL>, "objects": {"bbox": [...], "categories": [...]}}For Ultralytics training, use the YOLO folder layout directly:
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
model.train(data="quirofano-dataset-clean/data.yaml", epochs=100, imgsz=640)What ships in this HF repo
The metadata + the materialized YOLO splits ship to Hugging Face. The original raw/ PNGs and the pipeline scripts stay local.
annotations.json ← source of truth (train/val/test fields per image)
classes.yaml ← YOLO nc/names map
dataset_policy.md ← scope + split policy
data.yaml ← Ultralytics data descriptor
images/{train,val,test}/ ← YOLO image splits (derived from annotations.json)
labels/{train,val,test}/ ← YOLO label splits (derived from annotations.json)
README.md ← this file (the data card)The 319 synthetic PNGs in raw/generated/ (source), the QC artifacts in audit/, and the pipeline scripts in scripts/ live only on the dataset author's machine and are not redistributed through this repo.
Stats (as of this export)
- 319 images, 1129 annotations, 4 fully vacant (0 people)
- Class balance: 428
equipped(38%) / 701non_equipped(62%) - Splits (stratified by composition, no leakage): train 257 / val 30 / test 32
- 10 synthetic scenes (corridor, locker room, sterile supply, waiting area, night corridor, pre-op holding, scrub sink, elevator lobby, etc.), 13 people-composition tags (vacant / solo / mixed / crowd)
annotations.json schema (COCO + extensions)
Standard COCO fields (images, annotations, categories) plus:
images[].path— relative to the dataset root (portable; resolve asdataset_root / path)images[].scene_id,images[].composition— generation provenance, used only to stratify the train/val/test split (never treated as ground-truth counts — see Known limitation below)images[].split—train/val/testimages[].is_vacant— true iff 0 people detected in that imageannotations[].confidence— YOLO detection confidenceannotations[].equipped_color_ratio— HSV-classifier signal that produced the category (HSV band + morphological closing + median-saturation gate; classifier lives in the author's local pipeline, not in this repo)annotations[].manual_correction— present only on the ~55 boxes a human verified and corrected after the automated pass; the string explains what was wrong and why. Its absence means "automated pipeline output, not individually re-verified."
Splits
Splits are logical, not physical. There are no train/, val/, test/ directories — all 319 images live flat in raw/generated/, and which split each image belongs to is a field on its entry in annotations.json:
{
"images": [
{ "file_name": "scene01_solo_01.png", "split": "train", ... },
{ "file_name": "scene01_solo_07.png", "split": "val", ... },
{ "file_name": "scene02_mixed_03.png", "split": "test", ... }
]
}Query the split of any image directly from the JSON — no file copy needed:
import json
ann = json.loads(open("annotations.json").read())
train_files = {img["file_name"] for img in ann["images"] if img["split"] == "train"}Distribution (stratified by scene_id + composition, no leakage — the same scene never appears in two splits):
Why this layout
Keeping all images in one flat folder makes the dataset easy to ship, version, and load with HF datasets, pycocotools, or torchvision. The split is a query, not a file move.
Annotation pipeline
- Detection — YOLO person detector (Ultralytics family; exact weights are local-only and not redistributed). Person class only, NMS iou=0.45, boxes under 1% of frame area dropped (fragment filter).
- Color classification — HSV band on the cropped garment + morphological closing (bridges belt/shadow creases that can split one garment into two connected components) + a median-saturation gate (separates the target orange/mustard from same-hue-but-desaturated cream/beige clothing).
- Human/agent curation pass — every one of the 1129 boxes and all 319 full images were reviewed (not sampled). ~55 corrections applied: misclassified garment colors, a handful of near-duplicate boxes that survived NMS, and a few real people the area-fragment filter had dropped (added back after confirming at a lower confidence threshold, never by hand-drawn coordinates).
Known limitation
The filename's composition tag (e.g. solo_equipped_2) records what was requested from the image generator, not a verified ground-truth count — current text-to-image models frequently ignore exact headcount instructions (documented, systemic; see e.g. T2ICountBench). This dataset does not use the filename as ground truth anywhere — every category/box comes from the detector + color classifier + human review, independent of what the filename promises.
Scope
Dataset/annotation/QC only — no training, ROI, tracking, or alerting logic lives here (see dataset_policy.md). Intended downstream use: training a YOLO detector for the hac-vision project.
