From e40048759ab4c7d51f4960d10e182bc2510014a0 Mon Sep 17 00:00:00 2001
From: sfmig <33267254+sfmig@users.noreply.github.com>
Date: Thu, 10 Sep 2026 17:38:53 +0100
Subject: [PATCH 01/19] Review proposal from claude
---
.../proposal-detect-and-track-mask.md | 544 ++++++++++++++++++
1 file changed, 544 insertions(+)
create mode 100644 claude-plans/proposal-detect-and-track-mask.md
diff --git a/claude-plans/proposal-detect-and-track-mask.md b/claude-plans/proposal-detect-and-track-mask.md
new file mode 100644
index 00000000..758772bf
--- /dev/null
+++ b/claude-plans/proposal-detect-and-track-mask.md
@@ -0,0 +1,544 @@
+# Proposal for a `detect-and-track-mask` entry point
+
+## Description
+
+This document proposes a **new CLI entry point, `detect-and-track-mask`** in the crabs backage.
+
+This entry point runs the existing
+`detect-and-track-video` pipeline unchanged, then prompts SAM2 with the **tracked** boxes and
+writes one ID-encoded mask per frame, where each mask carries its **track ID**.
+
+
+> [!NOTE]
+> Nomenclature clarifications
+> * **Prompt** — a hint telling SAM2 *which* object to segment. Here, one bounding box in
+> `[x1, y1, x2, y2]` pixel coordinates per tracked crab.
+> * **Label image** — a 2-D integer array where `0` is background and every other value identifies
+> one object. This is the array `skimage.measure.regionprops` takes.
+
+
+## References
+It is a scoped-down
+first slice of Phase 3 of
+[`this-repo-collects-tools-pure-kernighan.md`](this-repo-collects-tools-pure-kernighan.md).
+
+---
+
+## Key aspects of suggested implementation
+
+
+
+### 1. A subclass, so the diff is one new file
+
+* `Tracking.detect_and_track_video` already produces exactly what SAM2 needs — tracked boxes and
+IDs per frame.
+* It already re-loops over the video twice (for `--save_video` and
+`--save_frames`). Masking is a third such loop.
+
+```mermaid
+flowchart TD
+ subgraph existing["detect-and-track-video (unchanged)"]
+ A["Tracking.detect_and_track_video()"] --> B["core_detection_and_tracking()
loop 1: detect + SORT"]
+ B --> C["write_tracked_detections_to_csv
<video>_tracks.csv"]
+ B --> D["generate_tracked_video
loop 2 (optional)"]
+ B --> E["write_all_video_frames_as_images
loop 3 (optional)"]
+ end
+ subgraph new["✨ detect-and-track-mask"]
+ F["TrackingAndMasking(Tracking)"] -.->|inherits, calls| A
+ F --> G["✨ generate_masks()
loop 4: SAM2 per frame"]
+ G --> H["✨ <video>_masks.zarr"]
+ end
+ style F fill:#e0e7ff,stroke:#4338ca,color:#1e1b4b
+ style G fill:#e0e7ff,stroke:#4338ca,color:#1e1b4b
+ style H fill:#e0e7ff,stroke:#4338ca,color:#1e1b4b
+```
+
+* The **entire feature is one new module**, `crabs/tracker/track_and_mask_video.py`.
+
+* The only change
+to existing Python is:
+ - one added line, so `generate_masks`in `crabs/tracker/track_and_mask_video.py` can see the boxes:
+
+ ```diff
+ --- a/crabs/tracker/track_video.py
+ +++ b/crabs/tracker/track_video.py
+ @@ def detect_and_track_video(self) -> None:
+ # Run detection and tracking over all frames in video
+ tracked_bboxes_dict = self.core_detection_and_tracking()
+ + self.tracked_bboxes_dict = tracked_bboxes_dict
+ ```
+* `prep_outputs` in `generate_masks` needs no change:
+ - `generate_masks` can derive its output path from `self.tracking_output_dir` and `self.input_video_file_root`, in the same way as it does already.
+
+* The masks are
+the third optional artefact in the same directory as the video `--save_video` writes and the raw PNGs `--save_frames` writes.
+ ```
+ tracking_output_/
+ ├──