Overview

Creates ground-plane footprint visualization by drawing partial ellipses at the bottom center of each bounding box. The elliptical shape provides a natural representation of object presence on the ground plane, making it ideal for spatial awareness, shadow effects, and ground-based tracking visualizations.

Function Signature

oval(
    image: np.ndarray,
    detections: Detections,
    thickness: Optional[int] = None,
    start_angle: int = default,
    end_angle: int = 235,
    colors: Optional[List[Tuple[int, int, int]]] = None
) -> np.ndarray

Parameters

image
np.ndarray
required
Input image array with shape (H, W, 3) in BGR color format.
detections
Detections
required
PixelFlow detections object containing bounding boxes. Each detection must have a .bbox attribute with (x1, y1, x2, y2) coordinates.
thickness
Optional[int]
default:"None"
Line thickness for ellipse drawing in pixels. If None, automatically adapts based on image size (typically 1-4 pixels). Default is None.
start_angle
int
default:"default"
Starting angle of the ellipse arc in degrees. Range: -180 to 180. Default is -45 (bottom-left quadrant).
end_angle
int
default:"235"
Ending angle of the ellipse arc in degrees. Range: -180 to 360. Default is 235 (bottom-right, creating bottom arc spanning ~280 degrees).
colors
Optional[List[Tuple[int, int, int]]]
default:"None"
List of BGR color tuples (B, G, R) where each value is 0-255. Colors are mapped to unique class_ids in order of appearance. If None, uses default ColorManager colors.

Returns

result
np.ndarray
Image array with elliptical footprints drawn at the bottom center of each detected object. Original image is modified in-place.

Examples

import cv2
import pixelflow as pf
from ultralytics import YOLO

# Load image and model
image = cv2.imread("pedestrians.jpg")
model = YOLO("yolo11n.pt")
outputs = model.predict(image)
results = pf.results.from_ultralytics(outputs)

# Basic footprint annotation with adaptive sizing
annotated = pf.annotators.oval(image, results)

# Custom thickness and colors for specific visualization
custom_colors = [(0, 255, 255), (255, 0, 255), (255, 255, 0)]  # Cyan, Magenta, Yellow
annotated = pf.annotators.oval(image, results, thickness=3, colors=custom_colors)

# Full ellipse instead of bottom arc
full_ellipse = pf.annotators.oval(image, results, start_angle=0, end_angle=360)

# Narrow bottom arc for subtle ground indication
subtle_footprint = pf.annotators.oval(image, results, start_angle=30, end_angle=150)

Error Handling

This function may raise the following exceptions:
  • AssertionError: If image is not a numpy.ndarray.
  • AttributeError: If detections object doesn’t have required bbox attributes.
  • ValueError: If angle parameters are invalid or cause OpenCV drawing errors.

Notes

  • Ellipse width automatically matches the full width of each bounding box
  • Ellipse height is set to 25% of the width for natural ground-plane proportions
  • Center point is positioned at the bottom-center of each bounding box (x_center, y2)
  • Uses anti-aliased line drawing (cv2.LINE_AA) for smooth curves
  • Thickness automatically adapts to image resolution when not specified
  • Colors cycle through the provided list if there are more detections than colors
  • Angles follow OpenCV convention: 0° = right, 90° = down, 180° = left, 270° = up