geowatch.cli.reproject_annotations module¶

Projects annotations from geojson files onto a kwcoco file.

This finds geojson regions that spatially overlap geo-registered kwcoco videos and then projects the CRS84 geojson annotations into image-space annotations for the assigned video. Tracked annotations in the geojson files are treated as keyframes and propogated across time based on the propogate_strategy argument.

CommandLine

# Update a dataset with new annotations
DVC_DATA_DPATH=$(geowatch_dvc --tags='phase2_data' --hardware=auto)

# You dont need to run this, but if you plan on running the reproject
# annotations script multiple times, preloading this work will make it
# faster
python -m geowatch add_fields \
    --src $DVC_DATA_DPATH/Drop6/data.kwcoco.json \
    --dst $DVC_DATA_DPATH/Drop6/data.kwcoco.json \
    --overwrite=warp --workers 10

# Update to whatever the state of the annotations submodule is.  The
# viz_dpath argument can be specified to visualize the algorithm details.
python -m geowatch reproject_annotations \
    --src $DVC_DATA_DPATH/Drop6/data.kwcoco.json \
    --dst $DVC_DATA_DPATH/Drop6/data.kwcoco.json \
    --viz_dpath $DVC_DATA_DPATH/Drop6/_viz_propogate \
    --site_models="$DVC_DATA_DPATH/annotations/drop6/site_models/*.geojson"

# Finally we can review the polygons.
python -m geowatch visualize \
    --src $DVC_DATA_DPATH/Drop6/data.kwcoco.json \
    --space="video" \
    --num_workers=avail \
    --any3="only" --draw_anns=True --draw_imgs=False --animate=True

Notes

To add iMerit regions, we will need to recognize site-summaries from region models instead of site-models themselves. Code to do this is in:

in add_site_summary_to_kwcoco.

Todo

  • [ ] use the new proper kwcoco track ids.

class geowatch.cli.reproject_annotations.ReprojectAnnotationsConfig(*args, **kwargs)[source]¶

Bases: DataConfig

Warp annotations from geospace onto kwcoco pixel space.

This also propogates track information across time in video datasets.

References

https://smartgitlab.com/TE/annotations/-/wikis/Alternate-Site-Type

The following is example usage in bash

DVC_DATA_DPATH=$(geowatch_dvc --tags='phase2_data' --hardware=auto)
geowatch reproject_annotations \
    --src $DVC_DATA_DPATH/Drop6/data.kwcoco.json \
    --dst $DVC_DATA_DPATH/Drop6/data.kwcoco.json \
    --region_models="$DVC_DATA_DPATH/annotations/drop6_hard_v1/region_models/*.geojson" \
    --site_models="$DVC_DATA_DPATH/annotations/drop6_hard_v1/site_models/*.geojson"

And equivalent usage in Python

from geowatch.cli import reproject_annotations
import geowatch
dvc_data_dpath = geowatch.find_dvc_dpath(tags='phase2_data', hardware='auto')
# Note that every CLI argument has a corresponding key/value argument
kwargs = {
    'src': dvc_data_dpath / 'Drop6/data.kwcoco.json',
    'dst': dvc_data_dpath / 'Drop6/data.kwcoco.json',
    'region_models': dvc_data_dpath / 'annotations/drop6_hard_v1/region_models/*.geojson',
    'site_models': dvc_data_dpath / 'annotations/drop6_hard_v1/site_models/*.geojson',
}
reproject_annotations.main(cmdline=False, **kwargs)

Valid options: []

Parameters:
  • *args – positional arguments for this data config

  • **kwargs – keyword arguments for this data config

default = {'clear_existing': <Value(True)>, 'dst': <Value(None)>, 'geo_preprop': <Value('auto')>, 'geospace_lookup': <Value('auto')>, 'ignore_system_rejected': <Value(True)>, 'inplace': <Value(False)>, 'io_workers': <Value('auto')>, 'propogate_strategy': <Value('NEW-SMART')>, 'region_models': <Value(None)>, 'role': <Value(None)>, 'site_models': <Value(None)>, 'src': <Value(None)>, 'status_to_catname': <Value(None)>, 'validate_checks': <Value(True)>, 'verbose': <Value(1)>, 'viz_dpath': <Value(None)>, 'workers': <Value(0)>}¶
main(**kwargs)¶

CommandLine

xdoctest -m /home/joncrall/code/watch/geowatch/cli/reproject_annotations.py main
HAS_DVC=1 xdoctest -m geowatch.cli.reproject_annotations main

Example

