Skip to content

Typer CLI

add

add(
    image_path,
    labels_path,
    json_path,
    output_dir,
    width,
    height,
    id_attribute=None,
    name_attribute=None,
    super_attribute=None,
)

Transform and add GIS annotations to an existing CocoDataset

This method generates a COCO dataset by moving across the given image (image_path) with a moving window (image_size), constantly checking for intersecting annotations (labels_path) that represent image objects in said image (e.g. buildings in satellite imagery; denoted by (super)category name and/or id). Each valid intersection will add n Annotations entries to the dataset (json_path) and save a subset of the input image that contained these entries (output_dir).

The output data size depends on your input labels, as the moving window adjusts its step size to accommodate the average annotation size, optimizing dataset representation and minimizing tool configuration. Each addition will also increment the dataset version: patch if using the same image_path, minor if using a new image_path, and major if using a new output_dir.

Source code in geococo\cli.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
@app.command()
def add(
    image_path: Annotated[
        pathlib.Path,
        typer.Argument(
            help="Path to geospatial image containing image objects",
            exists=True,
            readable=True,
            resolve_path=True,
        ),
    ],
    labels_path: Annotated[
        pathlib.Path,
        typer.Argument(
            help="Path to vector file containing annotated image objects",
            exists=True,
            readable=True,
            resolve_path=True,
        ),
    ],
    json_path: Annotated[
        pathlib.Path,
        typer.Argument(
            help="Path to json file containing the COCO dataset",
            exists=True,
            readable=True,
            resolve_path=True,
        ),
    ],
    output_dir: Annotated[
        pathlib.Path,
        typer.Argument(
            help="Path to output directory for image subsets",
            exists=True,
            readable=True,
            resolve_path=True,
        ),
    ],
    width: Annotated[int, typer.Argument(help="Width of image subsets")],
    height: Annotated[int, typer.Argument(help="Height of image subsets")],
    id_attribute: Annotated[
        Optional[str],
        typer.Option(
            help="Name of column containing category_id values "
            "(optional if --name_attribute is given)"
        ),
    ] = None,
    name_attribute: Annotated[
        Optional[str],
        typer.Option(
            help="Name of column containing category_name values "
            "(optional if --id_attribute is given)"
        ),
    ] = None,
    super_attribute: Annotated[
        Optional[str],
        typer.Option(help="Name of column containing supercategory values"),
    ] = None,
) -> None:
    """Transform and add GIS annotations to an existing CocoDataset

    This method generates a COCO dataset by moving across the given image (image_path)
    with a moving window (image_size), constantly checking for intersecting annotations
    (labels_path) that represent image objects in said image (e.g. buildings in
    satellite imagery; denoted by (super)category name and/or id). Each valid
    intersection will add n Annotations entries to the dataset (json_path) and save a
    subset of the input image that contained these entries (output_dir).

    The output data size depends on your input labels, as the moving window adjusts its
    step size to accommodate the average annotation size, optimizing dataset
    representation and minimizing tool configuration. Each addition will also increment
    the dataset version: patch if using the same image_path, minor if using a new
    image_path, and major if using a new output_dir.
    """

    # Loading CocoDataset model from json_path
    dataset = load_dataset(json_path=json_path)

    # Loading GIS data
    labels = gpd.read_file(labels_path)
    with rasterio.open(image_path) as src:
        # Find and save all Annotation instances
        dataset = append_dataset(
            dataset=dataset,
            images_dir=output_dir,
            src=src,
            labels=labels,
            window_bounds=[(width, height)],
            id_attribute=id_attribute,
            name_attribute=name_attribute,
            super_attribute=super_attribute,
        )

    # Encode CocoDataset instance as JSON and save to json_path
    save_dataset(dataset=dataset, json_path=json_path)

copy

copy(source_json, dest_json, update_meta=True)

Copy and (optionally) update the metadata of an existing CocoDataset

Source code in geococo\cli.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
@app.command()
def copy(
    source_json: Annotated[
        pathlib.Path,
        typer.Argument(
            help="Path to source CocoDataset",
            exists=True,
            readable=True,
            resolve_path=True,
        ),
    ],
    dest_json: Annotated[
        pathlib.Path,
        typer.Argument(
            help="Output path for copied CocoDataset",
            exists=True,
            readable=True,
            resolve_path=True,
        ),
    ],
    update_meta: Annotated[
        bool,
        typer.Option(help="Whether to prompt the user for new metadata"),
    ] = True,
) -> None:
    """Copy and (optionally) update the metadata of an existing CocoDataset"""

    # Loading CocoDataset model from json_path
    dataset = load_dataset(json_path=source_json)

    if update_meta:
        print("Updating metadata..")
        dataset.info.version = (
            input(f"Dataset version ({dataset.info.version}): ") or dataset.info.version
        )
        dataset.info.description = input(
            f"Dataset description ({dataset.info.description}): "
            or dataset.info.description
        )
        dataset.info.contributor = input(
            f"Dataset contributor ({dataset.info.contributor}): "
            or dataset.info.contributor
        )
        dataset.info.date_created = datetime.now()
        print(f"Dataset date: {dataset.info.date_created}")
        dataset.info.year = dataset.info.date_created.year

    # Encode CocoDataset instance as JSON and save to json_path
    save_dataset(dataset=dataset, json_path=dest_json)
    print(f"Copied CocoDataset to {dest_json}")

new

new(json_path)

Initialize a new CocoDataset with user-prompted metadata

Source code in geococo\cli.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@app.command()
def new(
    json_path: Annotated[
        pathlib.Path,
        typer.Argument(
            help="Output path for new CocoDataset",
            exists=False,
            file_okay=True,
            writable=True,
            resolve_path=True,
        ),
    ]
) -> None:
    """Initialize a new CocoDataset with user-prompted metadata"""

    print("Creating new dataset..")
    description = input("Dataset description: ")
    contributor = input("Dataset contributor: ")

    dataset = create_dataset(
        description=description,
        contributor=contributor,
    )

    # Encode CocoDataset instance as JSON and save to json_path
    save_dataset(dataset=dataset, json_path=json_path)
    print(f"Created new CocoDataset as {json_path}")