Evaluating Segmentations#

Available in: Open SourceEnterprise

You can use the evaluate_segmentations() method to evaluate the predictions of a semantic segmentation model stored in a Segmentation field of your dataset.

By default, the full segmentation masks will be evaluated at a pixel level, but you can specify other evaluation strategies such as evaluating only boundary pixels (see below for details).

Invoking evaluate_segmentations() returns a SegmentationResults instance that provides a variety of methods for generating various aggregate evaluation reports about your model.

In addition, when you specify an eval_key parameter, a number of helpful fields will be populated on each sample that you can leverage via the FiftyOne App to interactively explore the strengths and weaknesses of your model on individual samples.

Note

You can store mask targets for your Segmentation fields on your dataset so that you can view semantic labels in the App and avoid having to manually specify the set of mask targets each time you run evaluate_segmentations() on a dataset.

Simple evaluation (default)#

By default, evaluate_segmentations() will perform pixelwise evaluation of the segmentation masks, treating each pixel as a multiclass classification.

Here are some things to keep in mind:

  • If the size of a predicted mask does not match the ground truth mask, it is resized to match the ground truth.

  • You can specify the optional bandwidth parameter to evaluate only along the contours of the ground truth masks. By default, the entire masks are evaluated.

You can explicitly request that this strategy be used by setting the method parameter to "simple".

When you specify an eval_key parameter, the accuracy, precision, and recall of each sample is recorded in top-level fields of each sample:

 Accuracy: sample.<eval_key>_accuracy
Precision: sample.<eval_key>_precision
   Recall: sample.<eval_key>_recall

Note

The mask values 0 and #000000 are treated as a background class for the purposes of computing evaluation metrics like precision and recall.

The example below demonstrates segmentation evaluation by comparing the masks generated by two DeepLabv3 models (with ResNet50 and ResNet101 backbones):

 1import fiftyone as fo
 2import fiftyone.zoo as foz
 3
 4# Load a few samples from COCO-2017
 5dataset = foz.load_zoo_dataset(
 6    "quickstart",
 7    dataset_name="segmentation-eval-demo",
 8    max_samples=10,
 9    shuffle=True,
10)
11
12# The models are trained on the VOC classes
13CLASSES = (
14    "background,aeroplane,bicycle,bird,boat,bottle,bus,car,cat,chair,cow," +
15    "diningtable,dog,horse,motorbike,person,pottedplant,sheep,sofa,train," +
16    "tvmonitor"
17)
18dataset.default_mask_targets = {
19    idx: label for idx, label in enumerate(CLASSES.split(","))
20}
21
22# Add DeepLabv3-ResNet101 predictions to dataset
23model = foz.load_zoo_model("deeplabv3-resnet101-coco-torch")
24dataset.apply_model(model, "resnet101")
25
26# Add DeepLabv3-ResNet50 predictions to dataset
27model = foz.load_zoo_model("deeplabv3-resnet50-coco-torch")
28dataset.apply_model(model, "resnet50")
29
30print(dataset)
31
32# Evaluate the masks w/ ResNet50 backbone, treating the masks w/ ResNet101
33# backbone as "ground truth"
34results = dataset.evaluate_segmentations(
35    "resnet50",
36    gt_field="resnet101",
37    eval_key="eval_simple",
38)
39
40# Get a sense for the per-sample variation in likeness
41print("Accuracy range: (%f, %f)" % dataset.bounds("eval_simple_accuracy"))
42print("Precision range: (%f, %f)" % dataset.bounds("eval_simple_precision"))
43print("Recall range: (%f, %f)" % dataset.bounds("eval_simple_recall"))
44
45# Print a classification report
46results.print_report()
47
48# Visualize results in the App
49session = fo.launch_app(dataset)
evaluate-segmentations

Note

The easiest way to analyze models in FiftyOne is via the Model Evaluation panel!