RLE is run-length encoding. It is used to encode the location of foreground objects in segmentation. Instead of outputting a mask image, you give a list of start pixels and how many pixels after each of those starts is included in the mask.
The encoding rule is pretty simple: Where the mask is. Index of the mask, and how many pixels follows.
Here are 2 examples of how RLE works.
Example 1:
[0, 0, 0, 1, 0].
Mask2Rle encode: ‘4 1’
Example 2:
[[0, 0 , 0, 1, 0],[1,0,1,1,1]]
Mask2Rle encode: ‘4 1 6 1 8 3’
Python Code:
# ref.: https://www.kaggle.com/stainsby/fast-tested-rle
def mask2rle(img):
"""
img: numpy array, 1 - mask, 0 - background
Returns run length as string formatted
"""
pixels = img.flatten()
pixels = np.concatenate([[0], pixels, [0]])
runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
runs[1::2] -= runs[::2]
return ' '.join(str(x) for x in runs)
def rle2mask(mask_rle: str, label=1, shape=DEFAULT_IMAGE_SHAPE):
"""
mask_rle: run-length as string formatted (start length)
shape: (height,width) of array to return
Returns numpy array, 1 - mask, 0 - background
"""
s = mask_rle.split()
starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]
starts -= 1
ends = starts + lengths
img = np.zeros(shape[0] * shape[1], dtype=np.uint8)
for lo, hi in zip(starts, ends):
img[lo:hi] = label
return img.reshape(shape) # Needed to align to RLE direction