kwimage.im_runlen
¶
Logic pertaining to run-length encodings
- SeeAlso:
- kwimage.structs.mask - stores binary segmentation masks, using RLEs as a
backend representation. Also contains cython logic for handling the coco-rle format.
Module Contents¶
Functions¶
|
Construct the run length encoding (RLE) of an image. |
|
Decode run length encoding back into an image. |
|
Translates a run-length encoded image in RLE-space. |
|
Uncompresses a coco-bytes RLE into an array representation. |
|
Compresses an array RLE into a coco-bytes RLE. |
- kwimage.im_runlen.encode_run_length(img, binary=False, order='C')[source]¶
Construct the run length encoding (RLE) of an image.
- Parameters
img (ndarray) – 2D image
binary (bool, default=False) – If true, assume that the input image only contains 0’s and 1’s. Set to True for compatibility with COCO (which does not support multi-value RLE encodings).
order ({‘C’, ‘F’}, default=’C’) – row-major (C) or column-major (F)
- Returns
encoding: dictionary items are:
counts (ndarray): the run length encoding
- shape (Tuple): the original image shape.
This should be in standard shape row-major (e.g. h/w) order
- binary (bool):
if True, the counts are assumed to encode only 0’s and 1’s, otherwise the counts encoding specifies any numeric values.
order ({‘C’, ‘F’}, default=’C’): encoding order
- Return type
- SeeAlso:
kwimage.Mask - a cython-backed data structure to handle coco-style RLEs
Example
>>> import ubelt as ub >>> lines = ub.codeblock( >>> ''' >>> .......... >>> ......111. >>> ..2...111. >>> .222..111. >>> 22222..... >>> .222...... >>> ..2....... >>> ''').replace('.', '0').splitlines() >>> img = np.array([list(map(int, line)) for line in lines]) >>> encoding = encode_run_length(img) >>> target = np.array([0,16,1,3,0,3,2,1,0,3,1,3,0,2,2,3,0,2,1,3,0,1,2,5,0,6,2,3,0,8,2,1,0,7]) >>> assert np.all(target == encoding['counts'])
Example
>>> binary = True >>> img = np.array([[1, 0, 1, 1, 1, 0, 0, 1, 0]]) >>> encoding = encode_run_length(img, binary=True) >>> assert encoding['counts'].tolist() == [0, 1, 1, 3, 2, 1, 1]
- kwimage.im_runlen.decode_run_length(counts, shape, binary=False, dtype=np.uint8, order='C')[source]¶
Decode run length encoding back into an image.
- Parameters
counts (ndarray) – the run-length encoding
shape (Tuple[int, int])
binary (bool) – if the RLE is binary or non-binary. Set to True for compatibility with COCO.
dtype (dtype, default=np.uint8) – data type for decoded image
order ({‘C’, ‘F’}, default=’C’) – row-major (C) or column-major (F)
- Returns
the reconstructed image
- Return type
ndarray
Example
>>> from kwimage.im_runlen import * # NOQA >>> img = np.array([[1, 0, 1, 1, 1, 0, 0, 1, 0]]) >>> encoded = encode_run_length(img, binary=True) >>> recon = decode_run_length(**encoded) >>> assert np.all(recon == img)
>>> import ubelt as ub >>> lines = ub.codeblock( >>> ''' >>> .......... >>> ......111. >>> ..2...111. >>> .222..111. >>> 22222..... >>> .222...... >>> ..2....... >>> ''').replace('.', '0').splitlines() >>> img = np.array([list(map(int, line)) for line in lines]) >>> encoded = encode_run_length(img) >>> recon = decode_run_length(**encoded) >>> assert np.all(recon == img)
- kwimage.im_runlen.rle_translate(rle, offset, output_shape=None)[source]¶
Translates a run-length encoded image in RLE-space.
- Parameters
rle (dict) – an enconding dict returned by encode_run_length
offset (Tuple) – x,y offset, CAREFUL, this can only accept integers
output_shape (Tuple, optional) – h,w of transformed mask. If unspecified the input rle shape is used.
- SeeAlso:
# ITK has some RLE code that looks like it can perform translations https://github.com/KitwareMedical/ITKRLEImage/blob/master/include/itkRLERegionOfInterestImageFilter.h
- Doctest:
>>> # test that translate works on all zero images >>> img = np.zeros((7, 8), dtype=np.uint8) >>> rle = encode_run_length(img, binary=True, order='F') >>> new_rle = rle_translate(rle, (1, 2), (6, 9)) >>> assert np.all(new_rle['counts'] == [54])
Example
>>> from kwimage.im_runlen import * # NOQA >>> img = np.array([ >>> [1, 1, 1, 1], >>> [0, 1, 0, 0], >>> [0, 1, 0, 1], >>> [1, 1, 1, 1],], dtype=np.uint8) >>> rle = encode_run_length(img, binary=True, order='C') >>> offset = (1, -1) >>> output_shape = (3, 5) >>> new_rle = rle_translate(rle, offset, output_shape) >>> decoded = decode_run_length(**new_rle) >>> print(decoded) [[0 0 1 0 0] [0 0 1 0 1] [0 1 1 1 1]]
Example
>>> from kwimage.im_runlen import * # NOQA >>> img = np.array([ >>> [0, 0, 0], >>> [0, 1, 0], >>> [0, 0, 0]], dtype=np.uint8) >>> rle = encode_run_length(img, binary=True, order='C') >>> new_rle = rle_translate(rle, (1, 0)) >>> decoded = decode_run_length(**new_rle) >>> print(decoded) [[0 0 0] [0 0 1] [0 0 0]] >>> new_rle = rle_translate(rle, (0, 1)) >>> decoded = decode_run_length(**new_rle) >>> print(decoded) [[0 0 0] [0 0 0] [0 1 0]]
- kwimage.im_runlen._rle_bytes_to_array(s, impl='auto')[source]¶
Uncompresses a coco-bytes RLE into an array representation.
- Parameters
s (bytes) – compressed coco bytes rle
impl (str) – which implementation to use (defaults to cython is possible)
- CommandLine:
xdoctest -m ~/code/kwimage/kwimage/im_runlen.py _rle_bytes_to_array
- Benchmark:
>>> import ubelt as ub >>> from kwimage.im_runlen import _rle_bytes_to_array >>> s = b';?1B10O30O4' >>> ti = ub.Timerit(1000, bestof=50, verbose=2) >>> # --- time python impl --- >>> for timer in ti.reset('python'): >>> with timer: >>> _rle_bytes_to_array(s, impl='python') >>> # --- time cython impl --- >>> # xdoctest: +REQUIRES(--mask) >>> for timer in ti.reset('cython'): >>> with timer: >>> _rle_bytes_to_array(s, impl='cython')
- kwimage.im_runlen._rle_array_to_bytes(counts, impl='auto')[source]¶
Compresses an array RLE into a coco-bytes RLE.
- Parameters
counts (ndarray) – uncompressed array rle
impl (str) – which implementation to use (defaults to cython is possible)
Example
>>> # xdoctest: +REQUIRES(--mask) >>> from kwimage.im_runlen import _rle_array_to_bytes >>> from kwimage.im_runlen import _rle_bytes_to_array >>> arr_counts = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) >>> str_counts = _rle_array_to_bytes(arr_counts) >>> arr_counts2 = _rle_bytes_to_array(str_counts) >>> assert np.all(arr_counts2 == arr_counts)
- Benchmark:
>>> # xdoctest: +REQUIRES(--mask) >>> import ubelt as ub >>> from kwimage.im_runlen import _rle_array_to_bytes >>> from kwimage.im_runlen import _rle_bytes_to_array >>> counts = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) >>> ti = ub.Timerit(1000, bestof=50, verbose=2) >>> # --- time python impl --- >>> #for timer in ti.reset('python'): >>> # with timer: >>> # _rle_array_to_bytes(s, impl='python') >>> # --- time cython impl --- >>> for timer in ti.reset('cython'): >>> with timer: >>> _rle_array_to_bytes(s, impl='cython')