Add optical flow Auto Segment button
Annotators can now press Auto Segment to replace the current mask with an automatic river segmentation based on dense optical flow magnitude and frame brightness. The result is pushed onto the undo stack, so it can be refined or reverted like any other mask operation. Parameters (norm_squared_threshold, gaussian_kernel, brightness_range) live in a separate config/optical_flow_config.yaml; the button is only enabled when optical_flow_config_file is set in config.yaml. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
43
README.md
43
README.md
@@ -95,6 +95,7 @@ max_frames: 100 # max frames to extract per clip
|
||||
data_dir: data/clips # directory containing ZIP archives
|
||||
out_dir: data/annotation_results
|
||||
clips_file: config/clips.txt
|
||||
# optical_flow_config_file: config/optical_flow_config.yaml # optional, enables Auto Segment
|
||||
|
||||
questions:
|
||||
- section: River
|
||||
@@ -108,6 +109,23 @@ questions:
|
||||
|
||||
Add, remove, or reorder questions directly in the YAML — the UI rebuilds automatically. `key` is what gets saved in `metadata.json`; `default` selects the pre-checked option (omit or set to `null` to leave unselected).
|
||||
|
||||
### Optical flow segmentation (optional)
|
||||
|
||||
Set `optical_flow_config_file` in `config.yaml` to point to a YAML file that enables the **Auto Segment** button. When pressed, the tool computes a river mask from the loaded frames and replaces the current mask (undoable). The segmentation combines two criteria:
|
||||
|
||||
- **Optical flow magnitude** — pixels where the temporal median of frame-to-frame flow (scaled by FPS) exceeds a fraction of the maximum are considered moving water.
|
||||
- **Brightness** — pixels outside a brightness window are excluded (removes sky, saturated glare, etc.).
|
||||
|
||||
```yaml
|
||||
# config/optical_flow_config.yaml
|
||||
enabled: true
|
||||
norm_squared_threshold: 0.06 # fraction of max flow² that counts as moving
|
||||
gaussian_kernel: [5, 5] # blur kernel applied to the reference frame before brightness check
|
||||
brightness_range: [2, 253] # [min, max] greyscale brightness to keep
|
||||
```
|
||||
|
||||
`enabled: false` disables the button without removing the config file.
|
||||
|
||||
## Clip list file
|
||||
|
||||
`config/clips.txt` lists the clip filenames to annotate, one per line. Lines starting with `#` are ignored. Clips are processed in order; already-annotated clips (those with an existing `mask.png`) are skipped automatically. Pass `--no-skip` to include them. When the last clip is reached, a dialog appears and the app exits.
|
||||
@@ -176,6 +194,7 @@ Polygons are drawn as overlays and do not affect the mask until you use **Fill**
|
||||
| Toggle mask overlay | **Hide Mask / Show Mask** — button turns red when hidden; does not affect mask data |
|
||||
| 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** |
|
||||
| Optical flow first guess | **Auto Segment** — runs automatic river segmentation and replaces the current mask; undoable with **Undo**. Only enabled when `optical_flow_config_file` is set in `config.yaml`. |
|
||||
|
||||
### Image display adjustments
|
||||
|
||||
@@ -263,18 +282,20 @@ When a clip is loaded that already has a saved `mask.png` and `metadata.json`, t
|
||||
|
||||
```
|
||||
config/
|
||||
config.yaml # Your local config (git-ignored, copy from example)
|
||||
config.example.yaml # Example config to copy and edit
|
||||
clips.txt # Your clip list (git-ignored, copy from example)
|
||||
clips.example.txt # Example clip list
|
||||
config.yaml # Your local config (git-ignored, copy from example)
|
||||
config.example.yaml # Example config to copy and edit
|
||||
clips.txt # Your clip list (git-ignored, copy from example)
|
||||
clips.example.txt # Example clip list
|
||||
optical_flow_config.yaml # Optional optical flow parameters (enable via config.yaml)
|
||||
src/river_annotation_tool/
|
||||
annotation_script.py # Entry point — argument parsing and app launch
|
||||
annotator.py # Main QMainWindow — orchestrates all components
|
||||
clip_selector.py # Reads the clip list and picks the next clip
|
||||
mask_canvas.py # Drawing widget — brush, undo, erase, mouse events
|
||||
video_loader.py # ZIP extraction and frame resizing
|
||||
config.py # AppConfig dataclass and YAML loader
|
||||
__init__.py # Package version
|
||||
annotation_script.py # Entry point — argument parsing and app launch
|
||||
annotator.py # Main QMainWindow — orchestrates all components
|
||||
clip_selector.py # Reads the clip list and picks the next clip
|
||||
mask_canvas.py # Drawing widget — brush, undo, erase, mouse events
|
||||
video_loader.py # ZIP extraction and frame resizing
|
||||
compute_optical_flow.py # Optical flow river segmentation (Auto Segment button)
|
||||
config.py # AppConfig dataclass and YAML loader
|
||||
__init__.py # Package version
|
||||
pyproject.toml # Project metadata and dependencies
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user