>>> from geowatch.cli import reproject_annotations
>>> from geowatch.demo import smart_kwcoco_demodata
>>> import ubelt as ub
>>> dpath = ub.Path.appdir('geowatch/tests/reproject/doctest0')
>>> dpath.delete()
>>> coco_dset, region_dpath, site_dpath = smart_kwcoco_demodata.demo_dataset_with_regions_and_sites(dpath)
>>> coco_fpath = coco_dset.fpath
>>> cmdline = False
>>> output_fpath = dpath / 'test_project_data.kwcoco.json'
>>> viz_dpath = (dpath / 'viz').ensuredir()
>>> kwargs = {
>>>     'src': coco_fpath,
>>>     'dst': output_fpath,
>>>     'viz_dpath': viz_dpath,
>>>     'workers': 4,
>>>     'io_workers': 8,
>>>     'clear_existing': True,
>>>     'site_models': site_dpath,
>>>     'region_models': region_dpath,
>>> }
>>> reproject_annotations.main(cmdline=cmdline, **kwargs)
>>> import kwcoco
>>> output_dset = kwcoco.CocoDataset(output_fpath)
>>> num_tracks_out = len(set(output_dset.annots().lookup('track_id')))
>>> assert len(site_dpath.ls()) == num_tracks_out

Example

>>> # xdoctest: +REQUIRES(env:HAS_DVC)
>>> from geowatch.cli.reproject_annotations import *  # NOQA
>>> import geowatch
>>> dvc_dpath = geowatch.find_dvc_dpath(tags='phase2_data', hardware='auto')
>>> coco_fpath = dvc_dpath / 'Drop6/imgonly-KR_R001.kwcoco.json'
>>> dpath = ub.Path.appdir('geowatch/tests/project_annots').ensuredir()
>>> cmdline = False
>>> output_fpath = dpath / 'test_project_data.kwcoco.json'
>>> viz_dpath = (dpath / 'viz').ensuredir()
>>> kwargs = {
>>>     'src': coco_fpath,
>>>     'dst': output_fpath,
>>>     'viz_dpath': viz_dpath,
>>>     'workers': 4,
>>>     'io_workers': 8,
>>>     'site_models': dvc_dpath / 'annotations/drop6/site_models/KR_R001*',
>>>     'region_models': dvc_dpath / 'annotations/drop6/region_models/KR_R001*',
>>> }
>>> import kwplot
>>> kwplot.autoplt()  # For interactive viewing
>>> main(cmdline=cmdline, **kwargs)
normalize()¶
geowatch.cli.reproject_annotations.main(cmdline=False, **kwargs)[source]¶

CommandLine

xdoctest -m /home/joncrall/code/watch/geowatch/cli/reproject_annotations.py main
HAS_DVC=1 xdoctest -m geowatch.cli.reproject_annotations main

Example

>>> from geowatch.cli import reproject_annotations
>>> from geowatch.demo import smart_kwcoco_demodata
>>> import ubelt as ub
>>> dpath = ub.Path.appdir('geowatch/tests/reproject/doctest0')
>>> dpath.delete()
>>> coco_dset, region_dpath, site_dpath = smart_kwcoco_demodata.demo_dataset_with_regions_and_sites(dpath)
>>> coco_fpath = coco_dset.fpath
>>> cmdline = False
>>> output_fpath = dpath / 'test_project_data.kwcoco.json'
>>> viz_dpath = (dpath / 'viz').ensuredir()
>>> kwargs = {
>>>     'src': coco_fpath,
>>>     'dst': output_fpath,
>>>     'viz_dpath': viz_dpath,
>>>     'workers': 4,
>>>     'io_workers': 8,
>>>     'clear_existing': True,
>>>     'site_models': site_dpath,
>>>     'region_models': region_dpath,
>>> }
>>> reproject_annotations.main(cmdline=cmdline, **kwargs)
>>> import kwcoco
>>> output_dset = kwcoco.CocoDataset(output_fpath)
>>> num_tracks_out = len(set(output_dset.annots().lookup('track_id')))
>>> assert len(site_dpath.ls()) == num_tracks_out

Example

>>> # xdoctest: +REQUIRES(env:HAS_DVC)
>>> from geowatch.cli.reproject_annotations import *  # NOQA
>>> import geowatch
>>> dvc_dpath = geowatch.find_dvc_dpath(tags='phase2_data', hardware='auto')
>>> coco_fpath = dvc_dpath / 'Drop6/imgonly-KR_R001.kwcoco.json'
>>> dpath = ub.Path.appdir('geowatch/tests/project_annots').ensuredir()
>>> cmdline = False
>>> output_fpath = dpath / 'test_project_data.kwcoco.json'
>>> viz_dpath = (dpath / 'viz').ensuredir()
>>> kwargs = {
>>>     'src': coco_fpath,
>>>     'dst': output_fpath,
>>>     'viz_dpath': viz_dpath,
>>>     'workers': 4,
>>>     'io_workers': 8,
>>>     'site_models': dvc_dpath / 'annotations/drop6/site_models/KR_R001*',
>>>     'region_models': dvc_dpath / 'annotations/drop6/region_models/KR_R001*',
>>> }
>>> import kwplot
>>> kwplot.autoplt()  # For interactive viewing
>>> main(cmdline=cmdline, **kwargs)
geowatch.cli.reproject_annotations.check_sitemodel_assumptions(sites)[source]¶

For debugging and checking assumptions about site models

geowatch.cli.reproject_annotations.separate_region_model_types(regions)[source]¶

Break a region model into its site-summaries and header

Split up each region model into its region info and site summary info

