kwimage.im_cv2

Wrappers around cv2 functions

Note: all functions in kwimage work with RGB input by default instead of BGR.

Module Contents

Functions

_coerce_interpolation(interpolation, default=cv2.INTER_LANCZOS4, grow_default=cv2.INTER_LANCZOS4, shrink_default=cv2.INTER_AREA, scale=None)

Converts interpolation into flags suitable cv2 functions

_coerce_border(border_mode, default=cv2.BORDER_CONSTANT)

Converts border_mode into flags suitable cv2 functions

imscale(img, scale, interpolation=None, return_scale=False)

DEPRECATED and removed: use imresize instead

imcrop(img, dsize, about=None, origin=None, border_value=None, interpolation='nearest')

Crop an image about a specified point, padding if necessary.

imresize(img, scale=None, dsize=None, max_dim=None, min_dim=None, interpolation=None, grow_interpolation=None, letterbox=False, return_info=False, antialias=False)

Resize an image based on a scale factor, final size, or size and aspect

convert_colorspace(img, src_space, dst_space, copy=False, implicit=False, dst=None)

Converts colorspace of img.

_lookup_cv2_colorspace_conversion_code(src_space, dst_space)

gaussian_patch(shape=(7, 7), sigma=None)

Creates a 2D gaussian patch with a specific size and sigma

warp_affine(image, transform, dsize=None, antialias=False, interpolation='linear', border_mode=None, border_value=0, large_warp_dim=None, return_info=False)

Applies an affine transformation to an image with optional antialiasing.

_try_warp(image, transform_, large_warp_dim, dsize, max_dsize, new_origin, flags, borderMode, borderValue)

Helper for warp_affine

_large_warp(image, transform_, dsize, max_dsize, new_origin, flags, borderMode, borderValue, pieces_per_dim)

Split an image into pieces smaller than cv2’s limit, perform cv2.warpAffine on each piece,

_prepare_downscale(image, sx, sy)

Does a partial downscale with antialiasing and prepares for a final

_gauss_params(scale, k0=5, sigma0=1, fractional=True)

Compute a gaussian to mitigate aliasing for a requested downsample

_pyrDownK(a, k=1)

Downsamples by (2 ** k)x with antialiasing

Attributes

_CV2_INTERPOLATION_TYPES

_CV2_BORDER_MODES

kwimage.im_cv2._CV2_INTERPOLATION_TYPES[source]
kwimage.im_cv2._CV2_BORDER_MODES[source]
kwimage.im_cv2._coerce_interpolation(interpolation, default=cv2.INTER_LANCZOS4, grow_default=cv2.INTER_LANCZOS4, shrink_default=cv2.INTER_AREA, scale=None)[source]

Converts interpolation into flags suitable cv2 functions

Parameters
  • interpolation (int or str) – string or cv2-style interpolation type

  • default (int) – cv2 flag to use if interpolation is None and scale is None.

  • grow_default (int) – cv2 flag to use if interpolation is None and scale is greater than or equal to 1.

  • shrink_default (int) – cv2 flag to use if interpolation is None and scale is less than 1.

  • scale (float) – indicate if the interpolation will be used to scale the image.

Returns

flag specifying interpolation type that can be passed to

functions like cv2.resize, cv2.warpAffine, etc…

Return type

int

Example

>>> flag = _coerce_interpolation('linear')
>>> assert flag == cv2.INTER_LINEAR
>>> flag = _coerce_interpolation(cv2.INTER_LINEAR)
>>> assert flag == cv2.INTER_LINEAR
>>> flag = _coerce_interpolation('auto', default='lanczos')
>>> assert flag == cv2.INTER_LANCZOS4
>>> flag = _coerce_interpolation(None, default='lanczos')
>>> assert flag == cv2.INTER_LANCZOS4
>>> flag = _coerce_interpolation('auto', shrink_default='area', scale=0.1)
>>> assert flag == cv2.INTER_AREA
>>> flag = _coerce_interpolation('auto', grow_default='cubic', scale=10.)
>>> assert flag == cv2.INTER_CUBIC
>>> # xdoctest: +REQUIRES(module:pytest)
>>> import pytest
>>> with pytest.raises(TypeError):
>>>     _coerce_interpolation(3.4)
>>> import pytest
>>> with pytest.raises(KeyError):
>>>     _coerce_interpolation('foobar')
kwimage.im_cv2._coerce_border(border_mode, default=cv2.BORDER_CONSTANT)[source]

