kwimage.im_runlen module¶
Logic pertaining to run-length encodings. Can encode an ndarray as a RLE or decode an RLE into an ndarray.
- SeeAlso:
- kwimage.structs.mask - stores binary segmentation masks, using RLEs as a
backend representation. Also contains cython logic for handling the coco-rle format.
- 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) – 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 (str) – Order of the encoding. Either ‘C’ for row major or ‘F’ for column-major. Defaults to ‘C’.
- 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 (str):
Encoding order, either ‘C’ for row major or ‘F’ for column-major. Defaults to ‘C’.
- Return type
- SeeAlso:
kwimage.Mask
-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]
Example
>>> # Test empty case >>> from kwimage.im_runlen import * # NOQA >>> binary = True >>> img = np.zeros((0, 0), dtype=np.uint8) >>> encoding = encode_run_length(img, binary=True) >>> assert encoding['counts'].tolist() == [] >>> recon = decode_run_length(**encoding) >>> assert np.all(recon == img)
Example
>>> # Test small full cases >>> for d in [0, 1, 2, 3]: >>> img = np.zeros((d, d), dtype=np.uint8) >>> encoding = encode_run_length(img, binary=True) >>> recon = decode_run_length(**encoding) >>> assert np.all(recon == img) >>> img = np.ones((d, d), dtype=np.uint8) >>> encoding = encode_run_length(img, binary=True) >>> recon = decode_run_length(**encoding) >>> assert np.all(recon == img)
- kwimage.im_runlen.decode_run_length(counts, shape, binary=False, dtype=<class 'numpy.uint8'>, order='C')[source]¶
Decode run length encoding back into an image.
- Parameters
counts (ndarray) – the run-length encoding
shape (Tuple[int, int]) – the height / width of the mask
binary (bool) – if the RLE is binary or non-binary. Set to True for compatibility with COCO.
dtype (type) – data type for decoded image. Defaults to np.uint8.
order (str) – Order of the encoding. Either ‘C’ for row major or ‘F’ for column-major. Defaults to ‘C’.
- 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
kwimage.encode_run_length()
offset (Tuple[int, int]) – x, y integer offsets.
output_shape (Tuple[int, int]) – 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]]