Callbacks#

The image labeller implements a callback system that allows you to run arbitrary code whenever the displayed image changes or when an image has a label assigned.

# If in a notebook
%matplotlib ipympl
import matplotlib.pyplot as plt
import numpy as np

from mpl_image_labeller import image_labeller

images = np.random.randn(5, 10, 10)
labeller = image_labeller(images, classes=["good", "bad", "blarg"])


def image_changed_callback(index, image):
    print(index)
    print(image.sum())


def label_assigned(index, label):
    print(f"label {label} assigned to image {index}")


labeller.on_image_changed(image_changed_callback)
labeller.on_label_assigned(image_changed_callback)
plt.show()

Overlaying a mask#

One potential usage of this is to overlay a mask over the images which changes for each image. If the shape of image is changing then you will also need to adjust the extent of the overlay. If this is the case then uncomment the line in the update_mask function.

labeller = image_labeller(images, classes=["good", "bad", "blarg"])

mask_threshold = 0.6

from numpy.random import default_rng


def gen_mask(idx, image):
    # here we return a random mask - but you could base this on your data
    rng = default_rng(idx)
    mask = rng.random(image.shape)
    return mask > mask_threshold


overlay = labeller.ax.imshow(
    gen_mask(0, images[0]), cmap="gray", vmin=0, vmax=mask_threshold, alpha=0.75
)
cmap = overlay.cmap.copy()
cmap.set_over(alpha=0)
overlay.set_cmap(cmap)


def update_mask(idx, image):
    new_mask = gen_mask(idx, image)
    overlay.set_data(new_mask)

    # if your image is changing shape uncomment the next line
    # overlay.set_extent((-0.5, new_mask.shape[1] - 0.5, new_mask.shape[0] - 0.5, -0.5))


labeller.on_image_changed(update_mask)