Converts border_mode into flags suitable cv2 functions

Parameters

border_mode (int or str) – string or cv2-style interpolation type

Returns

flag specifying borderMode type that can be passed to

functions like cv2.warpAffine, etc…

Return type

int

Example

>>> flag = _coerce_border('constant')
>>> assert flag == cv2.BORDER_CONSTANT
>>> flag = _coerce_border(cv2.BORDER_CONSTANT)
>>> assert flag == cv2.BORDER_CONSTANT
>>> flag = _coerce_border(None, default='reflect')
>>> assert flag == cv2.BORDER_REFLECT
>>> # xdoctest: +REQUIRES(module:pytest)
>>> import pytest
>>> with pytest.raises(TypeError):
>>>     _coerce_border(3.4)
>>> import pytest
>>> with pytest.raises(KeyError):
>>>     _coerce_border('foobar')
kwimage.im_cv2.imscale(img, scale, interpolation=None, return_scale=False)[source]

DEPRECATED and removed: use imresize instead

kwimage.im_cv2.imcrop(img, dsize, about=None, origin=None, border_value=None, interpolation='nearest')[source]

Crop an image about a specified point, padding if necessary.

This is like PIL.Image.Image.crop with more convenient arguments, or cv2.getRectSubPix without the baked-in bilinear interpolation.

Parameters
  • img (ndarray) – image to crop

  • dsize (Tuple[None | int, None | int]) – the desired width and height of the new image. If a dimension is None, then it is automatically computed to preserve aspect ratio. This can be larger than the original dims; if so, the cropped image is padded with border_value.

  • about (Tuple[str | int, str | int]) – the location to crop about. Mutually exclusive with origin. Defaults to top left. If ints (w,h) are provided, that will be the center of the cropped image. There are also string codes available: ‘lt’: make the top left point of the image the top left point of

    the cropped image. This is equivalent to img[:dsize[1], :dsize[0]], plus padding.

    ‘rb’: make the bottom right point of the image the bottom right

    point of the cropped image. This is equivalent to img[-dsize[1]:, -dsize[0]:], plus padding.

    ‘cc’: make the center of the image the center of the cropped image. Any combination of these codes can be used, ex. ‘lb’, ‘ct’, (‘r’, 200), …

  • origin (Tuple[int, int] | None) – the origin of the crop in (x,y) order (same order as dsize/about). Mutually exclusive with about. Defaults to top left.

  • border_value (Numeric | Tuple | str, default=0) – any border border_value accepted by cv2.copyMakeBorder, ex. [255, 0, 0] (blue). Default is 0.

  • interpolation (str, default=’nearest’) – Can be ‘nearest’, in which case integral cropping is used. Can also be ‘linear’, in which case cv2.getRectSubPix is used.

Returns

the cropped image

Return type

ndarray

SeeAlso:
kwarray.padded_slice() - a similar function for working with

“negative slices”.

Example

>>> import kwimage
>>> import numpy as np
>>> #
>>> img = kwimage.grab_test_image('astro', dsize=(32, 32))
>>> #
>>> # regular crop
>>> new_img1 = kwimage.imcrop(img, dsize=(5,6))
>>> assert new_img1.shape == (6, 5, 3)
>>> #
>>> # padding for coords outside the image bounds
>>> new_img2 = kwimage.imcrop(img, dsize=(5,6),
>>>             origin=(-1,0), border_value=[1, 0, 0])
>>> assert np.all(new_img2[:, 0] == [1, 0, 0])
>>> #
>>> # codes for corner- and edge-centered cropping
>>> new_img3 = kwimage.imcrop(img, dsize=(5,6),
>>>             about='cb')
>>> #
>>> # special code for bilinear interpolation
>>> # with floating-point coordinates
>>> new_img4 = kwimage.imcrop(img, dsize=(5,6),
>>>             about=(5.5, 8.5), interpolation='linear')
>>> #
>>> # use with bounding boxes
>>> bbox = kwimage.Boxes.random(scale=5, rng=132).to_xywh().quantize()
>>> origin, dsize = np.split(bbox.data[0], 2)
>>> new_img5 = kwimage.imcrop(img, dsize=dsize,
>>>             origin=origin)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> pnum_ = kwplot.PlotNums(nSubplots=6)
>>> kwplot.imshow(img, pnum=pnum_())
>>> kwplot.imshow(new_img1, pnum=pnum_())
>>> kwplot.imshow(new_img2, pnum=pnum_())
>>> kwplot.imshow(new_img3, pnum=pnum_())
>>> kwplot.imshow(new_img4, pnum=pnum_())
>>> kwplot.imshow(new_img5, pnum=pnum_())
>>> kwplot.show_if_requested()
kwimage.im_cv2.imresize(img, scale=None, dsize=None, max_dim=None, min_dim=None, interpolation=None, grow_interpolation=None, letterbox=False, return_info=False, antialias=False)[source]

