Chris Leo commited on
scorevision: push artifact
Browse files- training/DATASET.md +133 -0
training/DATASET.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Detect-crime β Dataset Sources & Pipeline
|
| 2 |
+
|
| 3 |
+
The king's training set is small and synthetic β that's why per-class recalls collapse on
|
| 4 |
+
balaclava (3.4%), glove (6.4%), and spray paint (16.1%). The single biggest score lever is
|
| 5 |
+
**more, real, in-domain data**, especially for the four catastrophic classes.
|
| 6 |
+
|
| 7 |
+
## Target classes (target order β must match `class_names.txt`)
|
| 8 |
+
|
| 9 |
+
| id | name | king recall | priority |
|
| 10 |
+
|---:|---|---:|---|
|
| 11 |
+
| 0 | balaclava | 0.034 | **critical** |
|
| 12 |
+
| 1 | bat | 0.143 | high |
|
| 13 |
+
| 2 | glove | 0.064 | **critical** |
|
| 14 |
+
| 3 | graffiti | 0.321 | medium |
|
| 15 |
+
| 4 | hoodie | 0.274 | medium (carries the IoU mean alone) |
|
| 16 |
+
| 5 | spray paint | 0.161 | high |
|
| 17 |
+
|
| 18 |
+
## Sources
|
| 19 |
+
|
| 20 |
+
### Tier 1 β in-domain (gold)
|
| 21 |
+
|
| 22 |
+
**`manak0/Detect-crime` `latestAnnotatedChallenge` API.** Same pattern as petrol-station: the
|
| 23 |
+
console at `console.scorevision.io/api/v2/elements/manak0%2FDetect-crime?lookback_days=30`
|
| 24 |
+
returns one `latestAnnotatedChallenge` record at a time. The record rotates as the runner
|
| 25 |
+
emits fresh challenges, so polling at ~120s for several hours / days accumulates distinct
|
| 26 |
+
in-domain frames *with the king's predictions attached*. Use those predictions as silver
|
| 27 |
+
labels (king is 0.576, so they're noisy but in-domain).
|
| 28 |
+
|
| 29 |
+
Use `poll_manako.py` to collect; use `build_dataset.py --manako` to integrate.
|
| 30 |
+
|
| 31 |
+
### Tier 2 β public detection datasets (silver / gold mix)
|
| 32 |
+
|
| 33 |
+
| class | dataset | notes |
|
| 34 |
+
|---|---|---|
|
| 35 |
+
| **balaclava** | Roboflow Universe `balaclava-detection` (multiple variants, ~1kβ5k labeled imgs) | search "balaclava" on universe.roboflow.com; download YOLO format |
|
| 36 |
+
| balaclava | MAFA β masked-face dataset (35k labeled faces, occluded) | ~3k images contain ski-mask / balaclava-style coverage; relabel as "balaclava" only when the mouth+nose+ears are all occluded |
|
| 37 |
+
| **bat** | COCO 2017, class 35 "baseball bat" (~3.3k train + ~150 val instances) | already labeled YOLO-compatible after `pycocotools` re-export; map cls 35 -> our cls 1 |
|
| 38 |
+
| bat | Open Images V7, class `Baseball bat` | larger, but noisier labels |
|
| 39 |
+
| **glove** | Roboflow Universe `gloves-detection` / `ppe-detection` | ~5kβ10k labeled; merges leather, latex, work gloves |
|
| 40 |
+
| glove | COCO 2017 has no "glove" class; ImageNet n02883344 "ski glove" / n03775546 "boxing glove" β classification only, but useful for crops |
|
| 41 |
+
| **graffiti** | Roboflow Universe `graffiti-detection` | several variants 500β3k imgs |
|
| 42 |
+
| graffiti | STORM-IRMA Graffiti Dataset (Bardienus et al., academic release) | annotated graffiti tags + region bboxes |
|
| 43 |
+
| **hoodie** | DeepFashion2 (item id `short_sleeve_top + long_sleeve_outwear`) | very large; relabel "hooded" subset only |
|
| 44 |
+
| hoodie | Roboflow Universe `clothing-detection` | hooded sweatshirt subset |
|
| 45 |
+
| **spray paint** | Roboflow Universe `spray-paint-can`/`graffiti-tools` | small, 200β800 imgs each |
|
| 46 |
+
| spray paint | ImageNet n04270147 "spray can" | classification only β useful as copy-paste source crops |
|
| 47 |
+
|
| 48 |
+
Roboflow Universe links rotate; the build script uses the public Roboflow REST API
|
| 49 |
+
(`https://universe.roboflow.com/...`) and falls back to anonymous downloads for permissive-
|
| 50 |
+
licensed datasets. **Always check each dataset's license before use** β if a dataset is
|
| 51 |
+
non-redistributable, paste it into `--extra-dir` from a local copy instead.
|
| 52 |
+
|
| 53 |
+
### Tier 3 β synthetic & augmentation
|
| 54 |
+
|
| 55 |
+
- **Copy-paste augmentation** (built into ultralytics: `copy_paste=0.30`). Disproportionately
|
| 56 |
+
helps rare classes by pasting their crops into other training images.
|
| 57 |
+
- **Mosaic + mixup** (also built-in): standard for YOLOv11.
|
| 58 |
+
- **Photometric augmentation**: HSV jitter, brightness scaling. CCTV crime footage is
|
| 59 |
+
high-variance lighting (flashbang, IR night vision, daylight) β push `hsv_v` to 0.5.
|
| 60 |
+
|
| 61 |
+
## Pipeline
|
| 62 |
+
|
| 63 |
+
```
|
| 64 |
+
sources β KingLabeler (silver) βββ
|
| 65 |
+
ββ manako_pool/ (poll_manako.py) king's preds attached β
|
| 66 |
+
ββ roboflow/ (download.py per-class) β
|
| 67 |
+
ββ coco_bat/ (subset extractor) ββ build_dataset.py
|
| 68 |
+
ββ openimages/ (`oidv6` CLI, optional) β β YOLO data.yaml
|
| 69 |
+
ββ extra/ (manual / verified frames) β
|
| 70 |
+
β
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
## Stage A vs Stage B
|
| 74 |
+
|
| 75 |
+
- **Stage A β silver pretrain**: train on the **assembled silver corpus** (Roboflow + COCO
|
| 76 |
+
+ king-labeled manako + ImageNet copy-paste source). Targets: `200 epochs` at `imgsz=1280`,
|
| 77 |
+
YOLOv11s. Use heavy augmentation. Save EMA. Expect val mAP@50 around 0.30β0.45 β well
|
| 78 |
+
above king's 0.14, but synthetic-eval-flattering.
|
| 79 |
+
- **Stage B β clean fine-tune**: hand-verify (or LLM-verify with Qwen2-VL) ~300 manako frames
|
| 80 |
+
drawn from the latest 7-day window. This is the small-but-clean set that aligns most
|
| 81 |
+
closely with the live evaluator. Train `50 epochs` at `imgsz=1280` on Stage A weights with
|
| 82 |
+
reduced augmentation. Expect val mAP@50 to recede slightly (cleaner GT, harder eval) but
|
| 83 |
+
live-element score to *rise*, because we've shifted the distribution toward what's actually
|
| 84 |
+
scored on subnet.
|
| 85 |
+
|
| 86 |
+
## Class balancing
|
| 87 |
+
|
| 88 |
+
The king's set is heavily skewed toward hoodie (~half of GT boxes). Without rebalancing, our
|
| 89 |
+
model would inherit that. Two interventions:
|
| 90 |
+
|
| 91 |
+
1. **Weighted sampling** in dataloader (`sampler=` weighted by 1/sqrt(class_count)).
|
| 92 |
+
2. **Copy-paste augmentation** sourced from a curated rare-class crop bank
|
| 93 |
+
(`crime_miner/training/_rare_crops/{balaclava, glove, spray_paint}/`). The build script
|
| 94 |
+
produces this bank as a byproduct.
|
| 95 |
+
|
| 96 |
+
## What the build script writes
|
| 97 |
+
|
| 98 |
+
```
|
| 99 |
+
data/
|
| 100 |
+
βββ data.yaml # ultralytics-style; names + train/val paths
|
| 101 |
+
βββ images/
|
| 102 |
+
β βββ train/{src}_{sha}.jpg # one per source image
|
| 103 |
+
β βββ val/...
|
| 104 |
+
βββ labels/
|
| 105 |
+
βββ train/{src}_{sha}.txt # YOLO format: cls cx cy w h (normalized)
|
| 106 |
+
βββ val/...
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
Manako frames are forced into `val` so the held-out set lives in the real evaluation domain.
|
| 110 |
+
|
| 111 |
+
## Hard-class strategy: balaclava
|
| 112 |
+
|
| 113 |
+
Balaclava is the lowest-recall class. Two failure modes from the king's perspective:
|
| 114 |
+
|
| 115 |
+
1. **Box too small at 640 input** (king's stretch resize destroys 30 px head crops).
|
| 116 |
+
*Solved* by 1280 letterboxed input + multi-scale TTA. No retraining required.
|
| 117 |
+
2. **Few training examples**. Mitigations:
|
| 118 |
+
- Pull MAFA (~3k masked-face images) and select the ~30% subset where the mask covers the
|
| 119 |
+
entire head (i.e., balaclava, not surgical mask).
|
| 120 |
+
- Roboflow `balaclava-detection-v3` has ~1.5k labeled.
|
| 121 |
+
- Synthesize via copy-paste of balaclava crops onto random `hoodie` GT boxes (we have many
|
| 122 |
+
hoodie images; pasting a balaclava crop on top is plausible-looking).
|
| 123 |
+
|
| 124 |
+
Target: **5,000 balaclava-positive training images** going into Stage A.
|
| 125 |
+
|
| 126 |
+
## Notes on label vocabulary
|
| 127 |
+
|
| 128 |
+
Both the manak0 baseline and our model emit class names matching `class_names.txt` exactly.
|
| 129 |
+
**Do not rename or reorder** β class id is what's compared on-subnet.
|
| 130 |
+
|
| 131 |
+
If the live element uses SAM3 pseudo-GT (not real GT), SAM3 will be prompted with these
|
| 132 |
+
exact strings as text labels (`scorevision/vlm_pipeline/sam3/detect_objects.py:36`). So the
|
| 133 |
+
class names in `class_names.txt` *are* the SAM3 prompts.
|