geowatch.cli.reproject_annotations.expand_site_models_with_site_summaries(sites, regions, validate_checks=True)[source]¶

Take all site summaries from region models that do not have a corresponding site model and makes a “pseudo-site-model” for use in BAS.

Parameters:
  • sites (List[GeoDataFrame])

  • regions (List[GeoDataFrame])

Returns:

region_id_to_sites :

a mapping from region names to a list of site models both real and/or pseudo.

Return type:

Dict[str, List[DataFrame]]

geowatch.cli.reproject_annotations.make_pseudo_sitemodels(region_row, sitesummaries)[source]¶

In the case that only site sumaries are provided, this creates a dummy site model so it can follow the same codepath in keyframe propogation.

geowatch.cli.reproject_annotations.validate_site_dataframe(site_df)[source]¶

Debugging tool to ensure our assumptions about site models are satisfied.

geowatch.cli.reproject_annotations.assign_sites_to_images(coco_dset, region_id_to_sites, propogate_strategy, geospace_lookup='auto', want_viz=1, status_to_catname=None, ignore_system_rejected=True)[source]¶

Given a coco dataset (with geo information) and a list of geojson sites, determines which images each site-annotations should go on.

Parameters:
  • coco_dset (kwcoco.CocoDataset)

  • region_id_to_sites (Dict[str, List[DataFrame]])

  • propogate_strategy – (str): a code that describes how we are going to past/future propogate

  • geospace_lookup – (str):

  • want_viz (bool)

Returns:

A tuple: propogated_annotations, all_drawable_infos

Return type:

Tuple[List[Dict[str, Any]], Dict[str, Any]]

geowatch.cli.reproject_annotations.propogate_site(coco_dset, site_gdf, subimg_df, propogate_strategy, region_image_dates, region_image_indexes, region_gids, status_to_color, want_viz, status_to_catname, ignore_system_rejected)[source]¶

Given a set of site observations determines how to propogate them onto potential images in the assigned region.

geowatch.cli.reproject_annotations.keyframe_interpolate(image_times, key_infos)[source]¶

New method for keyframe interapolation.

Given a set of image times and a set of key frames with information on how they propogate, determine which keyframes are assigned to which images.

Not yet used for the SMART method, but could be in the future. The keyframe propogation behavior is also currently very simple and may be expanded in the future.

Parameters:
  • image_times (ndarray) – contains just the times of the underying images we will associate with the keyframes.

  • key_infos (Dict) – contains each keyframe time and information about its behavior.

Returns:

a list of associated image indexes for each key frame.

Return type:

List[List]

Example

>>> from geowatch.cli.reproject_annotations import *  # NOQA
>>> import numpy as np
>>> image_times = np.array([1, 2, 3, 4, 5, 6, 7])
>>> # TODO: likely also needs a range for a maximum amount of time you will
>>> # apply the observation for.
>>> key_infos = [
>>>     {'time': 1.2, 'applies': 'future'},
>>>     {'time': 3.4, 'applies': 'both'},
>>>     {'time': 6, 'applies': 'past'},
>>>     {'time': 9, 'applies': 'past'},
>>> ]
>>> key_assignment = keyframe_interpolate(image_times, key_infos)
>>> # xdoctest: +REQUIRES(--show)
>>> # xdoctest: +REQUIRES(module:kwplot)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.figure(fnum=1, doclf=1)
>>> key_times = [d['time'] for d in key_infos]
>>> key_times = np.array(key_times)
>>> plot_poc_keyframe_interpolate(image_times, key_times, key_assignment)

Example

>>> from geowatch.cli.reproject_annotations import *  # NOQA
>>> import numpy as np
>>> image_times = np.array([1, 2, 3, 4, 5, 6, 7])
>>> # TODO: likely also needs a range for a maximum amount of time you will
>>> # apply the observation for.
>>> key_infos = [
>>>     {'time': 1.2, 'applies': 'future', 'max_frames': 1},
>>>     {'time': 3.2, 'applies': 'future'},
>>>     {'time': 6, 'applies': 'future', 'max_frames': 1},
>>> ]
>>> key_assignment = keyframe_interpolate(image_times, key_infos)
>>> # xdoctest: +REQUIRES(--show)
>>> # xdoctest: +REQUIRES(module:kwplot)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.figure(fnum=1, doclf=1)
>>> key_times = [d['time'] for d in key_infos]
>>> key_times = np.array(key_times)
>>> plot_poc_keyframe_interpolate(image_times, key_times, key_assignment)
geowatch.cli.reproject_annotations.plot_poc_keyframe_interpolate(image_times, key_times, key_assignment)[source]¶

Helper to visualize the keyframe interpolation algorithm.

geowatch.cli.reproject_annotations.plot_image_and_site_times(coco_dset, region_image_dates, drawable_region_sites, region_id, ax=None)[source]¶

See [HandleDates]

References

geowatch.cli.reproject_annotations.draw_geospace(dvc_dpath, sites)[source]¶

Developer function

geowatch.cli.reproject_annotations.is_nonish(x)[source]¶