A Bitmask is a type of annotation on the Encord platform that allows for pixel-wise segmentation of an image, which can be useful when bounding boxes and polygons do not provide enough precision, or when topologically separate regions belonging to the same class need to be labeled.
Upload Bitmask Labels to Encord
If there are pre-existing Bitmask annotations, previously created in Encord or any other software, they can be uploaded to Encord using the SDK. The following code example shows how to read a bitmask from a file, and upload it:
Decode Bitmask Labels
Bitmask labels exported from Encord are encoded in an rleString. This rleString can be converted to an image or a binary array.
Creating Bitmask Images from JSON Export
The script below must only be used to decode bitmasks that are exported in the JSON format.
The following script takes your exported JSON file, finds the rleString, and converts it into an image.
# Import dependencies
import json
from pathlib import Path
import numpy as np
from encord.objects.coordinates import BitmaskCoordinates
from PIL import Image
# Read the JSON file.
# Replace labels.json with the path to the JSON file containing your Bitmask
labels = json.loads(Path("labels.json").read_text())
output_folder = Path("output")
output_folder.mkdir(parents=True, exist_ok=True)
# Finds the rleString and saves it to a .png image
found_any = False
for label_row in labels:
for du in label_row["data_units"].values():
slice_nums = list(du["labels"].keys())
for slice_num in slice_nums:
for obj in du["labels"][slice_num]["objects"]:
bmc = BitmaskCoordinates.from_dict(obj)
nparr = np.array(bmc)
img = Image.fromarray(nparr)
# img.show()
# Replace example.png with the name of the output file
img.save(output_folder / f"mask_{int(slice_num):05d}_{obj['objectHash']}.png")
print("Decoding complete.")
Creating a Binary Array
The rleStringcan also be converted into an array of 1’s and 0’s using the script below.
from encord.objects.coordinates import BitmaskCoordinates
# Create a numpy array
np_mask = BitmaskCoordinates.from_dict(obj).to_numpy_array()
print(np_mask.astype(int))
Creating Bitmask Images from COCO Export
Use the COCO API to decode Bitmasks when using the COCO export format.
from pycocotools.coco import COCO
import numpy as np
from pycocotools import mask as maskUtils
from PIL import Image
import json
# Read the COCO file. Replace 'labels.json' with the path to your COCO format annotations file
coco_annotations_path = 'labels.json'
coco = COCO(coco_annotations_path)
# Get all annotation IDs (you might want to filter or select specific ones)
annIds = coco.getAnnIds()
anns = coco.loadAnns(annIds)
# Decode each rleString and save as a .png image
for i, ann in enumerate(anns):
if 'segmentation' in ann and isinstance(ann['segmentation'], dict):
rle = ann['segmentation']
mask = maskUtils.decode(rle)
img = Image.fromarray(mask * 255).convert('L') # Convert to grayscale
# Replace example.png with the name of the output file
img.save("example.png")
print("Decoding complete.")
Export Bitmasks
See our documentation on exporting Bitmasks here.