Resize an image based on a scale factor, final size, or size and aspect ratio.

Slightly more general than cv2.resize, allows for specification of either a scale factor, a final size, or the final size for a particular dimension.

Parameters
  • img (ndarray) – image to resize

  • scale (float or Tuple[float, float]) – Desired floating point scale factor. If a tuple, the dimension ordering is x,y. Mutually exclusive with dsize, max_dim, and min_dim.

  • dsize (Tuple[int] | None) – The desired with and height of the new image. If a dimension is None, then it is automatically computed to preserve aspect ratio. Mutually exclusive with size, max_dim, and min_dim.

  • max_dim (int) – New size of the maximum dimension, the other dimension is scaled to maintain aspect ratio. Mutually exclusive with size, dsize, and min_dim.

  • min_dim (int) – New size of the minimum dimension, the other dimension is scaled to maintain aspect ratio.Mutually exclusive with size, dsize, and max_dim.

  • interpolation (str | int) – The interpolation key or code (e.g. linear lanczos). By default “area” is used if the image is shrinking and “lanczos” is used if the image is growing. Note, if this is explicitly set, then it will be used regardless of if the image is growing or shrinking. Set grow_interpolation to change the default for an enlarging interpolation.

  • grow_interpolation (str | int, default=”lanczos”) – The interpolation key or code to use when the image is being enlarged. Does nothing if “interpolation” is explicitly given. If “interpolation” is not specified “area” is used when shrinking.

  • letterbox (bool, default=False) – If used in conjunction with dsize, then the image is scaled and translated to fit in the center of the new image while maintaining aspect ratio. Zero padding is added if necessary.

  • return_info (bool, default=False) – if True returns information about the final transformation in a dictionary. If there is an offset, the scale is applied before the offset when transforming to the new resized space.

  • antialias (bool, default=False) – if True blurs to anti-alias before downsampling.

Returns

the new image and optionally an info dictionary if return_info=True

Return type

ndarray | Tuple[ndarray, Dict]

Example

>>> import kwimage
>>> import numpy as np
>>> # Test scale
>>> img = np.zeros((16, 10, 3), dtype=np.uint8)
>>> new_img, info = kwimage.imresize(img, scale=.85,
>>>                                  interpolation='area',
>>>                                  return_info=True)
>>> print('info = {!r}'.format(info))
>>> assert info['scale'].tolist() == [.8, 0.875]
>>> # Test dsize without None
>>> new_img, info = kwimage.imresize(img, dsize=(5, 12),
>>>                                  interpolation='area',
>>>                                  return_info=True)
>>> print('info = {!r}'.format(info))
>>> assert info['scale'].tolist() == [0.5 , 0.75]
>>> # Test dsize with None
>>> new_img, info = kwimage.imresize(img, dsize=(6, None),
>>>                                  interpolation='area',
>>>                                  return_info=True)
>>> print('info = {!r}'.format(info))
>>> assert info['scale'].tolist() == [0.6, 0.625]
>>> # Test max_dim
>>> new_img, info = kwimage.imresize(img, max_dim=6,
>>>                                  interpolation='area',
>>>                                  return_info=True)
>>> print('info = {!r}'.format(info))
>>> assert info['scale'].tolist() == [0.4  , 0.375]
>>> # Test min_dim
>>> new_img, info = kwimage.imresize(img, min_dim=6,
>>>                                  interpolation='area',
>>>                                  return_info=True)
>>> print('info = {!r}'.format(info))
>>> assert info['scale'].tolist() == [0.6  , 0.625]

Example

