Hi @nw26 !
def get_masks(data_row_id, basepath):
# get the mask names based on the dataframe column image_id
annotations = df[df['image_id'] == data_row_id].to_dict('records')
# get the mask paths
mask_names = [an['mask_id'] for an in annotations]
mask_paths = [os.path.join(basepath, f'masks/{mn}.png') for mn in mask_names]
mask_paths = [os.path.normpath(mp) for mp in mask_paths]
# load the masks
masks = [cv2.imread(mp, -1) for mp in mask_paths]
# return the mask id and the mask as a dictionary
return dict(zip(mask_names, masks))
def create_labelbox_masks(mask_dict, class_color_dict):
labelbox_masks = []
for mask_id, mask in mask_dict.items():
mask_data = lb_types.MaskData.from_2D_arr(mask)
# create a labelbox mask object
cls = df[df['mask_id'] == mask_id].class_name.values[0]
labelbox_mask = lb_types.ObjectAnnotation(
name=name_mapping[cls],
value=lb_types.Mask(mask=mask_data,
color=class_color_dict[cls]),
)
labelbox_masks.append(labelbox_mask)
return labelbox_masks
That is the function for preparing the labelbox mask objects; I used the functions like:
for dr in tqdm(data_rows[1:]):
global_key = dr.global_key
# get the masks for the data row
mask_dict = get_masks(global_key, basepath)
# create labelbox masks
labelbox_masks = create_labelbox_masks(mask_dict, class_color_dict)
labels = list()
labels.append(
lb_types.Label(data=lb_types.ImageData(global_key=global_key),
annotations=labelbox_masks))
try:
# Upload label for this data row in project
upload_job = lb.LabelImport.create_from_objects(
client = client,
project_id = ps.uid,
name="label_import_job"+str(uuid.uuid4()),
labels=labels)
except:
print(f"Errors: {upload_job.errors}", )
print(f"Status of uploads: {upload_job.statuses}")
The label object ends up being something like:
[Label(uid=None, data=ImageData(im_bytes=None,file_path=None,url=None,arr=None), annotations=[ObjectAnnotation(confidence=None, name='normal', feature_schema_id=None, extra={}, value=Mask(extra={}, mask=MaskData(im_bytes=None,file_path=None,url=None,arr=...), color=(0, 255, 0)), classifications=[]), ObjectAnnotation(confidence=None, name='normal', feature_schema_id=None, extra={}, value=Mask(extra={}, mask=MaskData(im_bytes=None,file_path=None,url=None,arr=...), color=(0, 255, 0)), classifications=[]), ObjectAnnotation(confidence=None, name='normal', feature_schema_id=None, extra={}, value=Mask(extra={}, mask=MaskData(im_bytes=None,file_path=None,url=None,arr=...), color=(0, 255, 0)), classifications=[])], extra={})]
Hope that helps.
You should be able to unpack the upload job errors to try and understand what the âimport failedâ error is about.
One âgotchaâ I had is that the color argument specified in the ObjectAnnotation object, is what filters the mask object;
e.g. if your mask is [1, 1, 1], and your color [2, 2, 2], the mask will get recognized as empty.
So, the âcolorâ argument is not what determines the actual color in the labelbox UI (this is done via the ontology), it is more of a filter for your mask object.
I didnât understand this straight away and I donât really see it well documented anywhere.
I did update the labelbox python package but I didnât yet try to import masks from s3;
if that ends up still being impossible, it will be potentially a major annoyance but iâm sure we can work around it - @labelbox team.