This changelog follows the specifications detailed in: Keep a Changelog.
This project adheres to Semantic Versioning, although we have not yet reached a 1.0.0 release.
- Normalized the way
oriented_bounding_boxreturns coordinates. - Better error message in
load_image_shape. - Improve
imwriteerror diagnostics for the cv2 backend. - Better gdal import errors.
- Drop Python 3.9
- Worked around the OpenCV 4.13.x
warpAffineregression forfloat64inputs with nearest-neighbor interpolation.
- Improved stack-images CLI.
- New crop-border CLI.
- Add
containstokwimage.Box - Add
kwimage.adjustto adjust simple image properties.
Detections.draw_onno longer breaks if some classes are unknown (i.e. null)- Fix overflow issue in
py_nmsif inputs were float16 - Fixed issue preventing torchvision nms from being recognized as a backend.
- Issue with Points.coerce when data was a numpy array
- Issue with resize on empty boxes
- Better errors on
stack_imageswith empty input
- kwimage.Affine.fit now falls back to a similarity transform if fewer than 3 correspondences are given,
- kwimage.Affine.fit now falls back on a np.linalg.lstdq solution if the SVD is degenerate.
- Added
areaproperty toSegmentation - Added
boxproperty toSegmentation - Added
boxmethod toMask - Added
none_policytoSegmentationList.coerce - Added
remove_holestoPolygonandMultiPolygon - Added
draw_polyline_on_imagetoim_draw.py - Handle
Polygon.draw_onwhere the input image is None.
- Deprecate
Mask.to_boxes - Deprecate
Mask.bounding_box
kwimage.Polygon.to_maskwill now pick dimensions to fit the polygon if they are unspecified.kwimage.Detections.to_coconow handles the case where an entry in data or meta is None- Generic spatial list objects used by
kwimage.Detectionsnow implement the full MutableSequence API, and may explicitly inherit from it in the future.
- Fixed issue in
Detections.from_coco_annotswhere column arrays would not be aligned if an annotation was missing specific data. - Fixed an issue that disallowed empty masks / heatmaps in some cases
- Issue where
Boxes.draw_onwould not allocate a correctly sized image when it was not given. - Fix
Polygon.drawwherefacecolor='none'. Polygon.circlenow produces polygons with the correct specified number of sides.- Rare case where Boxes.warp with None would warp by a null matrix instead of identity.
- Ignore imgaug if it fails to import.
Points.to_shapelyandCoords.to_shapelyPoints.from_shapelyandCoords.from_shapelyPoints.wktandCoords.wkt- classes arg to
Points.coerce
kwcoco.CategoryTreenow returns other metadata with it when converting to COCO dictionaries- Made
Points.to_cocoallow conversion to coco without category ids, by dropping them
- Issue in Points.coerce where unspecified keypoints categories were interpreted as specified with length zero.
-
warp_affinecan now be used withbackend='itk'. -
kwimage.Pointsnow contains a "new-v2" style of coco keypoints that it can handle.
-
Fix issue of coercing detections when segmentations are null.
-
Patched issue where checkerboard would produce the wrong sized image, fix is not perfect.
-
Move
warp_affine,warp_projective, andwarp_imageinto their own module to support the using multiple backends for the underlying operation. -
Module init now uses lazy imports
-
Default
grab_test_imageinterpolation changed from lanczos to linear. -
cv2 is now officially optional, but a large amount of functionality will not be available without it.
- Add classmethod
PolygonList.random - Add method
PolygonList.to_boxes
kwimage.Polygon.drawfacecolor argument now properly handles coercible colors.kwimage.PolygonList.drawnow handles setlim correctlykwimage.Boxes.coercenow handles the format argument correctly.
- Added
canonicalflag to Boxes to speed up creation time when input is known to be good. - Added
bayer_valueargument tokwimage.checkerboard.
- kwimage.Boxes and kwimage.Box now use
__slots__
- Passing a list of alphas to
Detections.draw_onnow works correctly. - Usage of distutils
- Issue in checkerboard function where the next multiple of X was not computed correctly.
- Support for numpy 2.0 on Python 3.9+
- Add "opacity" argument to
kwimage.Color.adjust. - Add
__json__tokwimage.Boxes - Allow user to specify backend order in
load_image_shape. - Add the superstar test image
kwimage.Color.nearest_namedfor finding the approximate name of a color.
- Removed support for Python 3.6 and 3.7
- Demodata is now more robust to networking outages. If no mirror can be reached, it generates random data to replace the real image.
- Fix issue with Boxes.draw when Boxes is empty
- Allow heatmap.draw to do something if classes are not defined.
kwimage.Boxes.clipnow works on torch.Tensor data.
- Basic CLI with the
stack_imagescommand. - Workaround for
colorizewhen heatmap is an index raster with negative ignore values.
-
Add
drop_non_polygonsargument to_ShapelyMixin.fix. -
Changed: argument to
grab_test_image_fpathcan now be an existing path and it will return that. (allows users to substitute custom images for demodata). -
Added
clip,shape,endpoint, andwrapargument toBox.from_slice
- Can now call
draw_header_textwithout an image argument.
kwimage.Affine.fliprot- a constructor that creates a transform equivalent to a flip and rotation with the positive image quadrantkwimage.Boxes._ensure_nonnegative_extent- experimental box method to fix negative width/heights
draw_onmethods forBoxes,Polygon, andPointsno longer crashes if you pass it an image with 0 width or height.- Fixed error in
subpixel_setvaluewhere the coordinate extents did not always match the requested axes (e.g. sometimes the y axis would be clipped by width)
- Added a too-big check in
imwritefor better error messages.
- Modified paths of augmented demodata to remove bad path characters.
Boxes.from_slicenow allows the left coordinate to be bigger than the right in the case you are clipping.
- Fixed issue when giving
Affine.coercean empty dictionary - Issue in box
intersection/union_hullwith integer data - Fixed
Box.to_coco()
- intersection to Box class.
grab_test_imagenow falls back to mirrors if the first URL returns an error- Allow
formatto be positional inkwimage.Box.coerceandkwimage.Boxes.coerce
- Fixed compatibility with new scikit-image
- Mixin methods are now shown in the docs
Disable torchvision NMS on windows by default
- Avoid importing torch globally
- Add "regular" and "star" classmethods to Polygon
- float128 issues on windows
- switch from ubelt.repr2 to ubelt.urepr
- On windows the default gdal compression is changed to LZW. The default everywhere else is still DEFLATE.
center_xandcenter_yto Box and Boxes.Boxes.resizenow hasaboutargument.
- Bug in
warp_affinewhen the input image has more than 4 dims, has an empty dimension, andborder_valueis an array. - Issue in
nodata_checkerboardwith masked arrays.
- New function:
exactly_1channel.
- kwimage.imresize now works when the input image has dsize=(1, 1)
- Small speedups
- Add cv2 backend to
fourier_mask, which is a 3x speedup, and set this to the default.
- imresize now returns the original image if all scale / dsize arguments are unspecified or None.
- Polygon.fill can now work in non-inplace cases, but the
assert_inplaceflag must be set to 0. - Allow nan as a nodata_method as alias for float
labelsindraw_onnow interprets integers as booleans- Fixed shapely warning about the "type" attribute. Now using
geom_typeinstead.
- imresize now accepts input dtypes: bool, int32
- imresize now outputs the same channel dimensions as given in the input
- Polygon.union is fixed. (previously it did intersection)
- replaced np.bool with bool
- Fixed issue when drawing text on an unspecified image with an rgba background color
- Better shapely and gdal transform support in Affine
- Improved agreement between polygon and box draw_on methods.
- Added Color.adjust
- Moved color data to its own module
fill_nans_with_checkersuses a muted checkerboard which is less visually jarring
- Fixed issue in kwimage.Box where some functions (e.g.
tl_x) were returning incorrectly shaped. - Bug in nms with cython cpu.
- Added new
Boxclass to represent a single box. - Basic shapely features in Polygon and MultiPolygon
Polygon.oriented_bounding_box- Added
__geo_interface__to Polygon and MultiPolygon - Add imwrite "pil" backend.
- imresize no longer fails if none of the scale params are given, it just returns the image as-is.
- Bug in
kwimage.Boxes.draw(setlim=1) - But in
fill_nans_with_checkerswith what channels were filled with checkers.
- support for torch in
Boxes.iooa(requires kwarray update) - imresize with letterbox now works when dsize has a None component.
- Expose
on_valueandoff_valueinfill_nans_with_checkers - Better color support
- Changed image of Carl Sagan to one I know has a CC license.
- Added IPFS CIDs to all demo images.
- Minor doc improvements.
- interpolate to Polygon and Color
- The
bg_colorarg todraw_header_text - Implemented
kwimage.warp_image - The
kwimage.Color.forimagefunction is now public - Basic support for polygon interpolation.
- Issue in Detections.draw where "cids" was not respected.
- Minor fixes in warp projective.
nodata_checkerboardnow works better with uint8 data.
- Enhanced the checkerboard function, which can now take "on" and "off" string colors and return different dtypes.
kwimage.warp_projectivekwimage.connected_componentskwimage.Boxes.resizefor setting the width/height of a box.kwimage.Polygon.circlecan now be constructed as an ellipse by specifying radii as a tuple
- Passing single and multiple colors now works correctly for
Points.draw_on. - Fixed morphology when kernel was 0
- Added "resize" option to
stack_images_grid - The
Coordsobject now implements__array__. - The
aboutparameter forPolygontransformations has been expanded to include codes: "top,left", "top,right", etc... - A
from_textmethod for masks.
- Fixed issue in copy methods of polygon and coords
- Issue where
Mask.to_multi_polygonwould break if the underlying data had dtype bool. - Minor issues in heatmap (other than the giant issue that is that class)
- Support for decomposing projective transforms
- Stack images now can do automatic casting between uint255 and float01
- In
warp_affinechange behavior soborder_valuescalars are transformed to tuples instead of the current opencv behavior where other channels are zeroed.
- Add
wrapkwarg toBoxes.from_slice
dsizearg tograb_test_image_fpath
kwimage.Affine.coercenow correctly respects "about"
- The
kwimage.imreadgdal backendnodataargument is deprecated, and should now be specified asnodata_methodto indicate how to handle nodata. Specific nodata values that are not embedded in image metadata should be handled outside of this function.
- Working on QOI support
- Added
kitware_greenandkitware_blue"Kitware colors" inkwimage.Color. - Type annotations stubs
- Moved binary backends to
kwimage_extmodule as optional dependencies. Kwimage is now a pure python package.
- Intention: ndarray functions in kwimage and kwarray should respect masked arrays.
- Deprecate using overview=-1 to get the coarsest overview. Use the string "coarsest" instead.
- The "overview" argument to gdal now uses 0-based indexing such that overview=0 is no overview,
and overview=1 is the first overview. This corresponds to the scale being
2^{overview}.
kwimage.Affine.to_shapelymethod for converting affine transforms to shapely-style
- Fix issue in
Polygon.drawwhere facecolor and edgecolor were not respected. - Added
to_shapelyforkwimage.Affine - Issue in
kwimage.load_image_shapewhen using pathlib.Path
- Bug in
Detections.draw_on(..., color='classes')when a class is unknown - Added workaround to cv2 bug to
Polygon.draw_onwhen polygon coordinates are too large. Currently clips the polygon and emits a warning, this prevents crashes, but results may not be correct.
Boxes.from_sliceno longer handles wraparound slices as it is not well defined and previous behavior was buggy.
- facecolor and edgecolor in
Polygon.draw_on
- Bug in MultiPolygon draw,
Polygon.draw_onno longer crashes when polygon is empty. - imread overviews now work for grayscale images
- Speed up drawing in PolygonList and other generic draw funcs
- improve checkerboard
- Added option to mask nodata regions when using imread and gdal backend.
- Added area property to Polygon and MultiPolygon.
- Added option to
ignore_color_tablewhen using gdal imread backend.
- Fixes for
intensity_normalize - Allow user to specify nodata, transform, and crs when writing a geotiff
- Consolidated environment variables in a new
kwiamge._internalmodule.
- Previously Polygon.fill would only fill the first channel, this is now fixed
kwimage.imwritenow raises an exception if the file fails to write.- Fixed alpha in
Polygon.draw_onfor polygon borders. - Fixed issue in
load_image_shapewhen PIL fails.
kwimage.Color.distinctnow usesdistinctipyas a backend, and gains functionality to exclude existing colors.
- Serious bug in
kwimage.Affine, wheredecomposeandaffinewere not inverse. Behavior of kwimage.Affine with shear is now deprecated as it was inconsistent. New parameter that impacts shear isxshear.
- Mask translation is now more efficient for c/f formats.
- Bug introduced in
Mask.to_multipolygonwhich caused bad offsets
pixels_areflag toto_mask/to_multi_polygonmethods, which can be points or areas. The latter uses a rasterio contour finding mechanism.imreadgdalbackend can now read from overviews if they exist.
warp_affinenow properly raises an error when cv2.warpAffine raises an unhandled error- Polygon to/from methods now handle the empty polygon case
- Improved polygon / segmentation coercion methods
- kwimage.morphology
- kwimage.draw_header_text
Mask.to_multi_polygonandPolygon.to_masknow take a flagpixels_arewhich will treat pixels as areas or points.
- But in imresize when a dim was automatically computed to be zero.
- Using
mathis much faster thannumpyfor scalars, switching to that in kwimage.Affine - Added default behavior to
draw_text_on_imagewhen origin is unspecified. - Polygon and MultiPolygon coerce work better with geojson
- Work on new robust normalizers (see
normalize_intensity)
- Add function
gaussian_blur - Added
padas an argument tostack_imagesto override a negativeoverlap - Added gaussian sigma kernel heuristic
- Added interleave as an option to COG write
- Add
filltoPolygonList
- Polygons now better respect the color parameter in detections draw on
- kwimage.imread can now take pathlib.Path objects
- Fixed issue with warp of empty keypoints
- Changed default GDAL compression in
kwimage.imwritefrom RAW to DEFLATE - Better overview support in
kwimage.imwrite - Improved speed of several
kwimage.Affineroutines.
- Wrapped
itk.imreadwithkwimage.imread. - Added
kwimage.imcrop - Add
large_warp_dimtokwimage.warp_affine
kwimage.warp_affinenow returns a sensible result when the source or destination image has no size.kwimage.grab_test_imagenow checks sha256 instead of sha1.- Fixed tests that downloaded data, but did not check hashes
- Improved
cv2.imreadauto-space default based on the available backend. Should no longer need to specify it unless working with cv2.
- C-Extension errors for boxes now fallback on pure-python
- Enhanced capabilities of
draw_text_on_image Mask.draw_onwill now draw on an empty image if none is provided
- C-Extension errors for masks now fallback on pure-python
- Not having
imgaugno longer warns - Fixed issues with generic warps
-
added
border_modeandborder_valuetowarp_affine. -
The
imgarg indraw_text_on_imagecan now be specified as a dictionary for control over canvas generation.
-
issue computing canvas size in
draw_text_on_imagewhen an image is not given. -
failing to have imgaug no longer crashes arbitrary functions in annotation warp methods.
kwimage.structs.*.warpcan now accept akwimage.Affineobject.
Boxes.to_slicesAffine.concise
- counterclockwise polygon check
- improvements to
kwimage.Affine.
- Fixed failure in Affine.coerce
- Fixed random test failure in Boxes
- New CI for building wheels with cibuildwheel
- Checkerboard demo image
warp_affinewith optional antialiasing for downsample operations.imresizenow has optional antialiasing.Affine.decomposewhich extracts the scale, translation, rotation, and shear from an affine matrix.
imscaleis deprecated and now results in an errorwarp_image, which did not do what you think it does, is deprecated and now results in an error
- New
transform.pymodule
- Fixed numpy warning by using
floatinstead ofnp.float.
- Errors instead of warns for opencv import issues
- Warp methods now treat None as the identity transform.
kwimage.num_channelsno longer errors when the number of channels is not 1, 3, or 4.
-
Using
from osgeo import gdalinstead ofimport gdalto fix for gdal 3.2.1 -
Fixed numpy warning by using
intinstead ofnp.int.
- opencv-python and opencv-python-headless are now optional dependencies.
- Issue with RLE to fortran mask conversion: https://gitlab.kitware.com/computer-vision/kwimage/-/issues/2
-
Add
.jp2to known GDAL extensions. -
Add
soft_filltoCoords, which aims to paint Gaussian blobs as coordinate locations. -
Add
kwimage.padded_sliceported and refactored from ndsampler. -
Add
reorder_axestoCoords, which can change xy to yx representations etc... -
Added
Boxes.bounding_boxmethod -
Added quantize method to bounding boxes which pushes the left-top coordinates to their floor and the right-bottom coordinates to their ceiling.
-
Detections.draw_oncan now accept color='classes' -
expose
thicknessinDetections.draw_on. -
Added
aboutto Polygon and Coords scale and rotate. -
Add
to_geojsontoPolygonList
-
kwimage.Detectionsnow correctly handlesNonedata values. PreviouslyNonewas converted to anarray(None, dtype=object). -
demodata images now have the correct extension
-
Fixed issue with channelless data in
Heatmap.draw_on -
Bug in
Detections._make_labelswhen scores are List[None]
-
BREAKING: TLBR has been internally switched to LTRB
-
Better Polygon coercion from geojson
- Added rotate to Coords and Polygon
- Added arg to control where text is drawn on
Boxes.draw_on.
- GPG Keys needed to be renewed
- Added support for
KWIMAGE_DISABLE_TORCHVISION_NMSenviron
- Error in
Mask.get_xywhwhen mask was empty.
- Torch and pandas are now optional
kwimage.draw_text_on_imagenow supporthalignkwimage.Boxes.draw_onnow supports different colors for each box.
- Removed explicit Python 3.5 support. Note, 3.5 should still still work using
the universal
py2.py3-none-anywheel.
- Issue with
Detections.from_cocowith keypoint categories - Fixed
kwimage.Boxes.draw_onwhen images are non-contiguous
- Add
to_boxesto MultiPolygon
- More methods in the Mask object should work without the c-extensions being built.
- The
Mask.to_cocomethod now returns a format based on the native encoding. - Support for the new is preferred "ltrb" format over "tlbr" which will eventually be deprecated.
- No longer publishing wheels / CI testing for Python 2.7
- Fix bug with check for turbojpeg in imread.
subpixel_slicenow works with non-integer slices
Detections.from_coco_annotsnow acceptsdsetkeyword argument that attempts to fill the category_id coco field.Boxes.iooas- intersection-over-other-areakwimage.imread- now has a turbojpeg backend.
- Fix bug in
Detections.from_coco_annotswhen categories are null. - Fix bug
Detections.compresswhen flags are in tensor space.
kwimage.imwritenow always returns the file path that was written to regardless of the backend.
draw_line_segments_on_image- Boxes.scale now accepts
aboutkeyword arg (can use to scale about center). - Boxes.warp now accepts matrices and does inexact corner warping
- kwimage structures
warpfunction now accepts a generic callable for mapping array-based points. - add
normalizefunction for intensity rebalance.
- Renamed
_rectify_interpolationto_coerce_interpolation. Old function is deprecated and removed in the future. _coerce_interpolationnow accepts strings for fallback interpolation flags.Detections.from_coco_annotsnow returns classes as ndsampler.CategoryTree when possible
- Added
im_filtermodule withfourier_maskfunction. - Add "amazon" demo image
- thickness to
Boxes.draw_on - add
.roundto Boxes, Points, and Coords - add
Boxes.contains - add
kwiamge.load_image_shape - add
MultiPolygon.fill kwimage.imwritenow accepts thebackendkeyword, which can becv2,skimage, orgdal. Thegdalbackend writes images as cloud-optimized-geotiffs.- add
kwimage.structs.Segmentationwhich encapsulates Masks, Polygons, and MultiPolygons - Add
im_filterwhich currently contains fourier domain filters.
- issue with
draw_clf_on_imagewhen truth is unknown
- fixed issue where non-max-suppression couldn't find a default implementation.
- Faster color casting
- Misc coco fixes.
- Tentative
Color._forimagemethod
- Simpler demo data file names.
- The kwimage.struct
draw_onmethods now operate in-place (more often) when possible.
- Fixed color in kwimage.struct
draw_onmethods. - Detections concatenate now works when segmentations are populated.
imresizenow acceptsletterboxflag.- add
numpyandtensormethods toMask
ensure_alpha_channelnow acceptsdtypeandcopykwargs.Mask.draw_onwill now draw on images larger or smaller than the mask itself
- Fixed Boxes.draw
Boxes.draw_onnow works correctly on uint8 and float32 images with 1, 3, or 4 channelsMasks.draw_onnow works correctly uint8 or float32 images- Fixed error in
draw_clf_on_images - Fixed scale error in
Detections.randomwhensegmentations=True
- "torchvision" nms mode.
- Ported pure-image drawing functions from kwplot. These are
draw_boxes_on_image,draw_clf_on_image,draw_text_on_image,make_heatmask,make_orimask,make_vector_field. - Ported Color from kwplot
- Using the new (correct) torch defaults for
align_cornersinwarp_tensorwhen possible. - Fixed bug in "numpy" nms mode.
- reworked nms auto mode
- nms impl=
cpu/gpu/pyare now deprecated forcython_cpu/cython_gpu/numpyinstead.
- First public release
- Add option (hack) to build without C-extensions
- Add
imresizeas a more powerful alternative toimscale. - The
imreadfunction now accepts abackendkwarg, which allows the user to control how an image is loaded. - Add
clipmethod toPolygon - Add
class_idxdata-key toHeatmapfor semantic segmentation support. - Add
class_energydata-key toHeatmapfor non-probabilistic output support. - Add
Detections.from_coco_annots, to create detections from COCO-style annotations. - Add
to_cocomethods to all structures. - Add
metatoPolygons
Coords.warpnow tentatively supports OSR transforms.- Continue improvements of annotation structures
- Increased efficiency of Cython CPU non-max-suppression
imreadnow read ptif and tiff files using GDAL by defaultimreadnow reads.r0images using GDAL.- Tweaked implementation of
Heatmap.random. ensure_uint255andensure_float01now raise properValueErrorsinstead of using assert statements.Pointsdraw methods now accept 'classes' as a color arg
imreadcan now handle nsf and color table images.- Python2 issues with
Boxes.__repr__ - Can now correctly draw 1D
Boxesobjects - Python2 issues mask shape using List[long] instead of List[int]
- Zero division in Cython
non-maximum-supressionwith zero sized boxes. Heatmap.shapenow works even ifclass_probsis not set.Coords.warpnow works with tensors.Coords.warpuses nearest neighbor interpolation for integer warping.
- Heatmap.warp may have some odd behavior and emit warnings.
- Add
Detections.rasterizemethod to which is a lossy "pseudo-inverse" ofHeatmap.detect. - All classes in
kwimage.structsshould now have warp and draw method - Add
subpixel_setvalueandsubpixel_getvalue - Add
Coordsdata structure - Add
Maskdata structure - Add
Pointsdata structure - Add
Polygondata structure - Add
_generic.ObjectListdata structure forMaskListandPointsList. - Add
util_warp.warp_points
- Speedup
overlay_alpha_layersby bypassing redundantnp.dstackoperations. - Changed
encode_run_lengthto return a dictionary - Add
output_shapeandinput_shapeas generally accepted kwargs for warp (even if they are unused) - Spatial data structure
warpmethods can now acceptimgaugaugmenters - Add checks to detection types
- Initial port of image-related utility code from KWIL. This includes:
- non-maximum suppression
BoxesDetectionsHeatmapim_stackim_coreim_ioim_demodataim_miscutil_warpim_runlenim_cv2im_alphablend