---
title: Panoptic Quality
description: Compute the Panoptic Quality for panoptic segmentations.
canonical: 'https://lightning.ai/docs/torchmetrics/stable/detection/panoptic_quality'
---
# Panoptic Quality {#panoptic-quality}

## Module Interface {#module-interface}

### `class torchmetrics.detection.PanopticQuality(things, stuffs, allow_unknown_preds_category=False, return_sq_and_rq=False, return_per_class=False, **kwargs)` {#torchmetrics.detection.PanopticQuality}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/detection/panoptic_qualities.py#L37-L290)

Compute the [Panoptic Quality](https://arxiv.org/abs/1801.00868) for panoptic segmentations.

```math
PQ = \frac{IOU}{TP + 0.5 FP + 0.5 FN}
```

where IOU, TP, FP and FN are respectively the sum of the intersection over union for true positives, the number of true positives, false positives and false negatives. This metric is inspired by the PQ implementation of panopticapi, a standard implementation for the PQ metric for panoptic segmentation.

As input to `forward` and `update` the metric accepts the following input:

*   `preds` ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")): An int tensor of shape `(B, *spatial_dims, 2)` containing the pair `(category_id, instance_id)` for each point, where there needs to be at least one spatial dimension.
    
*   `target` ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")): An int tensor of shape `(B, *spatial_dims, 2)` containing the pair `(category_id, instance_id)` for each point, where there needs to be at least one spatial dimension.
    

As output to `forward` and `compute` the metric returns the following output:

*   `quality` ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")): If `return_sq_and_rq=False` and `return_per_class=False` then a single scalar tensor is returned with average panoptic quality over all classes. If `return_sq_and_rq=True` and `return_per_class=False` a tensor of length 3 is returned with panoptic, segmentation and recognition quality (in that order). If If `return_sq_and_rq=False` and `return_per_class=True` a tensor of length equal to the number of classes are returned, with panoptic quality for each class. The order of classes is `things` first and then `stuffs`, and numerically sorted within each. (ex. with `things=[4, 1], stuffs=[3, 2]`, the output classes are ordered by `[1, 4, 2, 3]`) Finally, if both arguments are `True` a tensor of shape `(3, C)` is returned with individual panoptic, segmentation and recognition quality for each class.
    

Parameters:

*   **things** ([`Collection`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Collection "(in Python v3.15)")\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")\]) – Set of `category_id` for countable things.
    
*   **stuffs** ([`Collection`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Collection "(in Python v3.15)")\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")\]) – Set of `category_id` for uncountable stuffs.
    
*   **allow\_unknown\_preds\_category** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Boolean flag to specify if unknown categories in the predictions are to be ignored in the metric computation or raise an exception when found.
    
*   **return\_sq\_and\_rq** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Boolean flag to specify if Segmentation Quality and Recognition Quality should be also returned.
    
*   **return\_per\_class** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Boolean flag to specify if the per-class values should be returned or the class average.
    

Raises:

*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `things`, `stuffs` have at least one common `category_id`.
    
*   [**TypeError**](https://docs.python.org/3/builtins/exceptions.html#TypeError "(in Python v3.15)") – If `things`, `stuffs` contain non-integer `category_id`.
    

Example

```python
>>> from torch import tensor
>>> from torchmetrics.detection import PanopticQuality
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> panoptic_quality = PanopticQuality(things = {0, 1}, stuffs = {6, 7})
>>> panoptic_quality(preds, target)
tensor(0.5463, dtype=torch.float64)
```

You can also return the segmentation and recognition quality alognside the PQ

```python
>>> from torch import tensor
>>> from torchmetrics.detection import PanopticQuality
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> panoptic_quality = PanopticQuality(things = {0, 1}, stuffs = {6, 7}, return_sq_and_rq=True)
>>> panoptic_quality(preds, target)
tensor([0.5463, 0.6111, 0.6667], dtype=torch.float64)
```

You can also specify to return the per-class metrics

```python
>>> from torch import tensor
>>> from torchmetrics.detection import PanopticQuality
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> panoptic_quality = PanopticQuality(things = {0, 1}, stuffs = {6, 7}, return_per_class=True)
>>> panoptic_quality(preds, target)
tensor([[0.5185, 0.0000, 0.6667, 1.0000]], dtype=torch.float64)
```

#### `plot(val=None, ax=None)` {#torchmetrics.detection.PanopticQuality.plot}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/detection/panoptic_qualities.py#L231-L290)

Plot a single or multiple values from the metric.

Parameters:

*   **val** (`Union`\[[`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)"), [`Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence "(in Python v3.15)")\[[`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")\], [`None`](https://docs.python.org/3/builtins/constants.html#None "(in Python v3.15)")\]) – Either a single result from calling metric.forward or metric.compute or a list of these results. If no value is provided, will automatically call metric.compute and plot that result.
    
*   **ax** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional "(in Python v3.15)")\[[`Axes`](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html#matplotlib.axes.Axes "(in Matplotlib v3.11.2)")\]) – An matplotlib axis object. If provided will add plot to that axis
    

Return type:

[`tuple`](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")\[[`Figure`](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.html#matplotlib.figure.Figure "(in Matplotlib v3.11.2)"), `Union`\[[`Axes`](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html#matplotlib.axes.Axes "(in Matplotlib v3.11.2)"), [`ndarray`](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html#numpy.ndarray "(in NumPy v2.5)")\]\]

Returns:

Figure object and Axes object

Raises:

[**ModuleNotFoundError**](https://docs.python.org/3/builtins/exceptions.html#ModuleNotFoundError "(in Python v3.15)") – If matplotlib is not installed

```python
>>> from torch import tensor
>>> from torchmetrics.detection import PanopticQuality
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> metric = PanopticQuality(things = {0, 1}, stuffs = {6, 7})
>>> metric.update(preds, target)
>>> fig_, ax_ = metric.plot()
```

[![../../\_images/panoptic\_quality-1.png](/docs/torchmetrics/1.9.0/static/_images/panoptic_quality-1.png)](/docs/torchmetrics/1.9.0/static/_images/panoptic_quality-1.png)

```python
>>> # Example plotting multiple values
>>> from torch import tensor
>>> from torchmetrics.detection import PanopticQuality
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> metric = PanopticQuality(things = {0, 1}, stuffs = {6, 7})
>>> vals = []
>>> for _ in range(20):
...     vals.append(metric(preds, target))
>>> fig_, ax_ = metric.plot(vals)
```

[![../../\_images/panoptic\_quality-2.png](/docs/torchmetrics/1.9.0/static/_images/panoptic_quality-2.png)](/docs/torchmetrics/1.9.0/static/_images/panoptic_quality-2.png)

## Functional Interface {#functional-interface}

### `torchmetrics.functional.detection.panoptic_quality(preds, target, things, stuffs, allow_unknown_preds_category=False, return_sq_and_rq=False, return_per_class=False)` {#torchmetrics.functional.detection.panoptic_quality}

[\[source\]](https://github.com/Lightning-AI/torchmetrics/blob/v1.9.0/src/torchmetrics/functional/detection/panoptic_qualities.py#L30-L172)

Compute [Panoptic Quality](https://arxiv.org/abs/1801.00868) for panoptic segmentations.

```math
PQ = \frac{IOU}{TP + 0.5 FP + 0.5 FN}
```

where IOU, TP, FP and FN are respectively the sum of the intersection over union for true positives, the number of true positives, false positives and false negatives. This metric is inspired by the PQ implementation of panopticapi, a standard implementation for the PQ metric for object detection.

Parameters:

*   **preds** ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")) – torch tensor with panoptic detection of shape \[height, width, 2\] containing the pair (category\_id, instance\_id) for each pixel of the image. If the category\_id refer to a stuff, the instance\_id is ignored.
    
*   **target** ([`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")) – torch tensor with ground truth of shape \[height, width, 2\] containing the pair (category\_id, instance\_id) for each pixel of the image. If the category\_id refer to a stuff, the instance\_id is ignored.
    
*   **things** ([`Collection`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Collection "(in Python v3.15)")\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")\]) – Set of `category_id` for countable things.
    
*   **stuffs** ([`Collection`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Collection "(in Python v3.15)")\[[`int`](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")\]) – Set of `category_id` for uncountable stuffs.
    
*   **allow\_unknown\_preds\_category** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Boolean flag to specify if unknown categories in the predictions are to be ignored in the metric computation or raise an exception when found.
    
*   **return\_sq\_and\_rq** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Boolean flag to specify if Segmentation Quality and Recognition Quality should be also returned.
    
*   **return\_per\_class** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool "(in Python v3.15)")) – Boolean flag to specify if the per-class values should be returned or the class average.
    

Raises:

*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `things`, `stuffs` have at least one common `category_id`.
    
*   [**TypeError**](https://docs.python.org/3/builtins/exceptions.html#TypeError "(in Python v3.15)") – If `things`, `stuffs` contain non-integer `category_id`.
    
*   [**TypeError**](https://docs.python.org/3/builtins/exceptions.html#TypeError "(in Python v3.15)") – If `preds` or `target` is not an `torch.Tensor`.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `preds` or `target` has different shape.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `preds` has less than 3 dimensions.
    
*   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If the final dimension of `preds` has size != 2.
    

Return type:

[`Tensor`](https://docs.pytorch.org/docs/stable/tensors.html#torch.Tensor "(in PyTorch v2.15)")

Example

```python
>>> from torch import tensor
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> panoptic_quality(preds, target, things = {0, 1}, stuffs = {6, 7})
tensor(0.5463, dtype=torch.float64)
```

You can also return the segmentation and recognition quality alognside the PQ

```python
>>> from torch import tensor
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> panoptic_quality(preds, target, things = {0, 1}, stuffs = {6, 7}, return_sq_and_rq=True)
tensor([0.5463, 0.6111, 0.6667], dtype=torch.float64)
```

You can also specify to return the per-class metrics

```python
>>> from torch import tensor
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> panoptic_quality(preds, target, things = {0, 1}, stuffs = {6, 7}, return_per_class=True)
tensor([[0.5185, 0.0000, 0.6667, 1.0000]], dtype=torch.float64)
```

You can also specify to return the per-class metrics and the segmentation and recognition quality

```python
>>> from torch import tensor
>>> preds = tensor([[[[6, 0], [0, 0], [6, 0], [6, 0]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [0, 0], [6, 0], [0, 1]],
...                  [[0, 0], [7, 0], [6, 0], [1, 0]],
...                  [[0, 0], [7, 0], [7, 0], [7, 0]]]])
>>> target = tensor([[[[6, 0], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [0, 1]],
...                   [[0, 1], [0, 1], [6, 0], [1, 0]],
...                   [[0, 1], [7, 0], [1, 0], [1, 0]],
...                   [[0, 1], [7, 0], [7, 0], [7, 0]]]])
>>> panoptic_quality(preds, target, things = {0, 1}, stuffs = {6, 7},
...                  return_per_class=True, return_sq_and_rq=True)
tensor([[0.5185, 0.7778, 0.6667],
        [0.0000, 0.0000, 0.0000],
        [0.6667, 0.6667, 1.0000],
        [1.0000, 1.0000, 1.0000]], dtype=torch.float64)
```

---

**Navigation**

- Parent: [Detection](/docs/torchmetrics/1.9.0/detection.md)
