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_/ + ├──