diff --git a/CHANGELOG.md b/CHANGELOG.md index 844c6841b9fa21e91b2b74412f04af588c3e3584..c61702be53106ef364f41fc41cee566bb030f57a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,10 @@ This changelog follows the specifications detailed in: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), although we have not yet reached a `1.0.0` release. -## Version 0.6.3 - Unreleased +## Version 0.6.4 - Unreleased + + +## Version 0.6.3 - Released 2021-05-20 ## Version 0.6.2 - Released 2021-05-19 diff --git a/README.rst b/README.rst index 177cb508a3bf5961996242558c5d5a015b53db17..45cdf7a8b3f689fe532b296ee2bf9a325dab5c9d 100644 --- a/README.rst +++ b/README.rst @@ -4,15 +4,15 @@ ndsampler |GitlabCIPipeline| |GitlabCICoverage| |Pypi| |Downloads| -+------------------+-----------------------------------------------+ -| Read the docs | https://ndsampler.readthedocs.io | -+------------------+-----------------------------------------------+ -| Gitlab (main) | https://gitlab.kitware.com/utils/ndsampler | -+------------------+-----------------------------------------------+ -| Github (mirror) | https://github.com/Kitware/ndsampler | -+------------------+-----------------------------------------------+ -| Pypi | https://pypi.org/project/ndsampler | -+------------------+-----------------------------------------------+ ++------------------+---------------------------------------------------------+ +| Read the docs | https://ndsampler.readthedocs.io | ++------------------+---------------------------------------------------------+ +| Gitlab (main) | https://gitlab.kitware.com/computer-vision/ndsampler | ++------------------+---------------------------------------------------------+ +| Github (mirror) | https://github.com/Kitware/ndsampler | ++------------------+---------------------------------------------------------+ +| Pypi | https://pypi.org/project/ndsampler | ++------------------+---------------------------------------------------------+ The main webpage for this project is: https://gitlab.kitware.com/computer-vision/ndsampler diff --git a/ndsampler/__init__.py b/ndsampler/__init__.py index 8bac9a8463bc2c5e53a11def8a8a02659a2c2afe..fdbd4c6ce9b0446fe4b254d49f482c7a137fa3ba 100644 --- a/ndsampler/__init__.py +++ b/ndsampler/__init__.py @@ -2,7 +2,7 @@ mkinit ~/code/ndsampler/ndsampler/__init__.py --diff mkinit ~/code/ndsampler/ndsampler/__init__.py -w """ -__version__ = '0.6.3' +__version__ = '0.6.4' from ndsampler.utils.util_misc import (HashIdentifiable,) diff --git a/ndsampler/coco_regions.py b/ndsampler/coco_regions.py index de962ff5cc0a87b9dfb812f855add8f6603b4e2f..d98911770b841bdb2b4b1641e57422cb967659c9 100644 --- a/ndsampler/coco_regions.py +++ b/ndsampler/coco_regions.py @@ -553,6 +553,9 @@ class CocoRegions(Targets, util_misc.HashIdentifiable, ub.NiceRepr): if task == 'video_detection': sample_grid = new_video_sample_grid(dset, window_dims, window_overlap) + elif task == 'image_detection': + sample_grid = new_image_sample_grid(dset, window_dims, + window_overlap) else: raise NotImplementedError(task) @@ -849,7 +852,8 @@ def select_positive_regions(targets, window_dims=(300, 300), thresh=0.0, return selection -def new_video_sample_grid(dset, window_dims, window_overlap=0.0, +def new_video_sample_grid(dset, window_dims=None, window_overlap=0.0, + space_dims=None, time_dim=None, # TODO classes_of_interest=None, ignore_coverage_thresh=0.6, negative_classes={'ignore', 'background'}): """ diff --git a/ndsampler/coco_sampler.py b/ndsampler/coco_sampler.py index 5ff82adaedfa0ab5d39ec0e172279ba8b3e960ea..de23afdfa53188ca75a17d40cf7fb294330d64a2 100644 --- a/ndsampler/coco_sampler.py +++ b/ndsampler/coco_sampler.py @@ -885,6 +885,7 @@ class CocoSampler(abstract_sampler.AbstractSampler, util_misc.HashIdentifiable, # MECHANISM IS for time_idx, gid in enumerate(time_gids): img = self.dset.imgs[gid] + frame_index = img.get('frame_index', gid) tf_img_to_vid = Affine.coerce(img['warp_img_to_vid']) alignable = self.frames._load_alignable(gid) @@ -924,7 +925,8 @@ class CocoSampler(abstract_sampler.AbstractSampler, util_misc.HashIdentifiable, vid_chan_frame[None, ...], dims=('t', 'y', 'x', 'c'), coords={ - 't': np.array([time_idx]), + # TODO: this should be a timestamp if we have it + 't': np.array([frame_index]), # 'y': np.arange(vid_chan_frame.shape[0]), # 'x': np.arange(vid_chan_frame.shape[1]), 'c': list(matching_coords), diff --git a/ndsampler/delayed.py b/ndsampler/delayed.py index dfe16dd5c90235866b79b0897a627558d4f1f4eb..f92cdf1e5eeef0cbcb19b72f35890e08f55045c9 100644 --- a/ndsampler/delayed.py +++ b/ndsampler/delayed.py @@ -1,4 +1,7 @@ """ +DEPRECATD. THIS IS BEING MOVED TO KWCOCO FOR DEVELOPMENT AND EVENTUALLY WILL +LIVE IN KWIMAGE. + The classes in this file represent a tree of delayed operations. Proof of concept for delayed chainable transforms in Python. @@ -388,7 +391,7 @@ class DelayedLoad(DelayedImageOperation): dsize = self.meta.get('dsize', None) if dsize is not None: final = np.asarray(final) - final = kwimage.imresize(final, dsize=dsize) + final = kwimage.imresize(final, dsize=dsize, antialias=True) self.cache['final'] = final as_xarray = kwargs.get('as_xarray', False) @@ -710,29 +713,6 @@ class DelayedWarp(DelayedImageOperation): >>> tf = np.array([[5.2, 0, 1.1], [0, 3.1, 2.2], [0, 0, 1]]) >>> self = DelayedWarp(np.random.rand(3, 5, 13), tf, dsize=dsize) >>> self.finalize().shape - - Example: - >>> # Test aliasing - >>> from ndsampler.delayed import * # NOQA - >>> s = DelayedIdentity.demo('checkerboard') - >>> s = DelayedIdentity.demo() - >>> a = s.delayed_warp(Affine.scale(0.05), dsize='auto') - >>> b = s.delayed_warp(Affine.scale(3), dsize='auto') - - >>> # xdoctest: +REQUIRES(--show) - >>> import kwplot - >>> kwplot.autompl() - >>> # It looks like downsampling linear and area is the same - >>> # Does warpAffine have no alias handling? - >>> pnum_ = kwplot.PlotNums(nRows=2, nCols=4) - >>> kwplot.imshow(a.finalize(interpolation='area'), pnum=pnum_(), title='warpAffine area') - >>> kwplot.imshow(a.finalize(interpolation='linear'), pnum=pnum_(), title='warpAffine linear') - >>> kwplot.imshow(a.finalize(interpolation='nearest'), pnum=pnum_(), title='warpAffine nearest') - >>> kwplot.imshow(a.finalize(interpolation='cubic'), pnum=pnum_(), title='warpAffine cubic') - >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='area'), pnum=pnum_(), title='resize area') - >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='linear'), pnum=pnum_(), title='resize linear') - >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='nearest'), pnum=pnum_(), title='resize nearest') - >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='cubic'), pnum=pnum_(), title='resize cubic') """ def __init__(self, sub_data, transform=None, dsize=None): self.sub_data = sub_data @@ -910,11 +890,34 @@ class DelayedWarp(DelayedImageOperation): >>> kwplot.imshow(final1, pnum=(1, 3, 2), fnum=1) >>> kwplot.imshow(final2, pnum=(1, 3, 3), fnum=1) >>> kwplot.show_if_requested() + + Example: + >>> # Test aliasing + >>> from ndsampler.delayed import * # NOQA + >>> s = DelayedIdentity.demo() + >>> s = DelayedIdentity.demo('checkerboard') + >>> a = s.delayed_warp(Affine.scale(0.05), dsize='auto') + >>> b = s.delayed_warp(Affine.scale(3), dsize='auto') + + >>> # xdoctest: +REQUIRES(--show) + >>> import kwplot + >>> kwplot.autompl() + >>> # It looks like downsampling linear and area is the same + >>> # Does warpAffine have no alias handling? + >>> pnum_ = kwplot.PlotNums(nRows=2, nCols=4) + >>> kwplot.imshow(a.finalize(interpolation='area'), pnum=pnum_(), title='warpAffine area') + >>> kwplot.imshow(a.finalize(interpolation='linear'), pnum=pnum_(), title='warpAffine linear') + >>> kwplot.imshow(a.finalize(interpolation='nearest'), pnum=pnum_(), title='warpAffine nearest') + >>> kwplot.imshow(a.finalize(interpolation='nearest', antialias=False), pnum=pnum_(), title='warpAffine nearest AA=0') + >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='area'), pnum=pnum_(), title='resize area') + >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='linear'), pnum=pnum_(), title='resize linear') + >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='nearest'), pnum=pnum_(), title='resize nearest') + >>> kwplot.imshow(kwimage.imresize(s.finalize(), dsize=a.dsize, interpolation='cubic'), pnum=pnum_(), title='resize cubic') """ # todo: needs to be extended for the case where the sub_data is a # nested chain of transforms. - import cv2 - from kwimage import im_cv2 + # import cv2 + # from kwimage import im_cv2 if dsize is None: dsize = self.dsize transform = Affine.coerce(transform) @ self.transform @@ -932,33 +935,16 @@ class DelayedWarp(DelayedImageOperation): else: as_xarray = kwargs.get('as_xarray', False) # Leaf finalize - flags = im_cv2._coerce_interpolation(interpolation) + # flags = im_cv2._coerce_interpolation(interpolation) if dsize == (None, None): dsize = None sub_data_ = np.asarray(sub_data) - # sub_data_ = sub_data_.astype(np.float32) / 255. - # print('flags = {!r}'.format(flags)) - # print('sub_data_.dtype = {!r}'.format(sub_data_.dtype)) - - # TODO: should we blur the source if the determanent of M is less - # than 1? If so by how much - if kwargs.get('antialias', True) and interpolation != 'nearest': - factor = transform.det() - # [0:2, 0:2]) - # Hacked in heuristic for antialiasing before a downsample - if factor < 0.99: - k = int(1 / np.sqrt(factor) * 1.2) - if k % 2 == 0: - k += 1 - sigma = 0.3 * ((k - 1) * 0.5 - 1) + 0.8 - sigma = sigma ** 1.2 - sub_data_ = sub_data_.copy() - sub_data_ = cv2.GaussianBlur(sub_data_, (k, k), sigma, sigma) - M = np.asarray(transform) - final = cv2.warpAffine(sub_data_, M[0:2], dsize=dsize, flags=flags) + antialias = kwargs.get('antialias', True) + final = kwimage.warp_affine(sub_data_, M, dsize=dsize, + interpolation=interpolation, + antialias=antialias) # final = cv2.warpPerspective(sub_data_, M, dsize=dsize, flags=flags) - print(final.mean()) # Ensure that the last dimension is channels final = kwarray.atleast_nd(final, 3, front=False) if as_xarray: diff --git a/requirements/runtime.txt b/requirements/runtime.txt index 99257c27b7af001a7508acadca6d7c0d04664bed..a9735f1c9fb6694de2fff9dcfcc741fc7f2c0f55 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -23,7 +23,7 @@ pyqtree >= 1.0.0 # There are likely several more undocumented deps, see what fails and submit a PR please! # TODO : fill me in! -kwimage >= 0.4.0 +kwimage >= 0.7.6 kwarray >= 0.5.16 kwcoco >= 0.2.1