>>> import kwimage
>>> import numpy as np
>>> # Test letterbox resize
>>> img = np.ones((5, 10, 3), dtype=np.float32)
>>> new_img, info = kwimage.imresize(img, dsize=(19, 19),
>>>                                  letterbox=True,
>>>                                  return_info=True)
>>> print('info = {!r}'.format(info))
>>> assert info['offset'].tolist() == [0, 4]
>>> img = np.ones((10, 5, 3), dtype=np.float32)
>>> new_img, info = kwimage.imresize(img, dsize=(19, 19),
>>>                                  letterbox=True,
>>>                                  return_info=True)
>>> print('info = {!r}'.format(info))
>>> assert info['offset'].tolist() == [4, 0]
>>> import kwimage
>>> import numpy as np
>>> # Test letterbox resize
>>> img = np.random.rand(100, 200)
>>> new_img, info = kwimage.imresize(img, dsize=(300, 300), letterbox=True, return_info=True)

Example

>>> # Check aliasing
>>> import kwimage
>>> img = kwimage.grab_test_image('checkerboard')
>>> img = kwimage.grab_test_image('astro')
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> dsize = (14, 14)
>>> dsize = (64, 64)
>>> # When we set "grow_interpolation" for a "shrinking" resize it should
>>> # still do the "area" interpolation to antialias the results. But if we
>>> # use explicit interpolation it should alias.
>>> pnum_ = kwplot.PlotNums(nSubplots=12, nCols=4)
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True,  interpolation='area'), pnum=pnum_(), title='resize aa area')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True, interpolation='linear'), pnum=pnum_(), title='resize aa linear')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True, interpolation='nearest'), pnum=pnum_(), title='resize aa nearest')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True, interpolation='cubic'), pnum=pnum_(), title='resize aa cubic')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True, grow_interpolation='area'), pnum=pnum_(), title='resize aa grow area')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True, grow_interpolation='linear'), pnum=pnum_(), title='resize aa grow linear')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True, grow_interpolation='nearest'), pnum=pnum_(), title='resize aa grow nearest')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=True, grow_interpolation='cubic'), pnum=pnum_(), title='resize aa grow cubic')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=False, interpolation='area'), pnum=pnum_(), title='resize no-aa area')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=False, interpolation='linear'), pnum=pnum_(), title='resize no-aa linear')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=False, interpolation='nearest'), pnum=pnum_(), title='resize no-aa nearest')
>>> kwplot.imshow(kwimage.imresize(img, dsize=dsize, antialias=False, interpolation='cubic'), pnum=pnum_(), title='resize no-aa cubic')

Todo

  • [X] When interpolation is area and the number of channels > 4

    cv2.resize will error but it is fine for linear interpolation

  • [ ] TODO: add padding options when letterbox=True

kwimage.im_cv2.convert_colorspace(img, src_space, dst_space, copy=False, implicit=False, dst=None)[source]

Converts colorspace of img. Convenience function around cv2.cvtColor

Parameters
  • img (ndarray) – image data with float32 or uint8 precision

  • src_space (str) – input image colorspace. (e.g. BGR, GRAY)

  • dst_space (str) – desired output colorspace. (e.g. RGB, HSV, LAB)

  • implicit (bool) –

    if False, the user must correctly specify if the input/output

    colorspaces contain alpha channels.

    If True and the input image has an alpha channel, we modify

    src_space and dst_space to ensure they both end with “A”.

  • dst (ndarray[uint8_t, ndim=2], optional) – inplace-output array.

Returns

img - image data

Return type

ndarray

Note

Note the LAB and HSV colorspaces in float do not go into the 0-1 range.

For HSV the floating point range is:

0:360, 0:1, 0:1

For LAB the floating point range is:

0:100, -86.1875:98.234375, -107.859375:94.46875 (Note, that some extreme combinations of a and b are not valid)

Example

>>> import numpy as np
>>> convert_colorspace(np.array([[[0, 0, 1]]], dtype=np.float32), 'RGB', 'LAB')
>>> convert_colorspace(np.array([[[0, 1, 0]]], dtype=np.float32), 'RGB', 'LAB')
>>> convert_colorspace(np.array([[[1, 0, 0]]], dtype=np.float32), 'RGB', 'LAB')
>>> convert_colorspace(np.array([[[1, 1, 1]]], dtype=np.float32), 'RGB', 'LAB')
>>> convert_colorspace(np.array([[[0, 0, 1]]], dtype=np.float32), 'RGB', 'HSV')
Ignore:

# Check LAB output ranges import itertools as it s = 1 _iter = it.product(range(0, 256, s), range(0, 256, s), range(0, 256, s)) minvals = np.full(3, np.inf) maxvals = np.full(3, -np.inf) for r, g, b in ub.ProgIter(_iter, total=(256 // s) ** 3):

