argus-cv 1.3.0__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of argus-cv might be problematic. Click here for more details.

Files changed (41) hide show
  1. {argus_cv-1.3.0 → argus_cv-1.5.0}/CHANGELOG.md +16 -0
  2. {argus_cv-1.3.0 → argus_cv-1.5.0}/PKG-INFO +9 -2
  3. {argus_cv-1.3.0 → argus_cv-1.5.0}/README.md +8 -1
  4. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/getting-started/installation.md +5 -5
  5. argus_cv-1.5.0/docs/guides/datasets.md +142 -0
  6. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/guides/listing.md +1 -1
  7. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/guides/splitting.md +1 -7
  8. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/guides/stats.md +3 -0
  9. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/guides/viewer.md +9 -1
  10. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/index.md +5 -4
  11. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/reference/cli.md +2 -3
  12. {argus_cv-1.3.0 → argus_cv-1.5.0}/mkdocs.yml +1 -1
  13. {argus_cv-1.3.0 → argus_cv-1.5.0}/pyproject.toml +1 -1
  14. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/__init__.py +1 -1
  15. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/cli.py +157 -14
  16. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/core/__init__.py +12 -0
  17. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/core/coco.py +46 -8
  18. argus_cv-1.5.0/src/argus/core/convert.py +277 -0
  19. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/core/yolo.py +29 -0
  20. {argus_cv-1.3.0 → argus_cv-1.5.0}/tests/conftest.py +86 -0
  21. argus_cv-1.5.0/tests/test_convert.py +541 -0
  22. {argus_cv-1.3.0 → argus_cv-1.5.0}/tests/test_list_command.py +73 -0
  23. argus_cv-1.3.0/docs/guides/datasets.md +0 -68
  24. {argus_cv-1.3.0 → argus_cv-1.5.0}/.github/workflows/ci.yml +0 -0
  25. {argus_cv-1.3.0 → argus_cv-1.5.0}/.github/workflows/docs.yml +0 -0
  26. {argus_cv-1.3.0 → argus_cv-1.5.0}/.github/workflows/release.yml +0 -0
  27. {argus_cv-1.3.0 → argus_cv-1.5.0}/.gitignore +0 -0
  28. {argus_cv-1.3.0 → argus_cv-1.5.0}/.pre-commit-config.yaml +0 -0
  29. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/assets/javascripts/extra.js +0 -0
  30. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/assets/stylesheets/extra.css +0 -0
  31. {argus_cv-1.3.0 → argus_cv-1.5.0}/docs/getting-started/quickstart.md +0 -0
  32. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/__main__.py +0 -0
  33. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/commands/__init__.py +0 -0
  34. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/core/base.py +0 -0
  35. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/core/mask.py +0 -0
  36. {argus_cv-1.3.0 → argus_cv-1.5.0}/src/argus/core/split.py +0 -0
  37. {argus_cv-1.3.0 → argus_cv-1.5.0}/tests/test_classification.py +0 -0
  38. {argus_cv-1.3.0 → argus_cv-1.5.0}/tests/test_mask.py +0 -0
  39. {argus_cv-1.3.0 → argus_cv-1.5.0}/tests/test_split_command.py +0 -0
  40. {argus_cv-1.3.0 → argus_cv-1.5.0}/tests/test_stats_command.py +0 -0
  41. {argus_cv-1.3.0 → argus_cv-1.5.0}/uv.lock +0 -0
