feat: configurable track forward, track to end, skip-and-mark (REQ-189)
Track 5 Frames becomes Track Forward with a 1-100 count input, remembered in localStorage (default 5). A separate -> End action runs to the last frame behind a confirm and can be cancelled mid-flight. Frames that already hold a shape of the tracked class are skipped instead of re-annotated: hidden and dimmed shapes count as present. Skips are reported in the result banner and marked with a dot plus a class name on the filmstrip thumbnail. frames() now returns the class ids each frame holds, the same query row, no migration. Chaining and seed growth stay out: every frame is still seeded from the drawn box only.
This commit is contained in:
1 parent
f6b0335c93
commit
4f15335092
9 files changed
+226
-52
No files matched your search
+21
-11
@@ -205,7 +205,7 @@ SAM3: Ready | Off ← green when ready
|
||||
```
|
||||
|
||||
Icons are SVG (Heroicons/Lucide-style), never emoji. *(Some emoji survive inside page bodies —
|
||||
`🔄 Reset Auto`, `🏷️ Next Shape`, `📋 Copy Prev`, `🚀 Track 5`, `🤖`, `📦`, `⚡`, `🖼️`. These are
|
||||
`🔄 Reset Auto`, `🏷️ Next Shape`, `📋 Copy Prev`, `🚀 Track Forward`, `🤖`, `📦`, `⚡`, `🖼️`. These are
|
||||
legacy and **should** become SVG icons in a rebuild; that is the one place the current UI is
|
||||
off-spec.)*
|
||||
|
||||
@@ -897,7 +897,7 @@ worked". The jump happens once per load, and again after an auto-label job finis
|
||||
### 5.2 Data model in play
|
||||
|
||||
```
|
||||
frame { id, idx, filename, width, height, review_status, annotation_count }
|
||||
frame { id, idx, filename, width, height, review_status, annotation_count, class_ids }
|
||||
annotation { id, class_id, geometry, score, source: "auto"|"manual" }
|
||||
batch { …, review: { pending, approved, rejected }, annotation_count, status }
|
||||
```
|
||||
@@ -982,27 +982,37 @@ previous geometry** and shows the error. Same optimistic-with-rollback pattern f
|
||||
`POST /annotations/bulk-reclass` and `POST /annotations/bulk-delete`.
|
||||
|
||||
**Frame bar.** `←` · `n / N` + a status pill (`pending`/`approved`/`rejected`) · `→` ·
|
||||
**Next Shape [N]** · **Copy Prev [C]** · **Track 5 Frames [T]** · an "asking SAM3…" indicator ·
|
||||
**Next Shape [N]** · **Copy Prev [C]** · **Track Forward [T]** (+ N input, *→ End*) ·
|
||||
an "asking SAM3…" indicator ·
|
||||
**Reject [X]** · **Approve [A]**.
|
||||
|
||||
- *Next Shape* jumps to the next frame with annotations, wrapping to the first.
|
||||
- *Copy Prev* copies every annotation from frame `n-1` onto this frame (one POST per shape);
|
||||
disabled at index 0 or when the previous frame is empty.
|
||||
- *Track 5 Frames* takes the selected shape's bounding box and runs SAM3 assist on the next 5
|
||||
frames with it. Works for both geometry types: a bbox shape supplies its own box, a polygon
|
||||
is reduced to its bounding box. Nothing selected, an unusable shape, or the last frame
|
||||
- *Track Forward* takes the selected shape's bounding box and runs SAM3 assist on the next N
|
||||
frames with it, N from the number input beside the button (1–100, remembered, default 5).
|
||||
*→ End* runs to the last frame of the batch behind a confirm. Works for both geometry types:
|
||||
a bbox shape supplies its own box, a polygon is reduced to its bounding box. Nothing
|
||||
selected, an unusable shape, or the last frame
|
||||
says so in the error slot instead of silently doing nothing; a frame SAM3 refuses (nothing
|
||||
inside the box) does not stop the rest — the banner then **starts** with `Tracked N of M`
|
||||
(M = frames actually ahead, ≤ 5) followed by the per-frame failures. A second press while
|
||||
a run is in flight is ignored. Shapes are written `source=manual`, exactly as a hand-drawn
|
||||
one (REQ-189).
|
||||
(M = frames actually ahead) followed by `skipped K already had <class>` and the per-frame
|
||||
failures. Skipped frames are those that already hold a shape of the tracked class (hidden or
|
||||
dimmed counts); they get a dot on their filmstrip thumb and the thumb's tooltip says why. The
|
||||
"asking SAM3…" indicator becomes a **Cancel** button while a run is in flight (Cancel stops the
|
||||
remaining frames; the frame already in flight can still be saved by the server, and the banner
|
||||
says so). A second
|
||||
press while a run is in flight is ignored. Shapes are written `source=manual`, exactly as a
|
||||
hand-drawn one (REQ-189).
|
||||
|
||||
**Quick reclass bar** appears whenever a shape is selected: one button per class
|
||||
(`[n] name`, class-coloured) plus *Delete [Del]*.
|
||||
|
||||
**Filmstrip.** Every frame as a thumbnail (`GET /frames/{id}/image?w=120`, lazy-loaded), border
|
||||
coloured by review status, an annotation-count badge, `aria-current` on the active one, which
|
||||
is scrolled into view (`block: nearest, inline: center`) on every index change.
|
||||
is scrolled into view (`block: nearest, inline: center`) on every index change. A frame that
|
||||
Track Forward skipped carries a `--warn` dot top-left and a tooltip naming the class it already
|
||||
had; the marking clears on the next run (REQ-189).
|
||||
|
||||
### 5.6 The exemplar flow — the most intricate part of the app
|
||||
|
||||
@@ -1114,7 +1124,7 @@ Handlers are attached in the **capture** phase on `document`, and:
|
||||
| `U` | jump to next pending frame (`GET /batches/{id}/next-pending?after_idx=`) | same |
|
||||
| `N` | jump to next annotated frame | same |
|
||||
| `C` | copy annotations from previous frame | same |
|
||||
| `T` | track selected shape forward 5 frames | same |
|
||||
| `T` | track selected shape forward N frames (N = the count input) | same |
|
||||
| `1`–`9` | set active class; reclass the selected shape if any | reclass **all marked** shapes |
|
||||
| `Del` / `Backspace` | delete the selected shape | delete **all marked** shapes (confirmed) |
|
||||
| `H` | hide/show the selected shape(s); no-op with nothing selected | same |
|
||||
|
||||
Reference in new issue
Block a user