img255 = np.array([[[r, g, b]]], dtype=np.uint8) img01 = (img255 / 255.0).astype(np.float32) lab = convert_colorspace(img01, ‘rgb’, ‘lab’) np.minimum(lab[0, 0], minvals, out=minvals) np.maximum(lab[0, 0], maxvals, out=maxvals)

print(‘minvals = {}’.format(ub.repr2(minvals, nl=0))) print(‘maxvals = {}’.format(ub.repr2(maxvals, nl=0)))

kwimage.im_cv2._lookup_cv2_colorspace_conversion_code(src_space, dst_space)[source]
kwimage.im_cv2.gaussian_patch(shape=(7, 7), sigma=None)[source]

Creates a 2D gaussian patch with a specific size and sigma

Parameters
  • shape (Tuple[int, int]) – patch height and width

  • sigma (float | Tuple[float, float]) – Gaussian standard deviation

References

http://docs.opencv.org/modules/imgproc/doc/filtering.html#getgaussiankernel

CommandLine:

xdoctest -m kwimage.im_cv2 gaussian_patch –show

Example

>>> import numpy as np
>>> shape = (88, 24)
>>> sigma = None  # 1.0
>>> gausspatch = gaussian_patch(shape, sigma)
>>> sum_ = gausspatch.sum()
>>> assert np.all(np.isclose(sum_, 1.0))
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> norm = (gausspatch - gausspatch.min()) / (gausspatch.max() - gausspatch.min())
>>> kwplot.imshow(norm)
>>> kwplot.show_if_requested()

Example

>>> import numpy as np
>>> shape = (24, 24)
>>> sigma = 3.0
>>> gausspatch = gaussian_patch(shape, sigma)
>>> sum_ = gausspatch.sum()
>>> assert np.all(np.isclose(sum_, 1.0))
>>> # xdoc: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> norm = (gausspatch - gausspatch.min()) / (gausspatch.max() - gausspatch.min())
>>> kwplot.imshow(norm)
>>> kwplot.show_if_requested()
kwimage.im_cv2.warp_affine(image, transform, dsize=None, antialias=False, interpolation='linear', border_mode=None, border_value=0, large_warp_dim=None, return_info=False)[source]

Applies an affine transformation to an image with optional antialiasing.

Parameters
  • image (ndarray) – the input image as a numpy array. Note: this is passed directly to cv2, so it is best to ensure that it is contiguous and using a dtype that cv2 can handle.

  • transform (ndarray | Affine) – a coercable affine matrix. See kwimage.Affine for details on what can be coerced.

  • dsize (Tuple[int, int] | None | str, default=None) – A integer width and height tuple of the resulting “canvas” image. If None, then the input image size is used.

    If specified as a string, dsize is computed based on the given heuristic.

    If ‘positive’ (or ‘auto’), dsize is computed such that the positive coordinates of the warped image will fit in the new canvas. In this case, any pixel that maps to a negative coordinate will be clipped. This has the property that the input transformation is not modified.

    If ‘content’ (or ‘max’), the transform is modified with an extra translation such that both the positive and negative coordinates of the warped image will fit in the new canvas.

  • antialias (bool, default=False) – if True determines if the transform is downsampling and applies antialiasing via gaussian a blur.

  • interpolation (str, default=”linear”) – interpolation code or cv2 integer. Interpolation codes are linear, nearest, cubic, lancsoz, and area.

  • border_mode (str) – Border code or cv2 integer. Border codes are constant replicate, reflect, wrap, reflect101, and transparent.

  • border_value (int | float) – Used as the fill value if border_mode is constant. Otherwise this is ignored.

  • large_warp_dim (int | None | str, default=None) – If specified, perform the warp piecewise in chunks of the specified size. If “auto”, it is set to the maximum “short” value in numpy. This works around a limitation of cv2.warpAffine, which must have image dimensions < SHRT_MAX (=32767 in version 4.5.3)

  • return_info (bool, default=Fasle) – if True, returns information about the operation. In the case where dsize=”content”, this includes the modified transformation.

Returns

the warped image, or if return info is True, the warped image and the info dictionary.

Return type

ndarray | Tuple[ndarray, Dict]

Example

