# Visualizing results

*Estimated read time: 3 minutes*

Visualization centers on three attributes: `result.image` (original frame), `result.image_model` (model-preprocessed frame), and `result.image_overlay` (annotated output). This page shows how to preview each field and tune overlay options. Each example includes inline setup so you can copy and run sections independently.

## Preview overlays quickly

`Display` provides a windowed or inline preview, depending on your runtime. It accepts NumPy arrays in BGR order.

### Example

{% code overflow="wrap" %}

```python
from degirum_tools import ModelSpec, Display, remote_assets

model_spec = ModelSpec(
    model_name="yolov8n_coco--640x640_quant_axelera_metis_1",
    zoo_url="degirum/axelera",
    inference_host_address="@local",
    model_properties={"device_type": ["AXELERA/METIS"]},
)
model = model_spec.load_model()

result = model(remote_assets.three_persons)

with Display("AI Camera — Overlay preview") as output_display:
    output_display.show_image(result.image_overlay)
    print("Rendered overlay — close the display window to exit")
```

{% endcode %}

Example output:

{% code overflow="wrap" %}

```python
Rendered overlay — close the display window to exit
```

{% endcode %}

{% hint style="info" %}
Need to inspect multiple frames? Loop over a generator such as `degirum_tools.predict_stream` and call `show` inside the loop.
{% endhint %}

## Compare original and overlay frames

Use OpenCV to convert NumPy arrays into PNGs for before/after comparisons or debugging postprocessing.

### Example

{% code overflow="wrap" %}

```python
from pathlib import Path
import cv2
from degirum_tools import ModelSpec, remote_assets

model_spec = ModelSpec(
    model_name="yolov8n_coco--640x640_quant_axelera_metis_1",
    zoo_url="degirum/axelera",
    inference_host_address="@local",
    model_properties={"device_type": ["AXELERA/METIS"]},
)
model = model_spec.load_model()

result = model(remote_assets.three_persons)

output_dir = Path("visualization-frames")
output_dir.mkdir(parents=True, exist_ok=True)

cv2.imwrite(str(output_dir / "original-frame.png"), result.image)
cv2.imwrite(str(output_dir / "overlay-frame.png"), result.image_overlay)

if result.image_model is not None:
    cv2.imwrite(str(output_dir / "model-input.png"), result.image_model)

print(f"Saved frames in {output_dir.resolve()}")
```

{% endcode %}

Example output:

{% code overflow="wrap" %}

```python
Saved frames in /home/user/project/visualization-frames
```

{% endcode %}

{% hint style="info" %}
Guard against `result.image_model` being `None` before attempting to save it—some models do not expose the model-ready tensor.
{% endhint %}

## Adjust overlay styling via ModelSpec

You can set overlay properties when you build the `ModelSpec`. Pass the overlay fields you need alongside the device configuration.

### Example

{% code overflow="wrap" %}

```python
from degirum_tools import ModelSpec, remote_assets

model_spec = ModelSpec(
    model_name="yolov8n_coco--640x640_quant_axelera_metis_1",
    zoo_url="degirum/axelera",
    inference_host_address="@local",
    model_properties={
        "device_type": ["AXELERA/METIS"],
        "overlay_show_labels": True,
        "overlay_show_probabilities": True,
        "overlay_line_width": 2,
        "overlay_color": [(0, 255, 0)],
    },
)
model = model_spec.load_model()

result = model(remote_assets.three_persons)
print(f"Overlay generated with {len(result.results)} detections")
```

{% endcode %}

Example output:

{% code overflow="wrap" %}

```python
Overlay generated with 3 detections
```

{% endcode %}

{% hint style="info" %}
Need to hide overlays entirely? Set the corresponding flags to `False` (e.g., `"overlay_show_labels": False`).
{% endhint %}
