Visualization Tools

This notebook illustrates the basic usage of the visualization package. We will visualize different annotation types for images (bounding boxes and object masks) and discuss the difference between the functional and module based api.

First, lets import some requirements

from __future__ import annotations

from vis4d.common.typing import NDArrayF64, NDArrayI64
from vis4d.vis.functional import imshow_bboxes, imshow_masks, imshow_topk_bboxes, imshow, draw_bboxes, draw_masks, imshow_track_matches

import pickle
import numpy as np
Jupyter environment detected. Enabling Open3D WebVisualizer.
[Open3D INFO] WebRTC GUI backend enabled.
[Open3D INFO] WebRTCWindowSystem: HTTP handshake server disabled.

Lets load some data to visualize

with open("data/draw_bbox_with_cts.pkl", "rb") as f:
    testcase_gt = pickle.load(f)

images: list[NDArrayF64] = testcase_gt["imgs"]
boxes: list[NDArrayF64] = testcase_gt["boxes"]
classes: list[NDArrayI64] = testcase_gt["classes"]
scores: list[NDArrayF64] = testcase_gt["scores"]
tracks = [np.arange(len(b)) for b in boxes]

print(f"Loaded {len(images)} Images with {[len(box) for box in boxes]} bounding boxes each")
Loaded 2 Images with [19, 14] bounding boxes each

Lets show the first image and respective bounding box annotations

The raw Image:

imshow(images[0])
../_images/279f855c4b71d3b682024b56f0d46bf84992b3245d05e736933d6912d63da1d3.png

The respective bounding box annotations

imshow_bboxes(images[0], boxes[0])
../_images/0782066a138351560292ef6e7b49b0737a33c03b63581a3aeec4e31a925cd54e.png

Lets show some additional informatiion as e.g. class id, track_id and scores

imshow_bboxes(images[0], boxes[0], class_ids = classes[0], scores = scores[0], track_ids = tracks[0])
../_images/51a23b751b52e7955d644082f1f091541f21f2bcf4007c795684b283bcf27e44.png

Note that the first number denotes the classs id, the second the track id and the last one the confidence score in %. We can map the class ids to names by providing a mapping to the visualization function

imshow_bboxes(images[0], boxes[0], class_ids = classes[0], scores = scores[0], track_ids = tracks[0], class_id_mapping = {1 : "Human", 51: "Pan"})
../_images/bdc5a66994a73eb35ea186831d3069b17e101a537b95dbbece9068004cfce676.png

Now lets only visualize the top 3 bounding boxes with highest score

imshow_topk_bboxes(images[0], boxes[0], topk = 3, class_ids = classes[0], scores = scores[0], track_ids = tracks[0], class_id_mapping = {1 : "Human", 51: "Pan"})
../_images/f3cd3dd959dba28fa916f11999cbc7ff96b7911b647fc1523aeb50983a9119f9.png

Segmentation Masks

Finally, lets also visualize some segmentation masks

with open("data/mask_data.pkl", "rb") as f:
    testcase_in = pickle.load(f)

    images = [e["img"] for e in testcase_in]
    masks = [np.stack(e["masks"]) for e in testcase_in]
    class_ids = [np.stack(e["class_id"]) for e in testcase_in]

print(f"Loaded {len(images)} with {[len(m) for m in masks]} masks each.")
Loaded 2 with [14, 19] masks each.
imshow_masks(images[1], masks[1], class_ids = class_ids[1])
../_images/e4acbbcb33163ad669334c4b32fca1cd4a886028cf79b540b2b2c46aff035868.png

Combine Masks and Bounding Boxes

We can also compose both visualization methods by using the draw functionality:

img = draw_masks(images[1], masks[1], class_ids = class_ids[1])
img = draw_bboxes(img, boxes[0], class_ids = classes[0], scores = scores[0], track_ids = tracks[0], class_id_mapping = {1 : "Human", 51: "Pan"})
imshow(img)
../_images/d36808857cd8d34777de908849f05b50a4419b91a530410cdb67132f93aeea85.png

Tracking Matches

Lets show matching bounding boxes one by one which were assigned by their track ids

with open("data/draw_bbox_with_cts.pkl", "rb") as f:
    testcase_gt = pickle.load(f)

images: list[NDArrayF64] = testcase_gt["imgs"]
boxes: list[NDArrayF64] = testcase_gt["boxes"]
classes: list[NDArrayI64] = testcase_gt["classes"]
scores: list[NDArrayF64] = testcase_gt["scores"]
tracks = [np.arange(len(b)) for b in boxes]

print(f"Loaded {len(images)} Images with {[len(box) for box in boxes]} bounding boxes each")
Loaded 2 Images with [19, 14] bounding boxes each
# Lets only assign the same track id to the first 4 boxes to keep visualizations down
tracks[0][4:] = 100
tracks[1][4:] = 101 
imshow_track_matches([images[0]], [images[1]], key_boxes = [boxes[0]], ref_boxes = [boxes[1]], key_track_ids=[tracks[0]], ref_track_ids=[tracks[1]])
../_images/e0ecb8bba29f51aea006ed58b08c8cf3fe55f560c6cc918a5c44ba4f596c3e49.png ../_images/4f3bdfcdee63d6190c80bc81ca254f5b5efc1a95a9963260292b3f0601348305.png ../_images/07144bbf2147351b3edd684461214485d32e9281305e5e4e384b5d9578db074a.png ../_images/842042acf5eed340a07d085501e31baa701d3cb8622183a92ef2028843eb64e1.png ../_images/fa63068414383c401840fab3fb1494ee0eb6087d7853889af2b0c5b5b7cbc77e.png ../_images/4a004613db49228c10f0d1897e0e9979ec8d568b62ddde9c182022ad79d6fa35.png ../_images/c521afabb3728458cee74dda923c7e1ee3a5f7ced66913b682555b9c71299eb2.png ../_images/d2853d1163e477f2f0e7486a34a2037fd036fca5e13882ea55435d037a231cc9.png