@@ -2,6 +2,22 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.5.0 (2026-01-28)
6
+
7
+ ### Features
8
+
9
+ - Support Roboflow COCO format and improve YOLO classification detection
10
+ ([`902a59f`](https://github.com/pirnerjonas/argus/commit/902a59fbb506aa586d8677312d21ae240585b511))
11
+
12
+
13
+ ## v1.4.0 (2026-01-26)
14
+
15
+ ### Features
16
+
17
+ - **view**: Show polygon vertices and hide bbox for segmentation
18
+ ([`03b34f7`](https://github.com/pirnerjonas/argus/commit/03b34f78fdafefd35a8b2594bf1296007716d6c9))
19
+
20
+
5
21
  ## v1.3.0 (2026-01-24)
6
22
 
7
23
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: argus-cv
3
- Version: 1.3.0
3
+ Version: 1.5.0
4
4
  Summary: CLI tool for working with vision AI datasets
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: numpy>=1.24.0
@@ -12,7 +12,7 @@ Description-Content-Type: text/markdown
12
12
 
13
13
  # argus-cv
14
14
 
15
- Vision AI dataset toolkit for working with YOLO and COCO datasets.
15
+ Vision AI dataset toolkit for working with YOLO, COCO, and semantic mask datasets.
16
16
 
17
17
  **[Documentation](https://pirnerjonas.github.io/argus/)**
18
18
 
@@ -22,6 +22,13 @@ Vision AI dataset toolkit for working with YOLO and COCO datasets.
22
22
  uvx argus-cv
23
23
  ```
24
24
 
25
+ ## Highlights
26
+
27
+ - Detects YOLO, COCO, and folder-based semantic mask datasets.
28
+ - Reports per-class stats (pixel coverage for mask datasets).
29
+ - Interactive viewer with bounding boxes, polygons, or mask overlays.
30
+ - Split unsplit YOLO/COCO datasets into train/val/test.
31
+
25
32
  ## Usage
26
33
 
27
34
  ```bash
@@ -1,6 +1,6 @@
1
1
  # argus-cv
2
2
 
3
- Vision AI dataset toolkit for working with YOLO and COCO datasets.
3
+ Vision AI dataset toolkit for working with YOLO, COCO, and semantic mask datasets.
4
4
 
5
5
  **[Documentation](https://pirnerjonas.github.io/argus/)**
6
6
 
@@ -10,6 +10,13 @@ Vision AI dataset toolkit for working with YOLO and COCO datasets.
10
10
  uvx argus-cv
11
11
  ```
12
12
 
13
+ ## Highlights
14
+
15
+ - Detects YOLO, COCO, and folder-based semantic mask datasets.
16
+ - Reports per-class stats (pixel coverage for mask datasets).
17
+ - Interactive viewer with bounding boxes, polygons, or mask overlays.
18
+ - Split unsplit YOLO/COCO datasets into train/val/test.
19
+
13
20
  ## Usage
14
21
 
15
22
  ```bash
@@ -6,7 +6,7 @@ workflow.
6
6
  ## Quick install with uv
7
7
 
8
8
  ```bash
9
- uvx argus
9
+ uvx argus-cv
10
10
  ```
11
11
 
12
12
  `uvx` runs the package in an isolated environment and keeps it up to date.
@@ -14,19 +14,19 @@ uvx argus
14
14
  Verify it works:
15
15
 
16
16
  ```bash
17
- argus --help
17
+ argus-cv --help
18
18
  ```
19
19
 
20
20
  ## pipx
21
21
 
22
22
  ```bash
23
- pipx install argus
23
+ pipx install argus-cv
24
24
  ```
25
25
 
26
26
  Verify it works:
27
27
 
28
28
  ```bash
29
- argus --help
29
+ argus-cv --help
30
30
  ```
31
31
 
32
32
  ## From source
@@ -40,7 +40,7 @@ pip install -e .
40
40
  Verify it works:
41
41
 
42
42
  ```bash
43
- argus --help
43
+ argus-cv --help
44
44
  ```
45
45
 
46
46
  ## Requirements
@@ -0,0 +1,142 @@
1
+ # Dataset formats
2
+
3
+ Argus supports YOLO, COCO, and folder-based semantic mask datasets. Detection
4
+ and segmentation are handled out of the box.
5
+
6
+ ## YOLO
7
+
8
+ Argus looks for a YAML config file with a `names` key. It uses that file to
9
+ extract class names and verify the dataset layout.
10
+
11
+ Typical structure:
12
+
13
+ ```text
14
+ dataset/
15
+ ├── data.yaml
16
+ ├── images/
17
+ │ ├── train/
18
+ │ ├── val/
19
+ │ └── test/
20
+ └── labels/
21
+ ├── train/
22
+ ├── val/
23
+ └── test/
24
+ ```
25
+
26
+ Unsplit YOLO datasets are also supported:
27
+
28
+ ```text
29
+ dataset/
30
+ ├── data.yaml
31
+ ├── images/
32
+ └── labels/
33
+ ```
34
+
35
+ Argus infers the task type by scanning a few label files:
36
+
37
+ - 5 values per line: detection
38
+ - more than 5 values per line: segmentation polygons
39
+
40
+ ## COCO
41
+
42
+ Argus looks for COCO annotation JSON files in `annotations/` or at the dataset
43
+ root.
44
+
45
+ Typical structure:
46
+
47
+ ```text
48
+ dataset/
49
+ ├── annotations/
50
+ │ ├── instances_train.json
51
+ │ ├── instances_val.json
52
+ │ └── instances_test.json
53
+ └── images/
54
+ ├── train/
55
+ ├── val/
56
+ └── test/
57
+ ```
58
+
59
+ If your annotation filenames include `train`, `val`, or `test`, Argus will treat
60
+ those as splits. Otherwise it defaults to `train`.
61
+
62
+ ### Roboflow COCO
63
+
64
+ Argus also supports the Roboflow variant of COCO format, where annotations live
65
+ inside split directories:
66
+
67
+ ```text
68
+ dataset/
69
+ ├── train/
70
+ │ ├── _annotations.coco.json
71
+ │ └── *.jpg
72
+ ├── valid/
73
+ │ ├── _annotations.coco.json
74
+ │ └── *.jpg
75
+ └── test/
76
+ ├── _annotations.coco.json
77
+ └── *.jpg
78
+ ```
79
+
80
+ Splits are detected from directory names (`train`, `valid`/`val`, `test`).
81
+
82
+ ## Mask (semantic segmentation)
83
+
84
+ Mask datasets are simple image + mask folders. Argus detects a few common
85
+ patterns:
86
+
87
+ - `images/` + `masks/`
88
+ - `img/` + `gt/`
89
+ - `leftImg8bit/` + `gtFine/` (Cityscapes-style)
90
+
91
+ Split-aware layout:
92
+
93
+ ```text
94
+ dataset/
95
+ ├── images/
96
+ │ ├── train/
97
+ │ └── val/
98
+ ├── masks/
99
+ │ ├── train/
100
+ │ └── val/
101
+ └── classes.yaml # Optional for grayscale, required for RGB palette masks
102
+ ```
103
+
104
+ Unsplit layout:
105
+
106
+ ```text
107
+ dataset/
108
+ ├── images/
109
+ ├── masks/
110
+ └── classes.yaml
111
+ ```
112
+
113
+ ### Mask encoding
114
+
115
+ - Grayscale masks: each pixel value is the class ID. Argus will auto-detect
116
+ class IDs if no `classes.yaml` is provided.
117
+ - RGB palette masks: each class maps to a color. A `classes.yaml` is required.
118
+ - Mask files should be `.png` and match the image stem (e.g., `frame.png`), or
119
+ use common suffixes like `_mask`, `_gt`, or `_label`.
120
+
121
+ Example `classes.yaml`:
122
+
123
+ ```yaml
124
+ names:
125
+ - background
126
+ - road
127
+ - sidewalk
128
+ ignore_index: 255
129
+ palette:
130
+ - id: 0
131
+ name: background
132
+ - id: 1
133
+ name: road
134
+ ```
135
+
136
+ ## Detection heuristics
137
+
138
+ If Argus does not detect your dataset, check the following:
139
+
140
+ - The dataset root is correct and readable.
141
+ - YOLO: the YAML file includes `names` as a list or dict.
142
+ - COCO: `images`, `annotations`, and `categories` exist in the JSON.
@@ -11,7 +11,7 @@ argus-cv list --path /datasets
11
11
  This prints a table showing:
12
12
 
13
13
  - Dataset path
14
- - Format (yolo or coco)
14
+ - Format (yolo, coco, or mask)
15
15
  - Task (detection or segmentation)
16
16
  - Number of classes
17
17
  - Detected splits
@@ -8,7 +8,7 @@ Use `argus-cv split` to create train/val/test splits from an unsplit dataset.
8
8
  argus-cv split -d /datasets/animals -o /datasets/animals_splits
9
9
  ```
10
10
 
11
- By default, Argus uses a 0.8/0.1/0.1 ratio and stratified sampling.
11
+ Argus uses a 0.8/0.1/0.1 ratio and stratified sampling by default.
12
12
 
13
13
  ## Custom ratio
14
14
 
@@ -18,12 +18,6 @@ argus-cv split -d /datasets/animals -o /datasets/animals_splits -r 0.7,0.2,0.1
18
18
 
19
19
  Ratios can sum to 1.0 or 100.
20
20
 
21
- ## Disable stratification
22
-
23
- ```bash
24
- argus-cv split -d /datasets/animals -o /datasets/animals_splits --no-stratify
25
- ```
26
-
27
21
  ## Set a seed for determinism
28
22
 
29
23
  ```bash
@@ -1,6 +1,8 @@
1
1
  # Stats and counts
2
2
 
3
3
  `argus-cv stats` provides per-class instance counts and image totals by split.
4
+ For mask datasets, it reports pixel coverage and how many images contain each
5
+ class.
4
6
 
5
7
  ## Example
6
8
 
@@ -25,3 +27,4 @@ If Argus prints "No annotations found", check:
25
27
 
26
28
  - YOLO: `labels/` exists and matches `images/`.
27
29
  - COCO: annotation JSON files are valid and contain `annotations`.
30
+ - Mask: masks are `.png` files and match the image file names.
@@ -1,6 +1,7 @@
1
1
  # Visual inspection
2
2
 
3
- The viewer overlays boxes and masks for quick spot checks.
3
+ The viewer overlays boxes and masks for quick spot checks. For mask datasets,
4
+ it blends the segmentation mask over the image.
4
5
 
5
6
  ## Launching the viewer
6
7
 
@@ -14,6 +15,12 @@ argus-cv view -d /datasets/retail
14
15
  argus-cv view -d /datasets/retail --split val
15
16
  ```
16
17
 
18
+ ### Adjust mask opacity
19
+
20
+ ```bash
21
+ argus-cv view -d /datasets/roads --opacity 0.3
22
+ ```
23
+
17
24
  ## Controls
18
25
 
19
26
  - Right arrow or `N`: next image
@@ -22,6 +29,7 @@ argus-cv view -d /datasets/retail --split val
22
29
  - Drag: pan while zoomed
23
30
  - `R`: reset zoom
24
31
  - `Q` or `Esc`: quit
32
+ - `T`: toggle annotations or mask overlay
25
33
 
26
34
  ## Notes
27
35
 
@@ -3,8 +3,9 @@
3
3
  <p class="hero__eyebrow">Argus</p>
4
4
  <h1>Vision AI dataset work, without the friction.</h1>
5
5
  <p>
6
- Argus is a focused CLI for YOLO and COCO datasets. List datasets, inspect
7
- class balance, view annotations, and split cleanly for training.
6
+ Argus is a focused CLI for YOLO, COCO, and semantic mask datasets. List
7
+ datasets, inspect class balance, view annotations, and split cleanly for
8
+ training.
8
9
  </p>
9
10
  <div class="hero__actions">
10
11
  <a class="md-button md-button--primary" href="getting-started/quickstart/">Get started</a>
@@ -30,7 +31,7 @@ argus-cv view -d /data/animals --split val
30
31
  <div class="grid cards">
31
32
  <div class="card">
32
33
  <h3>Format-aware</h3>
33
- <p>Detects YOLO and COCO by structure and metadata, not guesses.</p>
34
+ <p>Detects YOLO, COCO, and mask datasets by structure and metadata.</p>
34
35
  </div>
35
36
  <div class="card">
36
37
  <h3>Readable statistics</h3>
@@ -38,7 +39,7 @@ argus-cv view -d /data/animals --split val
38
39
  </div>
39
40
  <div class="card">
40
41
  <h3>Annotation viewer</h3>
41
- <p>Browse images with boxes and masks overlayed. Pan and zoom included.</p>
42
+ <p>Browse images with boxes, polygons, and mask overlays. Pan and zoom included.</p>
42
43
  </div>
43
44
  <div class="card">
44
45
  <h3>Clean splits</h3>
@@ -3,7 +3,7 @@
3
3
  ## Global
4
4
 
5
5
  ```bash
6
- argus --help
6
+ argus-cv --help
7
7
  ```
8
8
 
9
9
  Argus uses subcommands: `list`, `stats`, `view`, and `split`.
@@ -45,6 +45,7 @@ Options:
45
45
 
46
46
  - `--dataset-path`, `-d`: dataset root path
47
47
  - `--split`, `-s`: split to view (train, val, test)
48
+ - `--opacity`, `-o`: mask overlay opacity (mask datasets only)
48
49
 
49
50
  ## split
50
51
 
@@ -54,7 +55,6 @@ Create train/val/test splits from an unsplit dataset.
54
55
  argus-cv split --dataset-path /datasets/animals \
55
56
  --output-path /datasets/animals_splits \
56
57
  --ratio 0.8,0.1,0.1 \
57
- --stratify \
58
58
  --seed 42
59
59
  ```
60
60
 
@@ -63,5 +63,4 @@ Options:
63
63
  - `--dataset-path`, `-d`: dataset root path
64
64
  - `--output-path`, `-o`: output directory (default: "splits" inside dataset path)
65
65
  - `--ratio`, `-r`: train/val/test ratio (default: 0.8,0.1,0.1)
66
- - `--stratify/--no-stratify`: enable or disable stratified splitting (default: enabled)
67
66
  - `--seed`: random seed (default: 42)
@@ -1,5 +1,5 @@
1
1
  site_name: Argus
2
- site_description: Vision AI dataset toolkit for YOLO and COCO datasets.
2
+ site_description: Vision AI dataset toolkit for YOLO, COCO, and mask datasets.
3
3
  site_author: Argus
4
4
  site_url: https://pirnerjonas.github.io/argus/
5
5
  repo_name: pirnerjonas/argus
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "argus-cv"
3
- version = "1.3.0"
3
+ version = "1.5.0"
4
4
  description = "CLI tool for working with vision AI datasets"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """Argus - Vision AI dataset toolkit."""
2
2
 
3
- __version__ = "1.3.0"
3
+ __version__ = "1.5.0"
@@ -8,11 +8,18 @@ import cv2
8
8
  import numpy as np
9
9
  import typer
10
10
  from rich.console import Console
11
- from rich.progress import Progress, SpinnerColumn, TextColumn
11
+ from rich.progress import (
12
+ BarColumn,
13
+ Progress,
14
+ SpinnerColumn,
15
+ TaskProgressColumn,
16
+ TextColumn,
17
+ )
12
18
  from rich.table import Table
13
19
 
14
20
  from argus.core import COCODataset, Dataset, MaskDataset, YOLODataset
15
21
  from argus.core.base import DatasetFormat, TaskType
22
+ from argus.core.convert import convert_mask_to_yolo_seg
16
23
  from argus.core.split import (
17
24
  is_coco_unsplit,
18
25
  parse_ratio,
@@ -534,13 +541,6 @@ def split_dataset(
534
541
  help="Train/val/test ratio (e.g. 0.8,0.1,0.1).",
535
542
  ),
536
543
  ] = "0.8,0.1,0.1",
537
- stratify: Annotated[
538
- bool,
539
- typer.Option(
540
- "--stratify/--no-stratify",
541
- help="Stratify by class distribution when splitting.",
542
- ),
543
- ] = True,
544
544
  seed: Annotated[
545
545
  int,
546
546
  typer.Option(
@@ -593,9 +593,7 @@ def split_dataset(
593
593
  ) as progress:
594
594
  progress.add_task("Creating YOLO splits...", total=None)
595
595
  try:
596
- counts = split_yolo_dataset(
597
- dataset, output_path, ratios, stratify, seed
598
- )
596
+ counts = split_yolo_dataset(dataset, output_path, ratios, True, seed)
599
597
  except ValueError as exc:
600
598
  console.print(f"[red]Error: {exc}[/red]")
601
599
  raise typer.Exit(1) from exc
@@ -628,7 +626,7 @@ def split_dataset(
628
626
  annotation_file,
629
627
  output_path,
630
628
  ratios,
631
- stratify,
629
+ True,
632
630
  seed,
633
631
  )
634
632
  except ValueError as exc:
@@ -641,6 +639,148 @@ def split_dataset(
641
639
  )
642
640
 
643
641
 
642
+ @app.command(name="convert")
643
+ def convert_dataset(
644
+ input_path: Annotated[
645
+ Path,
646
+ typer.Option(
647
+ "--input-path",
648
+ "-i",
649
+ help="Path to the source dataset.",
650
+ ),
651
+ ] = Path("."),
652
+ output_path: Annotated[
653
+ Path,
654
+ typer.Option(
655
+ "--output-path",
656
+ "-o",
657
+ help="Output directory for converted dataset.",
658
+ ),
659
+ ] = Path("converted"),
660
+ to_format: Annotated[
661
+ str,
662
+ typer.Option(
663
+ "--to",
664
+ help="Target format (currently only 'yolo-seg' is supported).",
665
+ ),
666
+ ] = "yolo-seg",
667
+ epsilon_factor: Annotated[
668
+ float,
669
+ typer.Option(
670
+ "--epsilon-factor",
671
+ "-e",
672
+ help="Polygon simplification factor (Douglas-Peucker algorithm).",
673
+ min=0.0,
674
+ max=1.0,
675
+ ),
676
+ ] = 0.005,
677
+ min_area: Annotated[
678
+ float,
679
+ typer.Option(
680
+ "--min-area",
681
+ "-a",
682
+ help="Minimum contour area in pixels to include.",
683
+ min=0.0,
684
+ ),
685
+ ] = 100.0,
686
+ ) -> None:
687
+ """Convert a dataset from one format to another.
688
+
689
+ Currently supports converting MaskDataset to YOLO segmentation format.
690
+
691
+ Example:
692
+ uvx argus-cv convert -i /path/to/masks -o /path/to/output --to yolo-seg
693
+ """
694
+ # Validate format
695
+ if to_format != "yolo-seg":
696
+ console.print(
697
+ f"[red]Error: Unsupported target format '{to_format}'.[/red]\n"
698
+ "[yellow]Currently only 'yolo-seg' is supported.[/yellow]"
699
+ )
700
+ raise typer.Exit(1)
701
+
702
+ # Resolve and validate input path
703
+ input_path = input_path.resolve()
704
+ if not input_path.exists():
705
+ console.print(f"[red]Error: Path does not exist: {input_path}[/red]")
706
+ raise typer.Exit(1)
707
+ if not input_path.is_dir():
708
+ console.print(f"[red]Error: Path is not a directory: {input_path}[/red]")
709
+ raise typer.Exit(1)
710
+
711
+ # Detect source dataset - must be MaskDataset for yolo-seg conversion
712
+ dataset = MaskDataset.detect(input_path)
713
+ if not dataset:
714
+ console.print(
715
+ f"[red]Error: No MaskDataset found at {input_path}[/red]\n"
716
+ "[yellow]Ensure the path contains images/ + masks/ directories "
717
+ "(or equivalent patterns like img/+gt/ or leftImg8bit/+gtFine/).[/yellow]"
718
+ )
719
+ raise typer.Exit(1)
720
+
721
+ # Resolve output path
722
+ if not output_path.is_absolute():
723
+ output_path = input_path.parent / output_path
724
+ output_path = output_path.resolve()
725
+
726
+ # Check if output already exists
727
+ if output_path.exists() and any(output_path.iterdir()):
728
+ console.print(
729
+ f"[red]Error: Output directory already exists and is not empty: "
730
+ f"{output_path}[/red]"
731
+ )
732
+ raise typer.Exit(1)
733
+
734
+ # Show conversion info
735
+ console.print("[cyan]Converting MaskDataset to YOLO segmentation format[/cyan]")
736
+ console.print(f" Source: {input_path}")
737
+ console.print(f" Output: {output_path}")
738
+ console.print(f" Classes: {dataset.num_classes}")
739
+ splits_str = ", ".join(dataset.splits) if dataset.splits else "unsplit"
740
+ console.print(f" Splits: {splits_str}")
741
+ console.print()
742
+
743
+ # Run conversion with progress bar
744
+ with Progress(
745
+ SpinnerColumn(),
746
+ TextColumn("[progress.description]{task.description}"),
747
+ BarColumn(),
748
+ TaskProgressColumn(),
749
+ console=console,
750
+ ) as progress:
751
+ task = progress.add_task("Processing images...", total=None)
752
+
753
+ def update_progress(current: int, total: int) -> None:
754
+ progress.update(task, completed=current, total=total)
755
+
756
+ try:
757
+ stats = convert_mask_to_yolo_seg(
758
+ dataset=dataset,
759
+ output_path=output_path,
760
+ epsilon_factor=epsilon_factor,
761
+ min_area=min_area,
762
+ progress_callback=update_progress,
763
+ )
764
+ except Exception as exc:
765
+ console.print(f"[red]Error during conversion: {exc}[/red]")
766
+ raise typer.Exit(1) from exc
767
+
768
+ # Show results
769
+ console.print()
770
+ console.print("[green]Conversion complete![/green]")
771
+ console.print(f" Images processed: {stats['images']}")
772
+ console.print(f" Labels created: {stats['labels']}")
773
+ console.print(f" Polygons extracted: {stats['polygons']}")
774
+
775
+ if stats["skipped"] > 0:
776
+ skipped = stats["skipped"]
777
+ console.print(f" [yellow]Skipped: {skipped} (no mask or empty)[/yellow]")
778
+ if stats["warnings"] > 0:
779
+ console.print(f" [yellow]Warnings: {stats['warnings']}[/yellow]")
780
+
781
+ console.print(f"\n[cyan]Output dataset: {output_path}[/cyan]")
782
+
783
+
644
784
  class _ImageViewer:
645
785
  """Interactive image viewer with zoom and pan support."""
646
786
 
@@ -1352,9 +1492,12 @@ def _draw_annotations(
1352
1492
  overlay = img.copy()
1353
1493
  cv2.fillPoly(overlay, [pts], color)
1354
1494
  cv2.addWeighted(overlay, 0.3, img, 0.7, 0, img)
1495
+ # Draw small points at polygon vertices
1496
+ for pt in pts:
1497
+ cv2.circle(img, tuple(pt), radius=3, color=color, thickness=-1)
1355
1498
 
1356
- # Draw bounding box
1357
- if bbox:
1499
+ # Draw bounding box (only for detection, not segmentation)
1500
+ if bbox and not polygon:
1358
1501
  x, y, w, h = bbox
1359
1502
  x1, y1 = int(x), int(y)
1360
1503
  x2, y2 = int(x + w), int(y + h)
@@ -2,6 +2,13 @@
2
2
 
3
3
  from argus.core.base import Dataset
4
4
  from argus.core.coco import COCODataset
5
+ from argus.core.convert import (
6
+ ConversionParams,
7
+ Polygon,
8
+ convert_mask_to_yolo_labels,
9
+ convert_mask_to_yolo_seg,
10
+ mask_to_polygons,
11
+ )
5
12
  from argus.core.mask import ConfigurationError, MaskDataset
6
13
  from argus.core.split import split_coco_dataset, split_yolo_dataset
7
14
  from argus.core.yolo import YOLODataset
@@ -14,4 +21,9 @@ __all__ = [
14
21
  "ConfigurationError",
15
22
  "split_coco_dataset",
16
23
  "split_yolo_dataset",
24
+ "ConversionParams",
25
+ "Polygon",
26
+ "mask_to_polygons",
27
+ "convert_mask_to_yolo_labels",
28
+ "convert_mask_to_yolo_seg",
17
29
  ]