scribble-annotation-generator 0.0.1__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.
- scribble_annotation_generator-0.0.1/.gitignore +5 -0
- scribble_annotation_generator-0.0.1/PKG-INFO +108 -0
- scribble_annotation_generator-0.0.1/README.md +79 -0
- scribble_annotation_generator-0.0.1/pyproject.toml +54 -0
- scribble_annotation_generator-0.0.1/scribble_annotation_generator/__init__.py +0 -0
- scribble_annotation_generator-0.0.1/scribble_annotation_generator/cli.py +195 -0
- scribble_annotation_generator-0.0.1/scribble_annotation_generator/crop_field.py +366 -0
- scribble_annotation_generator-0.0.1/scribble_annotation_generator/dataset.py +96 -0
- scribble_annotation_generator-0.0.1/scribble_annotation_generator/debug.py +43 -0
- scribble_annotation_generator-0.0.1/scribble_annotation_generator/nn.py +570 -0
- scribble_annotation_generator-0.0.1/scribble_annotation_generator/utils.py +495 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: scribble-annotation-generator
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Programmatically generate semi-realistic synthetic scribble annotations based on statistics from existing scribble datasets
|
|
5
|
+
Project-URL: Homepage, https://github.com/alexsenden/scribble-annotation-generator
|
|
6
|
+
Project-URL: Repository, https://github.com/alexsenden/scribble-annotation-generator
|
|
7
|
+
Project-URL: Issues, https://github.com/alexsenden/scribble-annotation-generator/issues
|
|
8
|
+
Author: Alex Senden
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: annotation,computer-vision,scribble,segmentation,synthetic-data
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Requires-Dist: numpy
|
|
25
|
+
Requires-Dist: opencv-python
|
|
26
|
+
Requires-Dist: scikit-image
|
|
27
|
+
Requires-Dist: scipy
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Scribble Annotation Generator
|
|
31
|
+
|
|
32
|
+
Programmatically generate semi-realistic scribble annotations for segmentation-style tasks. The project exposes a single CLI entrypoint for two workflows: synthetic crop-field generation and training/inference of the neural scribble generator.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install -e .
|
|
38
|
+
# or
|
|
39
|
+
pip install scribble-annotation-generator
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
After installation, the CLI command `scribble-annotation-generator` becomes available.
|
|
43
|
+
|
|
44
|
+
## Colour Map Specification
|
|
45
|
+
|
|
46
|
+
Many commands require a colour map that links RGB tuples to class IDs. Provide it in either form:
|
|
47
|
+
|
|
48
|
+
- Inline string: `R,G,B=class;R,G,B=class` (also accepts `R,G,B:class`)
|
|
49
|
+
- Example: `0,0,0=0;0,128,255=1;124,255,121=2`
|
|
50
|
+
- File path: a text file with one entry per line. Each line is `R,G,B,class`. If the class column is omitted, class IDs are assigned by line order starting at 0.
|
|
51
|
+
|
|
52
|
+
## CLI
|
|
53
|
+
|
|
54
|
+
### 1) Crop-field synthesis
|
|
55
|
+
|
|
56
|
+
Generate synthetic crop-field scribble images using a procedural model.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
scribble-annotation-generator crop-field \
|
|
60
|
+
--colour-map "0,0,0=0;0,128,255=1;124,255,121=2" \
|
|
61
|
+
--output-dir ./path/to/output \
|
|
62
|
+
--num-samples 50 \
|
|
63
|
+
--min-rows 4 \
|
|
64
|
+
--max-rows 6
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Key flags:
|
|
68
|
+
|
|
69
|
+
- `--colour-map` (required): inline or file as described above
|
|
70
|
+
- `--output-dir`: where PNGs are written (default `./local/crop_field`)
|
|
71
|
+
- `--num-samples`: number of images to create (default `200`)
|
|
72
|
+
- `--min-rows`, `--max-rows`: range for rows per sample
|
|
73
|
+
|
|
74
|
+
### 2) Train and run neural generator
|
|
75
|
+
|
|
76
|
+
Train the transformer-based object generator on a dataset of scribble annotations, then render model predictions on the validation set.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
scribble-annotation-generator train-nn \
|
|
80
|
+
--train-dir ./local/soybean1/train \
|
|
81
|
+
--val-dir ./local/soybean1/val \
|
|
82
|
+
--colour-map ./colour_map.csv \
|
|
83
|
+
--checkpoint-dir ./local/nn-checkpoints \
|
|
84
|
+
--inference-dir ./local/nn-inference \
|
|
85
|
+
--batch-size 8 \
|
|
86
|
+
--num-workers 4 \
|
|
87
|
+
--max-epochs 50
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Key flags:
|
|
91
|
+
|
|
92
|
+
- `--train-dir`, `--val-dir` (required): directories containing training and validation data
|
|
93
|
+
- `--colour-map` (required): inline or file form
|
|
94
|
+
- `--checkpoint-dir`: where PyTorch Lightning checkpoints are stored (default `./local/nn-checkpoints`)
|
|
95
|
+
- `--inference-dir`: where rendered scribbles from validation samples are saved (default `./local/nn-inference`)
|
|
96
|
+
- `--batch-size`, `--num-workers`, `--max-epochs`: training configuration
|
|
97
|
+
- `--num-classes`: override number of classes; by default derived from the colour map
|
|
98
|
+
|
|
99
|
+
## Python API
|
|
100
|
+
|
|
101
|
+
Instead of calling the CLI, you can call the main functions directly:
|
|
102
|
+
|
|
103
|
+
- `scribble_annotation_generator.crop_field.generate_crop_field_dataset(output_dir, colour_map, num_samples=..., min_rows=..., max_rows=...)`
|
|
104
|
+
- `scribble_annotation_generator.nn.train_and_infer(train_dir, val_dir, colour_map, checkpoint_dir=..., inference_dir=..., batch_size=..., num_workers=..., max_epochs=..., num_classes=None)`
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Scribble Annotation Generator
|
|
2
|
+
|
|
3
|
+
Programmatically generate semi-realistic scribble annotations for segmentation-style tasks. The project exposes a single CLI entrypoint for two workflows: synthetic crop-field generation and training/inference of the neural scribble generator.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install -e .
|
|
9
|
+
# or
|
|
10
|
+
pip install scribble-annotation-generator
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
After installation, the CLI command `scribble-annotation-generator` becomes available.
|
|
14
|
+
|
|
15
|
+
## Colour Map Specification
|
|
16
|
+
|
|
17
|
+
Many commands require a colour map that links RGB tuples to class IDs. Provide it in either form:
|
|
18
|
+
|
|
19
|
+
- Inline string: `R,G,B=class;R,G,B=class` (also accepts `R,G,B:class`)
|
|
20
|
+
- Example: `0,0,0=0;0,128,255=1;124,255,121=2`
|
|
21
|
+
- File path: a text file with one entry per line. Each line is `R,G,B,class`. If the class column is omitted, class IDs are assigned by line order starting at 0.
|
|
22
|
+
|
|
23
|
+
## CLI
|
|
24
|
+
|
|
25
|
+
### 1) Crop-field synthesis
|
|
26
|
+
|
|
27
|
+
Generate synthetic crop-field scribble images using a procedural model.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
scribble-annotation-generator crop-field \
|
|
31
|
+
--colour-map "0,0,0=0;0,128,255=1;124,255,121=2" \
|
|
32
|
+
--output-dir ./path/to/output \
|
|
33
|
+
--num-samples 50 \
|
|
34
|
+
--min-rows 4 \
|
|
35
|
+
--max-rows 6
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Key flags:
|
|
39
|
+
|
|
40
|
+
- `--colour-map` (required): inline or file as described above
|
|
41
|
+
- `--output-dir`: where PNGs are written (default `./local/crop_field`)
|
|
42
|
+
- `--num-samples`: number of images to create (default `200`)
|
|
43
|
+
- `--min-rows`, `--max-rows`: range for rows per sample
|
|
44
|
+
|
|
45
|
+
### 2) Train and run neural generator
|
|
46
|
+
|
|
47
|
+
Train the transformer-based object generator on a dataset of scribble annotations, then render model predictions on the validation set.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
scribble-annotation-generator train-nn \
|
|
51
|
+
--train-dir ./local/soybean1/train \
|
|
52
|
+
--val-dir ./local/soybean1/val \
|
|
53
|
+
--colour-map ./colour_map.csv \
|
|
54
|
+
--checkpoint-dir ./local/nn-checkpoints \
|
|
55
|
+
--inference-dir ./local/nn-inference \
|
|
56
|
+
--batch-size 8 \
|
|
57
|
+
--num-workers 4 \
|
|
58
|
+
--max-epochs 50
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Key flags:
|
|
62
|
+
|
|
63
|
+
- `--train-dir`, `--val-dir` (required): directories containing training and validation data
|
|
64
|
+
- `--colour-map` (required): inline or file form
|
|
65
|
+
- `--checkpoint-dir`: where PyTorch Lightning checkpoints are stored (default `./local/nn-checkpoints`)
|
|
66
|
+
- `--inference-dir`: where rendered scribbles from validation samples are saved (default `./local/nn-inference`)
|
|
67
|
+
- `--batch-size`, `--num-workers`, `--max-epochs`: training configuration
|
|
68
|
+
- `--num-classes`: override number of classes; by default derived from the colour map
|
|
69
|
+
|
|
70
|
+
## Python API
|
|
71
|
+
|
|
72
|
+
Instead of calling the CLI, you can call the main functions directly:
|
|
73
|
+
|
|
74
|
+
- `scribble_annotation_generator.crop_field.generate_crop_field_dataset(output_dir, colour_map, num_samples=..., min_rows=..., max_rows=...)`
|
|
75
|
+
- `scribble_annotation_generator.nn.train_and_infer(train_dir, val_dir, colour_map, checkpoint_dir=..., inference_dir=..., batch_size=..., num_workers=..., max_epochs=..., num_classes=None)`
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling", "hatch-vcs"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "scribble-annotation-generator"
|
|
7
|
+
description = "Programmatically generate semi-realistic synthetic scribble annotations based on statistics from existing scribble datasets"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.8"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Alex Senden" }]
|
|
12
|
+
keywords = [
|
|
13
|
+
"scribble",
|
|
14
|
+
"annotation",
|
|
15
|
+
"segmentation",
|
|
16
|
+
"computer-vision",
|
|
17
|
+
"synthetic-data",
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.8",
|
|
26
|
+
"Programming Language :: Python :: 3.9",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Topic :: Scientific/Engineering :: Image Processing",
|
|
31
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
dependencies = ["numpy", "scipy", "scikit-image", "opencv-python"]
|
|
35
|
+
|
|
36
|
+
# Version is automatically provided by hatch-vcs
|
|
37
|
+
dynamic = ["version"]
|
|
38
|
+
|
|
39
|
+
[project.scripts]
|
|
40
|
+
scribble-annotation-generator = "scribble_annotation_generator.cli:main"
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/alexsenden/scribble-annotation-generator"
|
|
44
|
+
Repository = "https://github.com/alexsenden/scribble-annotation-generator"
|
|
45
|
+
Issues = "https://github.com/alexsenden/scribble-annotation-generator/issues"
|
|
46
|
+
|
|
47
|
+
[tool.hatch.version]
|
|
48
|
+
source = "vcs"
|
|
49
|
+
|
|
50
|
+
[tool.hatch.build.targets.sdist]
|
|
51
|
+
include = ["scribble_annotation_generator/**", "README.md"]
|
|
52
|
+
|
|
53
|
+
[tool.hatch.build.targets.wheel]
|
|
54
|
+
include = ["scribble_annotation_generator/**"]
|
|
File without changes
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
from typing import Dict, Tuple
|
|
4
|
+
|
|
5
|
+
from scribble_annotation_generator.crop_field import (
|
|
6
|
+
NUM_SAMPLES_TO_GENERATE,
|
|
7
|
+
generate_crop_field_dataset,
|
|
8
|
+
)
|
|
9
|
+
from scribble_annotation_generator.nn import train_and_infer
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_colour_map(value: str) -> Dict[Tuple[int, int, int], int]:
|
|
13
|
+
"""Parse a colour map from an inline string or a file path."""
|
|
14
|
+
|
|
15
|
+
def _validate_rgb(rgb: Tuple[int, int, int]) -> Tuple[int, int, int]:
|
|
16
|
+
r, g, b = rgb
|
|
17
|
+
for channel in (r, g, b):
|
|
18
|
+
if channel < 0 or channel > 255:
|
|
19
|
+
raise ValueError("RGB values must be between 0 and 255")
|
|
20
|
+
return rgb
|
|
21
|
+
|
|
22
|
+
mapping: Dict[Tuple[int, int, int], int] = {}
|
|
23
|
+
|
|
24
|
+
if os.path.isfile(value):
|
|
25
|
+
with open(value, "r", encoding="utf-8") as handle:
|
|
26
|
+
for idx, line in enumerate(handle):
|
|
27
|
+
stripped = line.strip()
|
|
28
|
+
if not stripped:
|
|
29
|
+
continue
|
|
30
|
+
parts = [part.strip() for part in stripped.split(",") if part.strip()]
|
|
31
|
+
if len(parts) == 4:
|
|
32
|
+
r, g, b, cls = parts
|
|
33
|
+
elif len(parts) == 3:
|
|
34
|
+
r, g, b = parts
|
|
35
|
+
cls = idx
|
|
36
|
+
else:
|
|
37
|
+
raise ValueError(
|
|
38
|
+
"Each line in the colour map file must have 3 (RGB) or 4 (RGB,class) comma-separated values"
|
|
39
|
+
)
|
|
40
|
+
rgb = _validate_rgb((int(r), int(g), int(b)))
|
|
41
|
+
mapping[rgb] = int(cls)
|
|
42
|
+
else:
|
|
43
|
+
entries = [entry.strip() for entry in value.split(";") if entry.strip()]
|
|
44
|
+
for entry in entries:
|
|
45
|
+
if "=" in entry:
|
|
46
|
+
colour_part, class_part = entry.split("=", 1)
|
|
47
|
+
elif ":" in entry:
|
|
48
|
+
colour_part, class_part = entry.split(":", 1)
|
|
49
|
+
else:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
"Inline colour map entries must separate colour and class with '=' or ':'"
|
|
52
|
+
)
|
|
53
|
+
rgb_parts = [part.strip() for part in colour_part.split(",") if part.strip()]
|
|
54
|
+
if len(rgb_parts) != 3:
|
|
55
|
+
raise ValueError("Colours must be provided as R,G,B")
|
|
56
|
+
rgb = _validate_rgb((int(rgb_parts[0]), int(rgb_parts[1]), int(rgb_parts[2])))
|
|
57
|
+
mapping[rgb] = int(class_part.strip())
|
|
58
|
+
|
|
59
|
+
if not mapping:
|
|
60
|
+
raise ValueError("No colours were parsed for the colour map")
|
|
61
|
+
|
|
62
|
+
return mapping
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
66
|
+
parser = argparse.ArgumentParser(
|
|
67
|
+
description="Scribble Annotation Generator CLI",
|
|
68
|
+
)
|
|
69
|
+
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
70
|
+
|
|
71
|
+
crop_parser = subparsers.add_parser(
|
|
72
|
+
"crop-field", help="Generate synthetic crop field scribble images."
|
|
73
|
+
)
|
|
74
|
+
crop_parser.add_argument(
|
|
75
|
+
"--output-dir",
|
|
76
|
+
default="./local/crop_field",
|
|
77
|
+
help="Directory to write generated crop field images.",
|
|
78
|
+
)
|
|
79
|
+
crop_parser.add_argument(
|
|
80
|
+
"--num-samples",
|
|
81
|
+
type=int,
|
|
82
|
+
default=NUM_SAMPLES_TO_GENERATE,
|
|
83
|
+
help="Number of images to generate.",
|
|
84
|
+
)
|
|
85
|
+
crop_parser.add_argument(
|
|
86
|
+
"--min-rows",
|
|
87
|
+
type=int,
|
|
88
|
+
default=4,
|
|
89
|
+
help="Minimum number of crop rows per sample.",
|
|
90
|
+
)
|
|
91
|
+
crop_parser.add_argument(
|
|
92
|
+
"--max-rows",
|
|
93
|
+
type=int,
|
|
94
|
+
default=6,
|
|
95
|
+
help="Maximum number of crop rows per sample.",
|
|
96
|
+
)
|
|
97
|
+
crop_parser.add_argument(
|
|
98
|
+
"--colour-map",
|
|
99
|
+
required=True,
|
|
100
|
+
help=(
|
|
101
|
+
"Colour map specified inline as 'R,G,B=class;...' or a path to a file "
|
|
102
|
+
"with one 'R,G,B,class' entry per line."
|
|
103
|
+
),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
train_parser = subparsers.add_parser(
|
|
107
|
+
"train-nn", help="Train the scribble object generator and run inference."
|
|
108
|
+
)
|
|
109
|
+
train_parser.add_argument(
|
|
110
|
+
"--train-dir",
|
|
111
|
+
required=True,
|
|
112
|
+
help="Path to the training dataset directory.",
|
|
113
|
+
)
|
|
114
|
+
train_parser.add_argument(
|
|
115
|
+
"--val-dir",
|
|
116
|
+
required=True,
|
|
117
|
+
help="Path to the validation dataset directory.",
|
|
118
|
+
)
|
|
119
|
+
train_parser.add_argument(
|
|
120
|
+
"--checkpoint-dir",
|
|
121
|
+
default="./local/nn-checkpoints",
|
|
122
|
+
help="Directory to save model checkpoints.",
|
|
123
|
+
)
|
|
124
|
+
train_parser.add_argument(
|
|
125
|
+
"--inference-dir",
|
|
126
|
+
default="./local/nn-inference",
|
|
127
|
+
help="Directory to save inference visualisations.",
|
|
128
|
+
)
|
|
129
|
+
train_parser.add_argument(
|
|
130
|
+
"--batch-size",
|
|
131
|
+
type=int,
|
|
132
|
+
default=8,
|
|
133
|
+
help="Batch size for training.",
|
|
134
|
+
)
|
|
135
|
+
train_parser.add_argument(
|
|
136
|
+
"--num-workers",
|
|
137
|
+
type=int,
|
|
138
|
+
default=4,
|
|
139
|
+
help="Number of worker processes for data loading.",
|
|
140
|
+
)
|
|
141
|
+
train_parser.add_argument(
|
|
142
|
+
"--max-epochs",
|
|
143
|
+
type=int,
|
|
144
|
+
default=50,
|
|
145
|
+
help="Maximum number of training epochs.",
|
|
146
|
+
)
|
|
147
|
+
train_parser.add_argument(
|
|
148
|
+
"--num-classes",
|
|
149
|
+
type=int,
|
|
150
|
+
default=None,
|
|
151
|
+
help="Override the number of classes; defaults to the number of unique class IDs in the colour map.",
|
|
152
|
+
)
|
|
153
|
+
train_parser.add_argument(
|
|
154
|
+
"--colour-map",
|
|
155
|
+
required=True,
|
|
156
|
+
help=(
|
|
157
|
+
"Colour map specified inline as 'R,G,B=class;...' or a path to a file "
|
|
158
|
+
"with one 'R,G,B,class' entry per line."
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
return parser
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def main(argv=None):
|
|
166
|
+
parser = build_parser()
|
|
167
|
+
args = parser.parse_args(argv)
|
|
168
|
+
colour_map = parse_colour_map(args.colour_map)
|
|
169
|
+
|
|
170
|
+
if args.command == "crop-field":
|
|
171
|
+
generate_crop_field_dataset(
|
|
172
|
+
output_dir=args.output_dir,
|
|
173
|
+
colour_map=colour_map,
|
|
174
|
+
num_samples=args.num_samples,
|
|
175
|
+
min_rows=args.min_rows,
|
|
176
|
+
max_rows=args.max_rows,
|
|
177
|
+
)
|
|
178
|
+
elif args.command == "train-nn":
|
|
179
|
+
train_and_infer(
|
|
180
|
+
train_dir=args.train_dir,
|
|
181
|
+
val_dir=args.val_dir,
|
|
182
|
+
colour_map=colour_map,
|
|
183
|
+
checkpoint_dir=args.checkpoint_dir,
|
|
184
|
+
inference_dir=args.inference_dir,
|
|
185
|
+
batch_size=args.batch_size,
|
|
186
|
+
num_workers=args.num_workers,
|
|
187
|
+
max_epochs=args.max_epochs,
|
|
188
|
+
num_classes=args.num_classes,
|
|
189
|
+
)
|
|
190
|
+
else:
|
|
191
|
+
parser.error("A subcommand is required.")
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
if __name__ == "__main__":
|
|
195
|
+
main()
|