geowatch.utils.kwcoco_extensions module¶
Adds fields needed by ndsampler to correctly “watch” a region.
Some of this is done hueristically. We assume images come from certain sensors. We assume input is orthorectified. We assume some GSD “target” gsd for video and image processing. Note a video GSD will typically be much higher (i.e. lower resolution) than an image GSD.
- geowatch.utils.kwcoco_extensions.filter_image_ids(coco_dset, gids=None, include_sensors=None, exclude_sensors=None, select_images=None, select_videos=None)[source]¶
Filters to a specific set of images given query parameters
- geowatch.utils.kwcoco_extensions.populate_watch_fields(coco_dset, target_gsd=10.0, vidids=None, overwrite=False, default_gsd=None, conform=True, enable_video_stats=True, enable_valid_region=False, enable_intensity_stats=False, workers=0, mode='thread', remove_broken=False, skip_populate_errors=False)[source]¶
Aggregate populate function for fields useful to GeoWATCH.
- Parameters:
coco_dset (Dataset) – dataset to work with
target_gsd (float) – target gsd in meters
overwrite (bool | List[str]) – if True or False overwrites everything or nothing. Otherwise it can be a list of strings indicating what is overwritten. Valid keys are warp, band, and channels.
default_gsd (None | float) – if specified, assumed any images without geo-metadata have this GSD’
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import kwcoco >>> # TODO: make a demo dataset with some sort of gsd metadata >>> coco_dset = kwcoco.CocoDataset.demo('vidshapes8-multispectral') >>> print('coco_dset = {!r}'.format(coco_dset)) >>> target_gsd = 13.0 >>> populate_watch_fields(coco_dset, target_gsd, default_gsd=1) >>> print('coco_dset.index.imgs[1] = ' + ub.urepr(coco_dset.index.imgs[1], nl=2)) >>> print('coco_dset.index.videos = {}'.format(ub.urepr(coco_dset.index.videos, nl=1)))
>>> # TODO: make a demo dataset with some sort of gsd metadata >>> coco_dset = kwcoco.CocoDataset.demo('vidshapes8') >>> print('coco_dset = {!r}'.format(coco_dset)) >>> target_gsd = 13.0 >>> populate_watch_fields(coco_dset, target_gsd, default_gsd=1) >>> print('coco_dset.index.imgs[1] = ' + ub.urepr(coco_dset.index.imgs[1], nl=2)) >>> print('coco_dset.index.videos = {}'.format(ub.urepr(coco_dset.index.videos, nl=1)))
- geowatch.utils.kwcoco_extensions.coco_populate_geo_heuristics(coco_dset: CocoDataset, gids=None, overwrite=False, default_gsd=None, workers=0, mode='thread', remove_broken=False, **kw)[source]¶
Example
>>> # xdoctest: +REQUIRES(env:DVC_DPATH) >>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> from geowatch.utils.util_data import find_dvc_dpath >>> import kwcoco >>> dvc_dpath = find_dvc_dpath() >>> coco_fpath = dvc_dpath / 'drop1-S2-L8-aligned/data.kwcoco.json' >>> coco_dset = kwcoco.CocoDataset(coco_fpath) >>> coco_populate_geo_heuristics(coco_dset, overwrite=True, workers=12, >>> keep_geotiff_metadata=False, >>> mode='process')
Example
>>> # xdoctest: +REQUIRES(env:DVC_DPATH) >>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> from geowatch.utils.util_data import find_dvc_dpath >>> import kwcoco >>> dvc_dpath = find_dvc_dpath() >>> coco_fpath = dvc_dpath / 'drop1-S2-L8-aligned/data.kwcoco.json' >>> coco_dset = kwcoco.CocoDataset(coco_fpath) >>> coco_populate_geo_heuristics(coco_dset, overwrite=True, workers=12, >>> keep_geotiff_metadata=False, >>> mode='process')
- geowatch.utils.kwcoco_extensions.coco_populate_geo_img_heuristics2(coco_img, overwrite=False, default_gsd=None, keep_geotiff_metadata=False, enable_intensity_stats=False, enable_valid_region=False, skip_populate_errors=False)[source]¶
Note: this will not overwrite existing channel info unless specified
- Commandline
xdoctest -m ~/code/watch/geowatch/utils/kwcoco_extensions.py –profile
Todo
- [ ] Use logic in the align demo classmethod to make an example
that uses a real L8 / S2 image.
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import geowatch >>> import json >>> coco_dset = geowatch.coerce_kwcoco('geowatch-msi-geodata-dates-heatmap-videos1-frames2-gsize64') >>> gid = 1 >>> overwrite = {'warp', 'band'} >>> default_gsd = None >>> kw = {} >>> coco_img = coco_dset.coco_image(gid) >>> before_img_attrs = list(coco_img.img.keys()) >>> before_aux_attr_hist = ub.dict_hist(ub.flatten([list(aux) for aux in coco_img.img['auxiliary']])) >>> print('before_img_attrs = {!r}'.format(before_img_attrs)) >>> print('before_aux_attr_hist = {}'.format(ub.urepr(before_aux_attr_hist, nl=1))) >>> coco_populate_geo_img_heuristics2(coco_img) >>> img = coco_dset.index.imgs[gid] >>> after_img_attrs = list(coco_img.img.keys()) >>> after_aux_attr_hist = ub.dict_hist(ub.flatten([list(aux) for aux in coco_img.img['auxiliary']])) >>> new_img_attrs = set(after_img_attrs) - set(before_img_attrs) >>> new_aux_attrs = {k: after_aux_attr_hist[k] - before_aux_attr_hist.get(k, 0) for k in after_aux_attr_hist} >>> new_aux_attrs = {k: v for k, v in new_aux_attrs.items() if v > 0} >>> print('new_img_attrs = {}'.format(ub.urepr(new_img_attrs, nl=1))) >>> print('new_aux_attrs = {}'.format(ub.urepr(new_aux_attrs, nl=1))) >>> #print('after_img_attrs = {}'.format(ub.urepr(after_img_attrs, nl=1))) >>> #print('after_aux_attr_hist = {}'.format(ub.urepr(after_aux_attr_hist, nl=1))) >>> assert 'geos_corners' in img >>> #assert 'default_nodata' in img >>> #assert 'default_nodata' in new_aux_attrs >>> print(ub.varied_values(list(map(lambda x: ub.map_vals(json.dumps, x), coco_img.img['auxiliary'])), default=None))
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import kwcoco >>> ### >>> gid = 1 >>> dset = kwcoco.CocoDataset.demo('vidshapes8-multispectral') >>> coco_img = dset.coco_image(gid) >>> coco_populate_geo_img_heuristics2(coco_img, overwrite=True) >>> ### >>> gid = 1 >>> dset2 = kwcoco.CocoDataset.demo('shapes8') >>> coco_img = dset2.coco_image(gid) >>> coco_populate_geo_img_heuristics2(coco_img, overwrite=True)
- geowatch.utils.kwcoco_extensions.coco_populate_geo_video_stats(coco_dset, video_id, target_gsd='max-resolution')[source]¶
Create a “video-space” for all images in a video sequence at a specified resolution.
For this video, this chooses the “best” image as the “video canvas / region” and registers everything to that canvas/region. This creates the “video-space” for this image sequence. Currently the “best” image is the one that has the GSD closest to the target-gsd. This hueristic works well in most cases, but no all.
Notes
Currently the “best image” exactly define the video canvas / region.
Areas where other images do not overlap the vieo canvas are effectively lost when sampling in video space, because anything outside the video canvas is cropped out.
Auxilary / asset images are required to have an “approx_meter_gsd” and a “warp_to_wld” attribute to use this function atm.
Todo
[ ] Allow choosing of a custom “video-canvas” not based on any one image.
[ ] Allow choosing a “video-canvas” that encompases all images
- [ ] Allow the base image to contain “approx_meter_gsd” /
“warp_to_wld” instead of the auxiliary image
[ ] Is computing the scale factor based on approx_meter_gsd safe?
- Parameters:
coco_dset (CocoDataset) – coco dataset to be modified inplace
video_id (int) – video_id to modify
target_gsd (float | str) – string code, or float target gsd
Example
>>> # xdoctest: +REQUIRES(env:DVC_DPATH) >>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> from geowatch.utils.util_data import find_dvc_dpath >>> import kwcoco >>> dvc_dpath = find_dvc_dpath() >>> coco_fpath = dvc_dpath / 'Drop2-Aligned-TA1-2022-02-15/data.kwcoco.json' >>> video_id = 2
>>> coco_fpath = dvc_dpath / 'Aligned-Drop2-TA1-2022-03-07/data.kwcoco.json' >>> coco_dset = kwcoco.CocoDataset(coco_fpath) >>> target_gsd = 10.0 >>> video_id = 1 >>> # We can check transforms before we apply this function >>> coco_dset.images(video_id=video_id).lookup('warp_img_to_vid', None) >>> # Apply the function >>> coco_populate_geo_video_stats(coco_dset, video_id, target_gsd) >>> # Check these transforms to make sure they look right >>> popualted_video = coco_dset.index.videos[video_id] >>> popualted_video = ub.dict_isect(popualted_video, ['width', 'height', 'warp_wld_to_vid', 'target_gsd']) >>> print('popualted_video = {}'.format(ub.urepr(popualted_video, nl=-1))) >>> coco_dset.images(video_id=video_id).lookup('warp_img_to_vid')
# TODO: make a demo dataset with some sort of gsd metadata coco_dset = kwcoco.CocoDataset.demo(‘vidshapes8-multispectral’) print(‘coco_dset = {!r}’.format(coco_dset))
coco_fpath = ub.expandpath(‘~/data/dvc-repos/smart_watch_dvc/drop0_aligned/data.kwcoco.json’) coco_fpath = ‘/home/joncrall/data/dvc-repos/smart_watch_dvc/drop1-S2-L8-aligned/combo_data.kwcoco.json’ coco_dset = kwcoco.CocoDataset(coco_fpath) video_id = 1
target_gsd = 2.8
# Check drawing the valid region on the image frac = 1
valid_regions = coco_dset.images().lookup(‘valid_region’) cands = [] for idx, valid_region in enumerate(valid_regions):
valid_region_img = kwimage.MultiPolygon.coerce(valid_region) frac = valid_region_img.to_shapely().area / valid_region_img.bounding_box().area if frac < 0.6:
cands.append(idx)
gid = coco_dset.images().take(cands).lookup(‘id’)[0]
coco_img = coco_dset.coco_image(gid) imdata = coco_img.imdelay(‘blue’).finalize(nodata=’float’) valid_region_img = kwimage.MultiPolygon.coerce(coco_img.img[‘valid_region’]) frac = valid_region_img.to_shapely().area / valid_region_img.bounding_box().area print(‘frac = {!r}’.format(frac))
canvas_imgspace = kwimage.normalize_intensity(imdata) kwplot.autompl() kwplot.imshow(canvas_imgspace, doclf=1)
valid_region_img = kwimage.MultiPolygon.coerce(coco_img.img[‘valid_region’]) canvas_imgspace = valid_region_img.draw_on(canvas_imgspace, fill=0, color=’green’) kwplot.imshow(canvas_imgspace)
# Check the nodata polygon returned raw pixel methods primary_data = kwimage.imread(primary_fpath, nodata=’float’) valid_mask = ~np.isnan(primary_data) kw_poly = kwimage.Mask(valid_mask.astype(np.uint8), ‘c_mask’).to_multi_polygon() print(‘kwimage kw_poly.data = {!r}’.format(kw_poly.data))
# CHeck the one returned by util_raster primary_fpath = coco_img.primary_image_filepath() sh_poly = util_raster.mask(
primary_fpath, tolerance=None, convex_hull=0)
kw_poly = kwimage.MultiPolygon.from_shapely(sh_poly) print(‘rasterio kw_poly.data = {!r}’.format(kw_poly.data))
- geowatch.utils.kwcoco_extensions.check_kwcoco_spatial_transforms(coco_dset)[source]¶
import kwplot kwplot.plt.ion() import kwcoco dset = kwcoco.CocoDataset(‘/home/joncrall/remote/toothbrush/data/dvc-repos/smart_data_dvc-ssd/Drop6_MeanYear/imgonly-KR_R001.kwcoco.zip’)
import geowatch data_dvc_dpath = geowatch.find_dvc_dpath(tags=’phase2_data’, hardware=’auto’) dset = kwcoco.CocoDataset(data_dvc_dpath / ‘Drop6-MeanYear10GSD/imganns-NZ_R001.kwcoco.zip’)
dset = kwcoco.CocoDataset(‘/home/joncrall/quicklinks/toothbrush_smart_expt_dvc/_debug/pred.kwcoco.zip’)
- geowatch.utils.kwcoco_extensions.check_geo_transform_consistency(coco_dset)[source]¶
Checks the consistency of transforms between world, video, image, and asset space in a coco dataset.
- geowatch.utils.kwcoco_extensions.check_unique_channel_names(coco_dset, gids=None, verbose=0)[source]¶
Check each image has unique channel names
Todo
[ ] move to kwcoco proper
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import kwcoco >>> # TODO: make a demo dataset with some sort of gsd metadata >>> coco_dset = kwcoco.CocoDataset.demo('vidshapes8-multispectral') >>> check_unique_channel_names(coco_dset) >>> # Make some duplicate channels to test >>> obj = coco_dset.images().objs[0] >>> obj['auxiliary'][0]['channels'] = 'B1|B1' >>> obj = coco_dset.images().objs[1] >>> obj['auxiliary'][0]['channels'] = 'B1|B1' >>> obj = coco_dset.images().objs[2] >>> obj['auxiliary'][1]['channels'] = 'B1' >>> import pytest >>> with pytest.raises(AssertionError): >>> check_unique_channel_names(coco_dset)
- geowatch.utils.kwcoco_extensions.coco_list_asset_infos(coco_dset)[source]¶
Get a list of filename and channels for each coco image
- geowatch.utils.kwcoco_extensions.transfer_geo_metadata(coco_dset, gid)[source]¶
Transfer geo-metadata from source geotiffs to predicted feature images
THIS FUNCITON MODIFIES THE IMAGE DATA ON DISK! BE CAREFUL!
ASSUMES THAT EVERYTHING IS ALREADY ALIGNED
Example
# xdoctest: +REQUIRES(env:DVC_DPATH) from geowatch.utils.kwcoco_extensions import * # NOQA from geowatch.utils.util_data import find_dvc_dpath import kwcoco dvc_dpath = find_dvc_dpath() coco_fpath = dvc_dpath / ‘drop1-S2-L8-aligned/combo_data.kwcoco.json’ coco_dset = kwcoco.CocoDataset(coco_fpath) gid = coco_dset.images().peek()[‘id’]
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import kwcoco >>> from geowatch.demo.smart_kwcoco_demodata import hack_seed_geometadata_in_dset >>> coco_dset = kwcoco.CocoDataset.demo('vidshapes8-multispectral') >>> hack_seed_geometadata_in_dset(coco_dset, force=True, rng=0) >>> gid = 2 >>> transfer_geo_metadata(coco_dset, gid) >>> fpath = join(coco_dset.bundle_dpath, coco_dset.coco_image(gid).primary_asset()['file_name']) >>> _ = ub.cmd('gdalinfo ' + fpath, verbose=1)
- geowatch.utils.kwcoco_extensions.transfer_geo_metadata2(coco_img, dry=0)[source]¶
Second version of this function to work in process mode
Transfer geo-metadata from source geotiffs to predicted feature images
THIS FUNCITON MODIFIES THE IMAGE DATA ON DISK! BE CAREFUL!
ASSUMES THAT EVERYTHING IS ALREADY ALIGNED
- geowatch.utils.kwcoco_extensions.coco_channel_stats(coco_dset)[source]¶
Return information about what channels are available in the dataset
Example
>>> import kwcoco >>> import ubelt as ub >>> import geowatch >>> coco_dset = geowatch.coerce_kwcoco('vidshapes-geowatch') >>> from geowatch.utils import kwcoco_extensions >>> info = kwcoco_extensions.coco_channel_stats(coco_dset) >>> print(ub.urepr(info, nl=3))
- class geowatch.utils.kwcoco_extensions.TrackidGenerator(coco_dset=None)[source]¶
Bases:
object
Keep track of which trackids have been used and generate new ones on demand
TODO merge this into kwcoco as something like CocoDataset.next_trackid()? Or expose whatever mechanism is already generating new aids, gids, etc
- geowatch.utils.kwcoco_extensions.coco_img_wld_info(coco_img)[source]¶
TODO: candidate for kwcoco.CocoImage method
- geowatch.utils.kwcoco_extensions.warp_annot_segmentations_from_geos(coco_dset)[source]¶
Uses the segmentation_geos property (which should be crs84) and warps it into image space based on available geo data.
- Parameters:
coco_dset (kwcoco.CocoDataset) – a CocoDataset where annotations contain a “segmentation_geos” attribute. The “segmentation” attribute will be modified in-place.
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import geowatch >>> # creating demodata also uses warp_annot_segmentations_to_geos >>> orig_dset = geowatch.coerce_kwcoco('geowatch-msi', geodata=True) >>> coco_dset = orig_dset.copy() >>> for ann in coco_dset.annots().objs: ... ann.pop('segmentation', None) >>> warp_annot_segmentations_from_geos(coco_dset) >>> errors = [] >>> for aid in coco_dset.annots(): >>> ann1 = orig_dset.index.anns[aid] >>> ann2 = coco_dset.index.anns[aid] >>> poly1 = kwimage.MultiPolygon.coerce(ann1['segmentation']) >>> poly2 = kwimage.MultiPolygon.coerce(ann2['segmentation']) >>> worked = (poly1.is_invalid() and poly2.is_invalid()) or poly1.iou(poly2) > 0.99 >>> errors.append(not worked) >>> if sum(errors) > 0: >>> # FIXME: THERE SHOULD BE NO ERRORS HERE. PUNTING TO MAKE >>> # THE DASHBOARDS GREEN, BUT THIS SHOULD BE REVISITED >>> #raise AssertionError('transforms should have cyclic consistency') >>> warnings.warn('Transforms should have cyclic consistency, but some dont. This should be an error, but we will allow it for now') >>> assert (sum(errors) / len(errors)) < 0.5, 'more than half of the data does not have cyclic consistency'
- geowatch.utils.kwcoco_extensions.warp_annot_segmentations_to_geos(coco_dset)[source]¶
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import geowatch >>> orig_dset = geowatch.coerce_kwcoco('geowatch-msi', geodata=True) >>> coco_dset = orig_dset.copy() >>> for ann in coco_dset.annots().objs: ... ann.pop('segmentation_geos', None) >>> warp_annot_segmentations_to_geos(coco_dset) >>> errors = [] >>> for aid in ub.ProgIter(coco_dset.annots()): >>> ann1 = orig_dset.index.anns[aid] >>> ann2 = coco_dset.index.anns[aid] >>> poly1 = kwimage.MultiPolygon.from_geojson(ann1['segmentation_geos']) >>> poly2 = kwimage.MultiPolygon.from_geojson(ann2['segmentation_geos']) >>> worked = (poly1.is_invalid() and poly2.is_invalid()) or poly1.iou(poly2) > 0.99 >>> errors.append(not worked) >>> if sum(errors) > 0: >>> # FIXME: THERE SHOULD BE NO ERRORS HERE. PUNTING TO MAKE >>> # THE DASHBOARDS GREEN, BUT THIS SHOULD BE REVISITED >>> #raise AssertionError('transforms should have cyclic consistency') >>> warnings.warn('Transforms should have cyclic consistency, but some dont. This should be an error, but we will allow it for now') >>> assert (sum(errors) / len(errors)) < 0.5, 'more than half of the data does not have cyclic consistency'
- geowatch.utils.kwcoco_extensions.visualize_rois(coco_dset, zoom=None)[source]¶
Matplotlib visualization of image and annotation regions on a world map
Example
>>> # xdoctest: +REQUIRES(--slow) >>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> from geowatch.demo.smart_kwcoco_demodata import demo_kwcoco_with_heatmaps >>> coco_dset = demo_kwcoco_with_heatmaps(num_videos=1) >>> coco_populate_geo_heuristics(coco_dset, overwrite=True) >>> visualize_rois(coco_dset, zoom=0)
Example
>>> # xdoctest: +REQUIRES(env:DVC_DPATH) >>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> from geowatch.utils.util_data import find_dvc_dpath >>> import kwcoco >>> dvc_dpath = find_dvc_dpath() >>> coco_fpath = dvc_dpath / 'drop1-S2-L8-aligned/combo_data.kwcoco.json' >>> coco_dset = kwcoco.CocoDataset(coco_fpath) >>> coco_populate_geo_heuristics(coco_dset, overwrite=True, workers=4) >>> visualize_rois(coco_dset)
- geowatch.utils.kwcoco_extensions.covered_image_geo_regions(coco_dset, merge=False)[source]¶
Find the intersection of all image bounding boxes in world space to see what spatial regions are covered by the imagery.
- Returns:
gpd.GeoDataFrame
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> from geowatch.demo.smart_kwcoco_demodata import demo_kwcoco_with_heatmaps >>> coco_dset = demo_kwcoco_with_heatmaps(num_frames=1, num_videos=1) >>> coco_populate_geo_heuristics(coco_dset, overwrite=True) >>> img = coco_dset.index.imgs[1] >>> cov_image_gdf = covered_image_geo_regions(coco_dset)
Example
>>> # Check it works with empty data frame >>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> coco_dset = kwcoco.CocoDataset() >>> cov_image_gdf1 = covered_image_geo_regions(coco_dset, merge=False) >>> cov_image_gdf2 = covered_image_geo_regions(coco_dset, merge=True) >>> assert len(cov_image_gdf1) == 0 >>> assert len(cov_image_gdf2) == 0
- geowatch.utils.kwcoco_extensions.covered_video_geo_regions(coco_dset)[source]¶
Compute CRS84 bounds for each video in the coco dataset.
- Returns:
gpd.GeoDataFrame
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> from geowatch.demo.smart_kwcoco_demodata import demo_kwcoco_with_heatmaps >>> coco_dset = demo_kwcoco_with_heatmaps(num_frames=1, num_videos=1) >>> # coco_populate_geo_heuristics(coco_dset, overwrite=True) >>> # video_gdf = covered_video_geo_regions(coco_dset)
- geowatch.utils.kwcoco_extensions.covered_annot_geo_regions(coco_dset, merge=False)[source]¶
Given a dataset find spatial regions of interest that contain annotations
- geowatch.utils.kwcoco_extensions.associate_images(dset1, dset2, key_fallback=None)[source]¶
Builds an association between image-ids in two datasets.
One use for this is if
dset1
is a truth dataset anddset2
is a prediction dataset, and you need the to know which images are in common so they can be scored.- Parameters:
dset1 (kwcoco.CocoDataset) – a kwcoco datset.
dset2 (kwcoco.CocoDataset) – another kwcoco dataset
key_fallback (str) – The fallback key to use if the image “name” is not specified. This can either be “file_name” or “id” or None.
Todo
[ ] port to kwcoco proper
[ ] use in kwcoco eval as a robust image/video association method
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import kwcoco >>> from kwcoco.demo.perterb import perterb_coco >>> dset1 = kwcoco.CocoDataset.demo('shapes2') >>> kwargs = { >>> 'box_noise': 0.5, >>> 'n_fp': (0, 10), >>> 'n_fn': (0, 10), >>> } >>> dset2 = perterb_coco(dset1, **kwargs) >>> matches = associate_images(dset1, dset2, key_fallback='file_name') >>> assert len(matches['image']['match_gids1']) >>> assert len(matches['image']['match_gids2']) >>> assert not len(matches['video'])
Example
>>> from geowatch.utils.kwcoco_extensions import * # NOQA >>> import kwcoco >>> from kwcoco.demo.perterb import perterb_coco >>> dset1 = kwcoco.CocoDataset.demo('vidshapes2') >>> kwargs = { >>> 'box_noise': 0.5, >>> 'n_fp': (0, 10), >>> 'n_fn': (0, 10), >>> } >>> dset2 = perterb_coco(dset1, **kwargs) >>> matches = associate_images(dset1, dset2, key_fallback='file_name') >>> assert not len(matches['image']['match_gids1']) >>> assert not len(matches['image']['match_gids2']) >>> assert len(matches['video'])
- geowatch.utils.kwcoco_extensions.reorder_video_frames(dset)[source]¶
Reorder the image indexes in each video to ensure temporal ordering
- geowatch.utils.kwcoco_extensions.pick_channels(coco_img, choices)[source]¶
Choose the set of channels in choices that all exist in this image.
Todo
[ ] Add to CocoIamge as a method
- Parameters:
coco_img (CocoImage) – an image with channels
choices (List[FusedChannelSpec | str]) – a list of fused channels in priority order to choose from.
- Returns:
The first channel group in
choices
where all of those channels exist in the image.- Return type:
None | FusedChannelSpec
CommandLine
xdoctest -m geowatch.utils.kwcoco_extensions pick_channels
Example
>>> from geowatch.utils import kwcoco_extensions >>> import kwcoco >>> choices = ['blue|green|red', 'pan'] >>> # Make different demo CocoImages that contain different bands >>> coco_img1 = kwcoco.CocoImage({ >>> 'channels': 'red|green|blue', 'file_name': 'dummy'}) >>> coco_img2 = kwcoco.CocoImage({ >>> 'channels': 'green|blue', 'file_name': 'dummy'}) >>> coco_img3 = kwcoco.CocoImage({ >>> 'channels': 'blue|green|red', 'file_name': 'dummy'}) >>> coco_img4 = kwcoco.CocoImage({ >>> 'channels': 'pan', 'file_name': 'dummy'}) >>> # Channels are only found if all bands in a choices item are given >>> found1 = kwcoco_extensions.pick_channels(coco_img1, choices) >>> found2 = kwcoco_extensions.pick_channels(coco_img2, choices) >>> found3 = kwcoco_extensions.pick_channels(coco_img3, choices) >>> found4 = kwcoco_extensions.pick_channels(coco_img4, choices) >>> print(f'found1={found1}') >>> print(f'found2={found2}') >>> print(f'found3={found3}') >>> print(f'found4={found4}') found1=<FusedChannelSpec(blue|green|red)> found2=None found3=<FusedChannelSpec(blue|green|red)> found4=<FusedChannelSpec(pan)>
Example
>>> # Test case with different choices orders >>> from geowatch.utils import kwcoco_extensions >>> channel_priority1 = ['blue|green|red', 'pan'] >>> channel_priority2 = ['pan', 'blue|green|red'] >>> coco_img1 = kwcoco.CocoImage({ >>> 'channels': 'blue|green|red|pan', 'file_name': 'dummy'}) >>> coco_img2 = kwcoco.CocoImage({ >>> 'channels': 'pan|blue|green|red', 'file_name': 'dummy'}) >>> found1 = kwcoco_extensions.pick_channels(coco_img1, channel_priority1) >>> found2 = kwcoco_extensions.pick_channels(coco_img1, channel_priority2) >>> found3 = kwcoco_extensions.pick_channels(coco_img2, channel_priority1) >>> found4 = kwcoco_extensions.pick_channels(coco_img2, channel_priority2) >>> # The first found band in choices is returned when >>> # the image contains both, regardless of order in the image. >>> print(f'found1={found1}') >>> print(f'found2={found2}') >>> print(f'found3={found3}') >>> print(f'found4={found4}') found1=<FusedChannelSpec(blue|green|red)> found2=<FusedChannelSpec(pan)> found3=<FusedChannelSpec(blue|green|red)> found4=<FusedChannelSpec(pan)>