Skip to content

Commit

Permalink
feat: Add new --footprint-type geojson/csv option to export footpri…
Browse files Browse the repository at this point in the history
…nts as CSV (#51)
  • Loading branch information
munshkr authored Sep 18, 2024
1 parent f08affc commit 8a1e3a5
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 15 deletions.
53 changes: 39 additions & 14 deletions satproc/chips.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
prepare_label_shapes,
write_window_masks,
)
from satproc.utils import rescale_intensity, sliding_windows, write_chips_geojson
from satproc.utils import (
rescale_intensity,
sliding_windows,
write_chips_geojson,
write_chips_csv,
)

__author__ = "Damián Silvani"
__copyright__ = "Dymaxion Labs"
Expand All @@ -40,6 +45,7 @@ def extract_chips(
bands=None,
chip_type="tif",
write_footprints=False,
footprints_type="geojson",
classes=None,
crs=None,
skip_existing=True,
Expand Down Expand Up @@ -85,6 +91,7 @@ def extract_chips(
chip_type=chip_type,
within=within,
write_footprints=write_footprints,
footprints_type=footprints_type,
crs=crs,
labels=labels,
label_property=label_property,
Expand All @@ -108,6 +115,7 @@ def extract_chips_from_raster(
bands=None,
chip_type="tif",
write_footprints=False,
footprints_type="geojson",
labels=None,
label_property="class",
mask_type="class",
Expand Down Expand Up @@ -159,10 +167,12 @@ def extract_chips_from_raster(
if bands is None:
bands = list(range(1, min(ds.count, 3) + 1))

_logger.info((
f"Building windows of size {size}, step size {step_size}"
f"{' (no overlap)' if step_size >= size else ''}"
))
_logger.info(
(
f"Building windows of size {size}, step size {step_size}"
f"{' (no overlap)' if step_size >= size else ''}"
)
)
win_size = (size, size)
win_step_size = (step_size, step_size)
windows = list(
Expand Down Expand Up @@ -277,15 +287,30 @@ def filter_fn(w, aoi):
)

if write_footprints:
geojson_path = os.path.join(output_dir, "{}.geojson".format(basename))
_logger.info("Write chips footprints GeoJSON at %s", geojson_path)
write_chips_geojson(
geojson_path,
chips,
chip_type=chip_type,
crs=str(meta["crs"]),
basename=basename,
)
if footprints_type == "geojson":
if not meta["crs"]:
_logger.error("No CRS found, cannot write GeoJSON footprints")
else:
geojson_path = os.path.join(
output_dir, "{}.geojson".format(basename)
)
_logger.info("Write chips footprints GeoJSON at %s", geojson_path)
write_chips_geojson(
geojson_path,
chips,
chip_type=chip_type,
crs=str(meta["crs"]),
basename=basename,
)
elif footprints_type == "csv":
csv_path = os.path.join(output_dir, "{}.csv".format(basename))
_logger.info("Write chips footprints CSV at %s", csv_path)
write_chips_csv(
csv_path,
chips,
chip_type=chip_type,
basename=basename,
)


def write_image(img, path, *, percentiles=None, skip_low_contrast=False):
Expand Down
12 changes: 11 additions & 1 deletion satproc/console/extract_chips.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ def parse_args(args):
"--size", type=int, default=256, help="size of image tiles, in pixels"
)
parser.add_argument(
"--step-size", type=int, default=None, help="step size (i.e. stride), in pixels (if None, same as size i.e. no overlap)"
"--step-size",
type=int,
default=None,
help="step size (i.e. stride), in pixels (if None, same as size i.e. no overlap)",
)
parser.add_argument(
"--sliding-windows-mode",
Expand Down Expand Up @@ -165,6 +168,12 @@ def parse_args(args):
dest="write_footprints",
action="store_false",
)
parser.add_argument(
"--footprints-type",
help="footprints file format",
choices=["geojson", "csv"],
default="geojson",
)

parser.add_argument("--crs", help="force CRS of input files")

Expand Down Expand Up @@ -303,6 +312,7 @@ def main(args):
chip_type=args.type,
within=args.within,
write_footprints=args.write_footprints,
footprints_type=args.footprints_type,
classes=args.classes,
crs=args.crs,
skip_existing=args.skip_existing,
Expand Down
37 changes: 37 additions & 0 deletions satproc/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import csv
import json
import logging
import multiprocessing as mp
Expand Down Expand Up @@ -184,6 +185,42 @@ def write_chips_geojson(output_path, chip_pairs, *, chip_type, crs, basename):
f.write(json.dumps(d))


def write_chips_csv(output_path, chip_pairs, *, chip_type, basename):
"""Write a CSV containing chips polygons as features
Parameters
----------
output_path : str
CSV output path
chip_pairs : Tuple[Shape, Tuple[int, int, int]]
a pair with the chip polygon geometry, and a tuple of (feature id, x, y)
chip_type : str
chip file type extension (e.g. tif, jpg)
basename : str
basename of chip files
Returns
-------
None
"""
if not chip_pairs:
_logger.warn("No chips to save")
return

_logger.info("Write chips CSV")
os.makedirs(os.path.dirname(output_path), exist_ok=True)

header = ["id", "x", "y", "minx", "miny", "maxx", "maxy", "filename"]
with open(output_path, "w") as f:
writer = csv.writer(f)
writer.writerow(header)
for i, (chip, (_fi, xi, yi)) in enumerate(chip_pairs):
minx, miny, maxx, maxy = chip.bounds
filename = f"{basename}_{xi}_{yi}.{chip_type}"
writer.writerow([i, xi, yi, minx, miny, maxx, maxy, filename])


def get_raster_band_count(path):
"""Get raster band count
Expand Down

0 comments on commit 8a1e3a5

Please sign in to comment.