>>> from kwimage.im_cv2 import *  # NOQA
>>> import kwimage
>>> from kwimage.transform import Affine
>>> image = kwimage.grab_test_image('astro')
>>> #image = kwimage.grab_test_image('checkerboard')
>>> transform = Affine.random() @ Affine.scale(0.05)
>>> transform = Affine.scale(0.02)
>>> warped1 = warp_affine(image, transform, dsize='positive', antialias=1, interpolation='nearest')
>>> warped2 = warp_affine(image, transform, dsize='positive', antialias=0)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> pnum_ = kwplot.PlotNums(nRows=1, nCols=2)
>>> kwplot.imshow(warped1, pnum=pnum_(), title='antialias=True')
>>> kwplot.imshow(warped2, pnum=pnum_(), title='antialias=False')
>>> kwplot.show_if_requested()

Example

>>> from kwimage.im_cv2 import *  # NOQA
>>> import kwimage
>>> from kwimage.transform import Affine
>>> image = kwimage.grab_test_image('astro')
>>> image = kwimage.grab_test_image('checkerboard')
>>> transform = Affine.random() @ Affine.scale((.1, 1.2))
>>> warped1 = warp_affine(image, transform, dsize='positive', antialias=1)
>>> warped2 = warp_affine(image, transform, dsize='positive', antialias=0)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> pnum_ = kwplot.PlotNums(nRows=1, nCols=2)
>>> kwplot.imshow(warped1, pnum=pnum_(), title='antialias=True')
>>> kwplot.imshow(warped2, pnum=pnum_(), title='antialias=False')
>>> kwplot.show_if_requested()

Example

>>> # Test the case where the input data is empty or the target canvas
>>> # is empty, this should be handled like boundary effects
>>> import kwimage
>>> image = np.random.rand(1, 1, 3)
>>> transform = kwimage.Affine.random()
>>> result = kwimage.warp_affine(image, transform, dsize=(0, 0))
>>> assert result.shape == (0, 0, 3)
>>> #
>>> empty_image = np.random.rand(0, 1, 3)
>>> result = kwimage.warp_affine(empty_image, transform, dsize=(10, 10))
>>> assert result.shape == (10, 10, 3)
>>> #
>>> empty_image = np.random.rand(0, 1, 3)
>>> result = kwimage.warp_affine(empty_image, transform, dsize=(10, 0))
>>> assert result.shape == (0, 10, 3)

Example

>>> # Demo difference between positive and content dsize
>>> from kwimage.im_cv2 import *  # NOQA
>>> import kwimage
>>> from kwimage.transform import Affine
>>> image = kwimage.grab_test_image('astro', dsize=(512, 512))
>>> transform = Affine.coerce(offset=(-100, -50), scale=2, theta=0.1)
>>> # When warping other images or geometry along with this image
>>> # it is important to account for the modified transform when
>>> # setting dsize='content'. If dsize='positive', the transform
>>> # will remain unchanged wrt other aligned images / geometries.
>>> poly = kwimage.Boxes([[350, 5, 130, 290]], 'xywh').to_polygons()[0]
>>> # Apply the warping to the images
>>> warped_pos, info_pos = warp_affine(image, transform, dsize='positive', return_info=True)
>>> warped_con, info_con = warp_affine(image, transform, dsize='content', return_info=True)
>>> assert info_pos['dsize'] == (919, 1072)
>>> assert info_con['dsize'] == (1122, 1122)
>>> assert info_pos['transform'] == transform
>>> # Demo the correct and incorrect way to apply transforms
>>> poly_pos = poly.warp(transform)
>>> poly_con = poly.warp(info_con['transform'])
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> # show original
>>> kwplot.imshow(image, pnum=(1, 3, 1), title='original')
>>> poly.draw(color='green', alpha=0.5, border=True)
>>> # show positive warped
>>> kwplot.imshow(warped_pos, pnum=(1, 3, 2), title='dsize=positive')
>>> poly_pos.draw(color='purple', alpha=0.5, border=True)
>>> # show content warped
>>> ax = kwplot.imshow(warped_con, pnum=(1, 3, 3), title='dsize=content')[1]
>>> poly_con.draw(color='dodgerblue', alpha=0.5, border=True)   # correct
>>> poly_pos.draw(color='orangered', alpha=0.5, border=True)  # incorrect
>>> cc = poly_con.to_shapely().centroid
>>> cp = poly_pos.to_shapely().centroid
>>> ax.text(cc.x, cc.y + 250, 'correctly transformed', color='dodgerblue',
>>>         backgroundcolor=(0, 0, 0, 0.7), horizontalalignment='center')
>>> ax.text(cp.x, cp.y - 250, 'incorrectly transformed', color='orangered',
>>>         backgroundcolor=(0, 0, 0, 0.7), horizontalalignment='center')
>>> kwplot.show_if_requested()

