geowatch.cli.coco_average_features module¶
- class geowatch.cli.coco_average_features.CocoAverageFeaturesConfig(*args, **kwargs)[source]¶
Bases:
DataConfigAverage multiple kwcoco files - i.e. ensemble heatmap predictions.
Create a new kwcoco file with averaged features from multiple kwcoco files.
- High Level Steps:
Load kwcoco files. Must have at least two kwcoco files.
Create new kwcoco file by copying first kwcoco file.
- For each image ID in the kwcoco file, load the features from each kwcoco file.
Average the features from each kwcoco file.
Save the averaged features to the new kwcoco image.
Save the new kwcoco file.
Valid options: []
- Parameters:
*args – positional arguments for this data config
**kwargs – keyword arguments for this data config
- default = {'channel_name': <Value(None)>, 'flexible_merge': <Value(False)>, 'io_workers': <Value('avail')>, 'kwcoco_file_paths': <Value(None)>, 'output_channel_names': <Value(None)>, 'output_kwcoco_path': <Value(None)>, 'resolution': <Value(None)>, 'sensors': <Value(None)>, 'weights': <Value(None)>}¶
- geowatch.cli.coco_average_features.split_channel_names_by_grammar(channel_names)[source]¶
Split a string containing channel names by commas (,) and pipes (|).
- geowatch.cli.coco_average_features.check_kwcoco_file(kwcoco_file, channel_name, sensor_names=None, flexible_merge=False)[source]¶
Make sure that kwcoco files exist and contain required channel name.
- Parameters:
kwcoco_file (kwcoco.CocoDataset) – kwcoco file containing images.
channel_name (str) – Name of channel thats required to be in kwcoco file.
sensor_names (list(str), optional) – Only check images of from these types of sensors. Defaults to None.
flexible_merge (bool, optional) – Skip images that do not contain channel_name. Defaults to False.
- Returns:
A list of names corresponding to images without the channel name.
- Return type:
missing_image_names (list)
- geowatch.cli.coco_average_features.merge_kwcoco_channels(kwcoco_file_paths, output_kwcoco_path, channel_names, weights, output_channel_names, sensor_names=None, resolution=None, flexible_merge=False, io_workers='avail')[source]¶
Compute a weighted mean of channels from separate kwcoco file and save into merged kwcoco file.
- Assumptions:
- The channel_nams to merge are not a subset of a group of channels targeted in the kwcoco file.
I.e. ‘salient’ in ‘salient|notsalient’ will not work.
- Parameters:
kwcoco_file_paths (list(str)) – A list of paths representing pathes to kwcoco files to be merged.
output_kwcoco_path (str) – Local path to the kwcoco file with merged channels.
channel_names (list(str)) – A list of channel names corresponding to the channel name to merge from each kwcoco file. Note, the length of the channel names be equal to the number of kwcoco file paths.
weights (list(int)) – A list of floats representing how much weight a particular kwcoco file should contribute to the final merged prediction.
output_channel_names (list(str)) – A list containing the names of the output channel names. Must contain the same number of channel names as the input channel names.
sensor_names (list(str), optional) – Only merge images belonging to sensors in this list. Defaults to None (aka do not filter by sensor).
resolution (int | str, optional) – GSD to resize the resolution of the images to. Defaults to None.
flexible_merge (bool, optional) – Skip images that do not contain channel_name. Defaults to False.
Example
>>> # TEST 1: Merge two kwcoco files with the same number of images and plot results. >>> from geowatch.cli.coco_average_features import * # NOQA >>> import geowatch >>> import kwimage >>> import numpy as np >>> from kwcoco.demo.perterb import perterb_coco >>> import kwcoco >>> dpath = ub.Path.appdir('geowatch/tests/coco_average_features') >>> base_dset = geowatch.coerce_kwcoco('geowatch-msi', geodata=True, dates=True, image_size=(64, 64), num_videos=2, num_frames=2) >>> # Construct two copies of the same data with slightly different heatmaps >>> dset1 = perterb_coco(base_dset.copy(), box_noise=0.5, cls_noise=0.5, n_fp=10, n_fn=10, rng=32) >>> dset2 = base_dset.copy() >>> for video in dset1.dataset['videos']: ... video['resolution'] = '10GSD' >>> for video in dset2.dataset['videos']: ... video['resolution'] = '10GSD' >>> dset1.fpath = ub.Path(dset1.fpath).augment(stemsuffix='_heatmap1') >>> dset2.fpath = ub.Path(dset2.fpath).augment(stemsuffix='_heatmap2') >>> geowatch.demo.smart_kwcoco_demodata.hack_in_heatmaps(dset1, heatmap_dname='dummy_heatmap1', with_nan=0, rng=423432) >>> geowatch.demo.smart_kwcoco_demodata.hack_in_heatmaps(dset2, heatmap_dname='dummy_heatmap2', with_nan=0, rng=132129) >>> dset1.dump(dset1.fpath) >>> dset2.dump(dset2.fpath) >>> # Build method args >>> kwcoco_file_paths = [dset1.fpath, dset2.fpath] >>> output_bundle_dpath = (dpath / 'merge_bundle').delete().ensuredir() >>> output_kwcoco_path = output_bundle_dpath / 'data.kwcoco.json' >>> channel_names = ['notsalient|salient'] * 2 >>> weights = [1.0, 1.0] >>> output_channel_names = 'notsalient|salient' >>> sensor_name = None >>> resolution = '12GSD' >>> # Execute merge >>> merge_kwcoco_channels(kwcoco_file_paths, output_kwcoco_path, >>> channel_names, weights, output_channel_names, >>> sensor_name, resolution=resolution) >>> # Check results >>> output_dset = kwcoco.CocoDataset(output_kwcoco_path) >>> gid = output_dset.images()[1] >>> imdata1 = dset1.coco_image(gid).imdelay('salient', space='asset').finalize() >>> imdata2 = dset2.coco_image(gid).imdelay('salient', space='asset').finalize() >>> imdataM = output_dset.coco_image(gid).imdelay('salient', space='asset').finalize() >>> imdata1_img = dset1.coco_image(gid).imdelay('salient', space='image').finalize() >>> imdata2_img = dset2.coco_image(gid).imdelay('salient', space='image').finalize() >>> imdataM_img = output_dset.coco_image(gid).imdelay('salient', space='image').finalize() >>> print(f'Weights: {weights}') >>> print(f'Img1 mean: {np.nan_to_num(imdata1).mean()}') >>> print(f'Img2 mean: {np.nan_to_num(imdata2).mean()}') >>> print(f'Merge mean: {np.nan_to_num(imdataM).mean()}') >>> print() >>> print(f'Img1 shape (asset space): {imdata1.shape}') >>> print(f'Img2 shape (asset space): {imdata2.shape}') >>> print(f'Merge shape (asset space): {imdataM.shape}') >>> print(f'Img1 shape (img space): {imdata1_img.shape}') >>> print(f'Img2 shape (img space): {imdata2_img.shape}') >>> print(f'Merge shape (img space): {imdataM_img.shape}') >>> os.remove(dset1.fpath) >>> os.remove(dset2.fpath) >>> os.remove(output_dset.fpath) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> F = kwimage.fill_nans_with_checkers >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata1)), title='img1 (asset)', pnum=(2, 3, 1), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata2)), title='img2 (asset)', pnum=(2, 3, 2), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdataM)), title='mean (asset)', pnum=(2, 3, 3), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata1_img)), title='img1 (img)', pnum=(2, 3, 4), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata2_img)), title='img2 (img)', pnum=(2, 3, 5), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdataM_img)), title='mean (img)', pnum=(2, 3, 6), fnum=1) >>> save_figure_path = dpath / 'test_1_result_plot.png' >>> import matplotlib.pyplot as plt >>> plt.savefig(save_figure_path) >>> print(f'Test 1 plot saved to: {save_figure_path}')
Example
>>> # TEST 2: Merge two kwcoco files with geo information. >>> from geowatch.cli.coco_average_features import * # NOQA >>> import geowatch >>> import kwimage >>> from kwcoco.demo.perterb import perterb_coco >>> import kwcoco >>> import numpy as np >>> dpath = ub.Path.appdir('geowatch/tests/coco_average_features') >>> base_dset = geowatch.coerce_kwcoco('geowatch-msi', geodata=True, dates=True, image_size=(64, 64), num_videos=2, num_frames=2) >>> # Construct two copies of the same data with slightly different heatmaps >>> dset1 = perterb_coco(base_dset.copy(), box_noise=0.5, cls_noise=0.5, n_fp=10, n_fn=10, rng=32) >>> dset2 = base_dset.copy() >>> dset1.fpath = ub.Path(dset1.fpath).augment(stemsuffix='_heatmap1') >>> dset2.fpath = ub.Path(dset2.fpath).augment(stemsuffix='_heatmap2') >>> geowatch.demo.smart_kwcoco_demodata.hack_in_heatmaps(dset1, heatmap_dname='dummy_heatmap1', with_nan=0, rng=423555) >>> geowatch.demo.smart_kwcoco_demodata.hack_in_heatmaps(dset2, heatmap_dname='dummy_heatmap2', with_nan=0, rng=132666) >>> dset1.dump(dset1.fpath) >>> dset2.dump(dset2.fpath) >>> # Build method args >>> kwcoco_file_paths = [dset1.fpath, dset2.fpath] >>> output_bundle_dpath = (dpath / 'merge_bundle').delete().ensuredir() >>> output_kwcoco_path = output_bundle_dpath / 'data.kwcoco.json' >>> channel_names = ['notsalient|salient'] * 2 >>> weights = [1.0, 1.0] >>> output_channel_names = 'notsalient|salient' >>> sensor_name = None >>> resolution = None >>> # Execute merge >>> merge_kwcoco_channels(kwcoco_file_paths, output_kwcoco_path, >>> channel_names, weights, output_channel_names, >>> sensor_name, resolution=resolution) >>> # Check results >>> output_dset = kwcoco.CocoDataset(output_kwcoco_path) >>> gid = 3 >>> imdata1 = dset1.coco_image(gid).imdelay('salient', space='asset').finalize() >>> imdata2 = dset2.coco_image(gid).imdelay('salient', space='asset').finalize() >>> imdataM = output_dset.coco_image(gid).imdelay('salient', space='asset').finalize() >>> imdata1_img = dset1.coco_image(gid).imdelay('salient', space='image').finalize() >>> imdata2_img = dset2.coco_image(gid).imdelay('salient', space='image').finalize() >>> imdataM_img = output_dset.coco_image(gid).imdelay('salient', space='image').finalize() >>> print(f'Weights: {weights}') >>> print(f'Img1 mean: {np.nan_to_num(imdata1).mean()}') >>> print(f'Img2 mean: {np.nan_to_num(imdata2).mean()}') >>> print(f'Merge mean: {np.nan_to_num(imdataM).mean()}') >>> print() >>> print(f'Img1 shape (asset space): {imdata1.shape}') >>> print(f'Img2 shape (asset space): {imdata2.shape}') >>> print(f'Merge shape (asset space): {imdataM.shape}') >>> print(f'Img1 shape (img space): {imdata1_img.shape}') >>> print(f'Img2 shape (img space): {imdata2_img.shape}') >>> print(f'Merge shape (img space): {imdataM_img.shape}') >>> os.remove(dset1.fpath) >>> os.remove(dset2.fpath) >>> os.remove(output_dset.fpath) >>> # xdoctest: +REQUIRES(--show) >>> import kwplot >>> kwplot.autompl() >>> F = kwimage.fill_nans_with_checkers >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata1)), title='img1 (asset)', pnum=(2, 3, 1), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata2)), title='img2 (asset)', pnum=(2, 3, 2), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdataM)), title='mean (asset)', pnum=(2, 3, 3), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata1_img)), title='img1 (img)', pnum=(2, 3, 4), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdata2_img)), title='img2 (img)', pnum=(2, 3, 5), fnum=1) >>> kwplot.imshow(F(kwimage.normalize_intensity(imdataM_img)), title='mean (img)', pnum=(2, 3, 6), fnum=1) >>> save_figure_path = dpath / 'test_2_result_plot.png' >>> import matplotlib.pyplot as plt >>> plt.savefig(save_figure_path) >>> print(f'Test 2 plot saved to: {save_figure_path}')
- geowatch.cli.coco_average_features.main(cmdline=True, **kw)[source]¶
Main function for merge_kwcoco_channels. See
CocoAverageFeaturesConfigfor detailsTODO: Add examples
Example
>>> from geowatch.cli.coco_average_features import * # NOQA >>> import geowatch >>> import kwimage >>> import numpy as np >>> from kwcoco.demo.perterb import perterb_coco >>> import kwcoco >>> dpath = ub.Path.appdir('geowatch/tests/coco_average_features_main') >>> base_dset = geowatch.coerce_kwcoco('geowatch-msi', geodata=True, dates=True, image_size=(64, 64), num_videos=2, num_frames=2) >>> # Construct two copies of the same data with slightly different heatmaps >>> dset1 = perterb_coco(base_dset.copy(), box_noise=0.5, cls_noise=0.5, n_fp=10, n_fn=10, rng=32) >>> dset2 = base_dset.copy() >>> for video in dset1.dataset['videos']: ... video['resolution'] = '10GSD' >>> for video in dset2.dataset['videos']: ... video['resolution'] = '10GSD' >>> dset1.fpath = ub.Path(dset1.fpath).augment(stemsuffix='_heatmap1') >>> dset2.fpath = ub.Path(dset2.fpath).augment(stemsuffix='_heatmap2') >>> geowatch.demo.smart_kwcoco_demodata.hack_in_heatmaps(dset1, heatmap_dname='dummy_heatmap1', with_nan=0, rng=423432) >>> geowatch.demo.smart_kwcoco_demodata.hack_in_heatmaps(dset2, heatmap_dname='dummy_heatmap2', with_nan=0, rng=132129) >>> dset1.dump(dset1.fpath) >>> dset2.dump(dset2.fpath) >>> output_kwcoco_path = dpath / 'output.kwcoco.zip' >>> # Execute merge >>> kwargs = { >>> 'kwcoco_file_paths': [dset1.fpath, dset2.fpath], >>> 'output_kwcoco_path': output_kwcoco_path, >>> 'channels': ['notsalient|salient'], >>> 'resolution': 30, >>> } >>> cmdline = 0 >>> main(cmdline=cmdline, **kwargs) >>> output_dset = kwcoco.CocoDataset(output_kwcoco_path) >>> coco_img = output_dset.images().coco_images[0] >>> import numpy as np >>> assert not np.all(np.isnan(coco_img.imdelay('salient').finalize()))