Add polygon drawing and click-to-fill tools
Introduce two new drawing modes alongside the existing brush: - Polygon mode: left-click to place vertices connected by lines; right-click removes the last vertex; clicking near the first vertex (red dot) when >= 3 points are placed closes the shape (bold cyan outline). Multiple shapes can coexist as canvas overlays. Cancel Current Poly discards the in-progress polygon; Del Shape removes the last completed shape. - Fill mode: left-click inside any closed polygon to rasterise it onto the mask. Selects the innermost shape containing the click (smallest area via cv2.contourArea). Polygons whose centroid lies inside the target are punched out as holes. Each fill is a single undoable step in the mask history. Also renames the Alpha slider label to Mask Alpha and removes the stale Reload Saved reference from the README. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
65
README.md
65
README.md
@@ -49,7 +49,7 @@ python -m river_annotation_tool.annotation_script
|
||||
| `--data` | *(from config)* | Override `data_dir` from config |
|
||||
| `--out` | *(from config)* | Override `out_dir` from config |
|
||||
| `--clips` | *(from config)* | Override `clips_file` from config |
|
||||
| `--clip` | *(first unannotated in list)* | Open a specific clip by stem name (e.g. `left_20230501`) |
|
||||
| `--clip` | *(first unannotated in list)* | Open a specific clip by stem name |
|
||||
| `--extras` | off | Also save GIFs and extra PNGs (see Output section) |
|
||||
| `--no-skip` | off | Show already-annotated clips instead of skipping them |
|
||||
|
||||
@@ -124,21 +124,58 @@ Copy `config/clips.example.txt` as a starting point.
|
||||
|
||||
The window shows the video on the left (auto-playing) and the survey panel on the right.
|
||||
|
||||
### Mask drawing
|
||||
### Tool modes
|
||||
|
||||
Three drawing tools are available in the tool row. The active tool is highlighted in blue.
|
||||
|
||||
| Tool | How to activate | Description |
|
||||
|---|---|---|
|
||||
| **Brush** | Click **Brush** | Click and drag to paint the mask with a circular brush (default) |
|
||||
| **Polygon** | Click **Polygon** | Click to place vertices and build closed shapes; use **Fill** mode to commit them |
|
||||
| **Fill** | Click **Fill** | Click inside a closed polygon to fill it onto the mask |
|
||||
|
||||
### Brush tool
|
||||
|
||||
| Action | How |
|
||||
|---|---|
|
||||
| Draw water mask | Click and drag on the video |
|
||||
| Erase mask | Toggle **Eraser** button (turns orange when active), then drag |
|
||||
| Brush preview | A white circle follows the cursor showing the current brush size |
|
||||
| Adjust brush size | **Brush size** slider below the controls; click **↺** to reset |
|
||||
| Undo last stroke | **Undo** |
|
||||
| Undo 10 strokes | **Undo×10** |
|
||||
| Redo | **Redo** — steps forward through undone strokes |
|
||||
| Adjust brush size | **Brush size** slider; click **↺** to reset |
|
||||
|
||||
### Polygon tool
|
||||
|
||||
Polygons are drawn as overlays and do not affect the mask until you use **Fill** mode.
|
||||
|
||||
| Action | How |
|
||||
|---|---|
|
||||
| Add vertex | Left-click on the canvas |
|
||||
| Remove last vertex | Right-click |
|
||||
| Close a shape | Left-click near the first vertex (red dot) when ≥ 3 vertices are placed; completed shapes turn bold cyan |
|
||||
| Draw multiple shapes | Each closed shape is kept independently; draw as many as needed |
|
||||
| Cancel in-progress polygon | **Cancel Current Poly** — discards the unfinished polygon, keeps completed shapes |
|
||||
| Delete last completed shape | **Del Shape** |
|
||||
|
||||
### Fill tool
|
||||
|
||||
| Action | How |
|
||||
|---|---|
|
||||
| Fill a shape | Left-click anywhere inside a closed polygon; that shape's interior is painted onto the mask |
|
||||
| Nested shapes | If a closed polygon lies entirely inside the target, its interior is left unfilled (acts as a hole) |
|
||||
| Innermost shape | Clicking inside nested shapes always fills the innermost (smallest) polygon containing the click |
|
||||
| Undo fill | **Undo** — each fill is a single undoable step |
|
||||
|
||||
### Common mask actions
|
||||
|
||||
| Action | How |
|
||||
|---|---|
|
||||
| Undo last action | **Undo** |
|
||||
| Undo 10 actions | **Undo×10** |
|
||||
| Redo | **Redo** |
|
||||
| Clear entire mask | **Clear** |
|
||||
| Toggle mask overlay | **Hide Mask / Show Mask** — button turns red when hidden; does not affect mask data |
|
||||
| Mask transparency | **Alpha** slider below the controls; click **↺** to reset |
|
||||
| Load mask from previous clip | **Load Prev Mask** — copies the saved mask of the previous clip in the list onto the current clip; the action is undoable with **Undo** |
|
||||
| Mask transparency | **Mask Alpha** slider; click **↺** to reset |
|
||||
| Load mask from previous clip | **Load Prev Mask** — copies the saved mask of the previous clip; undoable with **Undo** |
|
||||
|
||||
### Image display adjustments
|
||||
|
||||
@@ -208,11 +245,19 @@ Up to `max_frames` frames are extracted from the video and scaled so the longest
|
||||
|
||||
### Mask drawing
|
||||
|
||||
The mask is a binary NumPy array matching the display frame size. Each brush stroke stamps a filled circle of the selected radius, setting pixels to 1 (draw) or 0 (erase). The history stack stores a copy of the mask before each stroke, enabling unlimited undo. On save the mask is resized to the original video resolution with nearest-neighbour interpolation and written as an 8-bit PNG (0 or 255).
|
||||
The mask is a binary NumPy array matching the display frame size.
|
||||
|
||||
**Brush:** each stroke stamps a filled circle of the selected radius, setting pixels to 1 (draw) or 0 (erase).
|
||||
|
||||
**Polygon:** vertices are stored as a list of floating-point canvas coordinates. Multiple closed shapes can coexist. Completed shapes are rendered as cyan overlays on the canvas but do not touch the mask until a fill is applied.
|
||||
|
||||
**Fill:** clicking inside a closed polygon rasterises it with `cv2.fillPoly` and ORs the result into the mask. Among all shapes containing the click, the innermost (smallest area, determined by `cv2.contourArea`) is selected as the fill target. Any polygon whose centroid lies inside the target is then punched out as a hole.
|
||||
|
||||
Every mask-changing operation (brush stroke, fill) pushes the previous mask onto the undo stack before modifying it. On save the mask is resized to the original video resolution with nearest-neighbour interpolation and written as an 8-bit PNG (0 or 255).
|
||||
|
||||
### Resuming
|
||||
|
||||
When a clip is loaded that already has a saved `mask.png` and `metadata.json`, the mask is restored at display resolution and the survey answers are pre-filled. **Reload Saved** lets you revert to the last save at any point during the current session.
|
||||
When a clip is loaded that already has a saved `mask.png` and `metadata.json`, the mask is restored at display resolution and the survey answers are pre-filled.
|
||||
|
||||
## Repository structure
|
||||
|
||||
|
||||
Reference in New Issue
Block a user