Example

>>> # Demo piecewise transform
>>> from kwimage.im_cv2 import *  # NOQA
>>> import kwimage
>>> from kwimage.transform import Affine
>>> image = kwimage.grab_test_image('astro', dsize=(512, 512))
>>> transform = Affine.coerce(offset=(-100, -50), scale=2, theta=0.1)
>>> warped_piecewise, info = warp_affine(image, transform, dsize='positive', return_info=True, large_warp_dim=32)
>>> warped_normal, info = warp_affine(image, transform, dsize='positive', return_info=True, large_warp_dim=None)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(image, pnum=(1, 3, 1), title='original')
>>> kwplot.imshow(warped_normal, pnum=(1, 3, 2), title='normal warp')
>>> kwplot.imshow(warped_piecewise, pnum=(1, 3, 3), title='piecewise warp')
kwimage.im_cv2._try_warp(image, transform_, large_warp_dim, dsize, max_dsize, new_origin, flags, borderMode, borderValue)[source]

Helper for warp_affine

kwimage.im_cv2._large_warp(image, transform_, dsize, max_dsize, new_origin, flags, borderMode, borderValue, pieces_per_dim)[source]

Split an image into pieces smaller than cv2’s limit, perform cv2.warpAffine on each piece, and stitch them back together with minimal artifacts.

Example

>>> # xdoctest: +REQUIRES(--large_memory)
>>> import kwimage
>>> img = np.random.randint(255, size=(32767, 32767), dtype=np.uint8)
>>> aff = kwimage.Affine.random()
>>> import cv2
>>> #
>>> # without this function
>>> try:
>>>     res = kwimage.warp_affine(img, aff, large_warp_dim=None)
>>> except cv2.error as e:
>>>     pass
>>> #
>>> # with this function
>>> res = kwimage.warp_affine(img, aff, large_warp_dim='auto')
>>> assert res.shape == img.shape
>>> assert res.dtype == img.dtype

Example

>>> import kwimage
>>> import cv2
>>> image = kwimage.grab_test_image('astro')
>>> # Use wrapper function
>>> transform = kwimage.Affine.coerce(
>>>     {'offset': (136.3946757082253, 0.0),
>>>      'scale': (1.7740542832875767, 1.0314621286400032),
>>>      'theta': 0.2612311452107956,
>>>      'type': 'affine'})
>>> res, info = kwimage.warp_affine(
>>>     image, transform, dsize='content', return_info=True,
>>>     large_warp_dim=128)
>>> # Explicit args for this function
>>> transform = info['transform']
>>> new_origin = np.array((0, 0))
>>> max_dsize = (1015, 745)
>>> dsize = max_dsize
>>> res2 = _large_warp(image, transform, dsize, max_dsize, new_origin,
>>>                   flags=cv2.INTER_LINEAR, borderMode=None,
>>>                   borderValue=None, pieces_per_dim=2)
>>> # xdoctest: +REQUIRES(--show)
>>> import kwplot
>>> kwplot.autompl()
>>> kwplot.imshow(res, pnum=(1, 2, 1))
>>> kwplot.imshow(res2, pnum=(1, 2, 2))
kwimage.im_cv2._prepare_downscale(image, sx, sy)[source]

Does a partial downscale with antialiasing and prepares for a final downsampling. Only downscales by factors of 2, any residual scaling to be done is returned.

Example

>>> s = 523
>>> image = np.random.rand(s, s)
>>> sx = sy = 1 / 11
>>> downsampled, rx, ry = _prepare_downscale(image, sx, sy)
kwimage.im_cv2._gauss_params(scale, k0=5, sigma0=1, fractional=True)[source]

Compute a gaussian to mitigate aliasing for a requested downsample

Parameters
  • scale – requested downsample factor

  • k0 (int) – kernel size for one downsample operation

  • sigma0 (float) – sigma for one downsample operation

  • fractional (bool) – controls if we compute params for integer downsample

  • ops

kwimage.im_cv2._pyrDownK(a, k=1)[source]

Downsamples by (2 ** k)x with antialiasing